diff options
Diffstat (limited to 'dynamic-layers/meta-perl/recipes-security')
25 files changed, 9216 insertions, 0 deletions
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/bastille_3.2.1.bb b/dynamic-layers/meta-perl/recipes-security/bastille/bastille_3.2.1.bb new file mode 100644 index 0000000..e7852d9 --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/bastille_3.2.1.bb | |||
| @@ -0,0 +1,166 @@ | |||
| 1 | #The functionality of Bastille that is actually available is restricted. Please | ||
| 2 | #consult the README file for the meta-security layer for additional information. | ||
| 3 | SUMMARY = "Linux hardening tool" | ||
| 4 | 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." | ||
| 5 | LICENSE = "GPL-2.0-only" | ||
| 6 | LIC_FILES_CHKSUM = "file://${S}/COPYING;md5=c93c0550bd3173f4504b2cbd8991e50b" | ||
| 7 | # Bash is needed for set +o privileged (check busybox), might also need ncurses | ||
| 8 | DEPENDS = "virtual/kernel" | ||
| 9 | 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" | ||
| 10 | FILES:${PN} += "/run/lock/subsys/bastille" | ||
| 11 | |||
| 12 | SRC_URI = "http://sourceforge.net/projects/bastille-linux/files/bastille-linux/3.2.1/Bastille-3.2.1.tar.bz2 \ | ||
| 13 | file://AccountPermission.pm \ | ||
| 14 | file://FileContent.pm \ | ||
| 15 | file://HPSpecific.pm \ | ||
| 16 | file://Miscellaneous.pm \ | ||
| 17 | file://ServiceAdmin.pm \ | ||
| 18 | file://config \ | ||
| 19 | file://fix_version_parse.patch \ | ||
| 20 | file://fixed_defined_warnings.patch \ | ||
| 21 | file://call_output_config.patch \ | ||
| 22 | file://fix_missing_use_directives.patch \ | ||
| 23 | file://fix_number_of_modules.patch \ | ||
| 24 | file://remove_questions_text_file_references.patch \ | ||
| 25 | file://simplify_B_place.patch \ | ||
| 26 | file://find_existing_config.patch \ | ||
| 27 | file://upgrade_options_processing.patch \ | ||
| 28 | file://accept_os_flag_in_backend.patch \ | ||
| 29 | file://allow_os_with_assess.patch \ | ||
| 30 | file://edit_usage_message.patch \ | ||
| 31 | file://organize_distro_discovery.patch \ | ||
| 32 | file://do_not_apply_config.patch \ | ||
| 33 | " | ||
| 34 | |||
| 35 | SRC_URI[md5sum] = "df803f7e38085aa5da79f85d0539f91b" | ||
| 36 | SRC_URI[sha256sum] = "0ea25191b1dc1c8f91e1b6f8cb5436a3aa1e57418809ef902293448efed5021a" | ||
| 37 | |||
| 38 | S = "${WORKDIR}/Bastille" | ||
| 39 | |||
| 40 | do_install () { | ||
| 41 | install -d ${D}${sbindir} | ||
| 42 | install -d ${D}${libdir}/perl5/site_perl/Curses | ||
| 43 | |||
| 44 | install -d ${D}${libdir}/Bastille | ||
| 45 | install -d ${D}${libdir}/Bastille/API | ||
| 46 | install -d ${D}${datadir}/Bastille | ||
| 47 | install -d ${D}${datadir}/Bastille/OSMap | ||
| 48 | install -d ${D}${datadir}/Bastille/OSMap/Modules | ||
| 49 | install -d ${D}${datadir}/Bastille/Questions | ||
| 50 | install -d ${D}${datadir}/Bastille/FKL/configs/ | ||
| 51 | install -d ${D}${sysconfdir}/Bastille | ||
| 52 | install -m 0755 AutomatedBastille ${D}${sbindir} | ||
| 53 | install -m 0755 BastilleBackEnd ${D}${sbindir} | ||
| 54 | install -m 0755 InteractiveBastille ${D}${sbindir} | ||
| 55 | install -m 0644 Modules.txt ${D}${datadir}/Bastille | ||
| 56 | # New Weights file(s). | ||
| 57 | install -m 0644 Weights.txt ${D}${datadir}/Bastille | ||
| 58 | # Castle graphic | ||
| 59 | install -m 0644 bastille.jpg ${D}${datadir}/Bastille/ | ||
| 60 | # Javascript file | ||
| 61 | install -m 0644 wz_tooltip.js ${D}${datadir}/Bastille/ | ||
| 62 | install -m 0644 Credits ${D}${datadir}/Bastille | ||
| 63 | install -m 0644 FKL/configs/fkl_config_redhat.cfg ${D}${datadir}/Bastille/FKL/configs/ | ||
| 64 | install -m 0755 RevertBastille ${D}${sbindir} | ||
| 65 | install -m 0755 bin/bastille ${D}${sbindir} | ||
| 66 | install -m 0644 bastille-firewall ${D}${datadir}/Bastille | ||
| 67 | install -m 0644 bastille-firewall-reset ${D}${datadir}/Bastille | ||
| 68 | install -m 0644 bastille-firewall-schedule ${D}${datadir}/Bastille | ||
| 69 | install -m 0644 bastille-tmpdir-defense.sh ${D}${datadir}/Bastille | ||
| 70 | install -m 0644 bastille-tmpdir.csh ${D}${datadir}/Bastille | ||
| 71 | install -m 0644 bastille-tmpdir.sh ${D}${datadir}/Bastille | ||
| 72 | install -m 0644 bastille-firewall.cfg ${D}${datadir}/Bastille | ||
| 73 | install -m 0644 bastille-ipchains ${D}${datadir}/Bastille | ||
| 74 | install -m 0644 bastille-netfilter ${D}${datadir}/Bastille | ||
| 75 | install -m 0644 bastille-firewall-early.sh ${D}${datadir}/Bastille | ||
| 76 | install -m 0644 bastille-firewall-pre-audit.sh ${D}${datadir}/Bastille | ||
| 77 | install -m 0644 complete.xbm ${D}${datadir}/Bastille | ||
| 78 | install -m 0644 incomplete.xbm ${D}${datadir}/Bastille | ||
| 79 | install -m 0644 disabled.xpm ${D}${datadir}/Bastille | ||
| 80 | install -m 0644 ifup-local ${D}${datadir}/Bastille | ||
| 81 | install -m 0644 hosts.allow ${D}${datadir}/Bastille | ||
| 82 | |||
| 83 | install -m 0644 Bastille/AccountSecurity.pm ${D}${libdir}/Bastille | ||
| 84 | install -m 0644 Bastille/Apache.pm ${D}${libdir}/Bastille | ||
| 85 | install -m 0644 Bastille/API.pm ${D}${libdir}/Bastille | ||
| 86 | install -m 0644 ${WORKDIR}/AccountPermission.pm ${D}${libdir}/Bastille/API | ||
| 87 | install -m 0644 ${WORKDIR}/FileContent.pm ${D}${libdir}/Bastille/API | ||
| 88 | install -m 0644 ${WORKDIR}/HPSpecific.pm ${D}${libdir}/Bastille/API | ||
| 89 | install -m 0644 ${WORKDIR}/ServiceAdmin.pm ${D}${libdir}/Bastille/API | ||
| 90 | install -m 0644 ${WORKDIR}/Miscellaneous.pm ${D}${libdir}/Bastille/API | ||
| 91 | install -m 0644 Bastille/BootSecurity.pm ${D}${libdir}/Bastille | ||
| 92 | install -m 0644 Bastille/ConfigureMiscPAM.pm ${D}${libdir}/Bastille | ||
| 93 | install -m 0644 Bastille/DisableUserTools.pm ${D}${libdir}/Bastille | ||
| 94 | install -m 0644 Bastille/DNS.pm ${D}${libdir}/Bastille | ||
| 95 | install -m 0644 Bastille/FilePermissions.pm ${D}${libdir}/Bastille | ||
| 96 | install -m 0644 Bastille/FTP.pm ${D}${libdir}/Bastille | ||
| 97 | install -m 0644 Bastille/Firewall.pm ${D}${libdir}/Bastille | ||
| 98 | install -m 0644 Bastille/OSX_API.pm ${D}${libdir}/Bastille | ||
| 99 | install -m 0644 Bastille/LogAPI.pm ${D}${libdir}/Bastille | ||
| 100 | install -m 0644 Bastille/HP_UX.pm ${D}${libdir}/Bastille | ||
| 101 | install -m 0644 Bastille/IOLoader.pm ${D}${libdir}/Bastille | ||
| 102 | install -m 0644 Bastille/Patches.pm ${D}${libdir}/Bastille | ||
| 103 | install -m 0644 Bastille/Logging.pm ${D}${libdir}/Bastille | ||
| 104 | install -m 0644 Bastille/MiscellaneousDaemons.pm ${D}${libdir}/Bastille | ||
| 105 | install -m 0644 Bastille/PatchDownload.pm ${D}${libdir}/Bastille | ||
| 106 | install -m 0644 Bastille/Printing.pm ${D}${libdir}/Bastille | ||
| 107 | install -m 0644 Bastille/PSAD.pm ${D}${libdir}/Bastille | ||
| 108 | install -m 0644 Bastille/RemoteAccess.pm ${D}${libdir}/Bastille | ||
| 109 | install -m 0644 Bastille/SecureInetd.pm ${D}${libdir}/Bastille | ||
| 110 | install -m 0644 Bastille/Sendmail.pm ${D}${libdir}/Bastille | ||
| 111 | install -m 0644 Bastille/TestDriver.pm ${D}${libdir}/Bastille | ||
| 112 | install -m 0644 Bastille/TMPDIR.pm ${D}${libdir}/Bastille | ||
| 113 | install -m 0644 Bastille/test_AccountSecurity.pm ${D}${libdir}/Bastille | ||
| 114 | install -m 0644 Bastille/test_Apache.pm ${D}${libdir}/Bastille | ||
| 115 | install -m 0644 Bastille/test_DNS.pm ${D}${libdir}/Bastille | ||
| 116 | install -m 0644 Bastille/test_FTP.pm ${D}${libdir}/Bastille | ||
| 117 | install -m 0644 Bastille/test_HP_UX.pm ${D}${libdir}/Bastille | ||
| 118 | install -m 0644 Bastille/test_MiscellaneousDaemons.pm ${D}${libdir}/Bastille | ||
| 119 | install -m 0644 Bastille/test_Patches.pm ${D}${libdir}/Bastille | ||
| 120 | install -m 0644 Bastille/test_SecureInetd.pm ${D}${libdir}/Bastille | ||
| 121 | install -m 0644 Bastille/test_Sendmail.pm ${D}${libdir}/Bastille | ||
| 122 | install -m 0644 Bastille/test_BootSecurity.pm ${D}${libdir}/Bastille | ||
| 123 | install -m 0644 Bastille/test_DisableUserTools.pm ${D}${libdir}/Bastille | ||
| 124 | install -m 0644 Bastille/test_FilePermissions.pm ${D}${libdir}/Bastille | ||
| 125 | install -m 0644 Bastille/test_Logging.pm ${D}${libdir}/Bastille | ||
| 126 | install -m 0644 Bastille/test_Printing.pm ${D}${libdir}/Bastille | ||
| 127 | install -m 0644 Bastille/IPFilter.pm ${D}${libdir}/Bastille | ||
| 128 | install -m 0644 Bastille_Curses.pm ${D}${libdir}/perl5/site_perl | ||
| 129 | install -m 0644 Bastille_Tk.pm ${D}${libdir}/perl5/site_perl | ||
| 130 | install -m 0644 Curses/Widgets.pm ${D}${libdir}/perl5/site_perl/Curses | ||
| 131 | |||
| 132 | install -m 0644 OSMap/LINUX.bastille ${D}${datadir}/Bastille/OSMap | ||
| 133 | install -m 0644 OSMap/LINUX.system ${D}${datadir}/Bastille/OSMap | ||
| 134 | install -m 0644 OSMap/LINUX.service ${D}${datadir}/Bastille/OSMap | ||
| 135 | install -m 0644 OSMap/HP-UX.bastille ${D}${datadir}/Bastille/OSMap | ||
| 136 | install -m 0644 OSMap/HP-UX.system ${D}${datadir}/Bastille/OSMap | ||
| 137 | install -m 0644 OSMap/HP-UX.service ${D}${datadir}/Bastille/OSMap | ||
| 138 | install -m 0644 OSMap/OSX.bastille ${D}${datadir}/Bastille/OSMap | ||
| 139 | install -m 0644 OSMap/OSX.system ${D}${datadir}/Bastille/OSMap | ||
| 140 | |||
| 141 | install -m 0777 ${WORKDIR}/config ${D}${sysconfdir}/Bastille/config | ||
| 142 | |||
| 143 | for file in `cat Modules.txt` ; do | ||
| 144 | install -m 0644 Questions/$file.txt ${D}${datadir}/Bastille/Questions | ||
| 145 | done | ||
| 146 | |||
| 147 | ${THISDIR}/files/set_required_questions.py ${D}${sysconfdir}/Bastille/config ${D}${datadir}/Bastille/Questions | ||
| 148 | |||
| 149 | ln -s RevertBastille ${D}${sbindir}/UndoBastille | ||
| 150 | |||
| 151 | # Create /var/log/Bastille in runtime. | ||
| 152 | if [ "${@bb.utils.filter('DISTRO_FEATURES', 'systemd', d)}" ]; then | ||
| 153 | install -d ${D}${nonarch_libdir}/tmpfiles.d | ||
| 154 | echo "d ${localstatedir}/log/Bastille - - - -" > ${D}${nonarch_libdir}/tmpfiles.d/Bastille.conf | ||
| 155 | fi | ||
| 156 | if [ "${@bb.utils.filter('DISTRO_FEATURES', 'sysvinit', d)}" ]; then | ||
| 157 | install -d ${D}${sysconfdir}/default/volatiles | ||
| 158 | echo "d root root 0755 ${localstatedir}/log/Bastille none" > ${D}${sysconfdir}/default/volatiles/99_Bastille | ||
| 159 | fi | ||
| 160 | } | ||
| 161 | |||
| 162 | FILES:${PN} += "${datadir}/Bastille \ | ||
| 163 | ${libdir}/Bastille \ | ||
| 164 | ${libdir}/perl* \ | ||
| 165 | ${sysconfdir}/* \ | ||
| 166 | ${nonarch_libdir}/tmpfiles.d" | ||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/API.pm b/dynamic-layers/meta-perl/recipes-security/bastille/files/API.pm new file mode 100644 index 0000000..5060f52 --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/API.pm | |||
| @@ -0,0 +1,2528 @@ | |||
| 1 | # Copyright (C) 1999-2007 Jay Beale | ||
| 2 | # Copyright (C) 2001-2008 Hewlett-Packard Development Company, L.P. | ||
| 3 | # Licensed under the GNU General Public License, version 2 | ||
| 4 | |||
| 5 | package Bastille::API; | ||
| 6 | |||
| 7 | ## TO DO: | ||
| 8 | # | ||
| 9 | # | ||
| 10 | # 1) Look for more places to insert error handling... | ||
| 11 | # | ||
| 12 | # 2) Document this module more | ||
| 13 | # | ||
| 14 | # | ||
| 15 | |||
| 16 | |||
| 17 | ########################################################################## | ||
| 18 | # | ||
| 19 | # This module forms the basis for the v1.1 API. | ||
| 20 | # | ||
| 21 | ########################################################################## | ||
| 22 | |||
| 23 | # | ||
| 24 | # This module forms the initial basis for the Bastille Engine, implemented | ||
| 25 | # presently via a Perl API for Perl modules. | ||
| 26 | # | ||
| 27 | # This is still under construction -- it is very usable, but not very well | ||
| 28 | # documented, yet. | ||
| 29 | # | ||
| 30 | |||
| 31 | ########################################################################## | ||
| 32 | # | ||
| 33 | # API Function Listing | ||
| 34 | # | ||
| 35 | ########################################################################## | ||
| 36 | # The routines which should be called by Bastille modules are listed here, | ||
| 37 | # though they are better documented throughout this file. | ||
| 38 | # | ||
| 39 | # Distro Specific Stuff: | ||
| 40 | # | ||
| 41 | # &GetDistro - figures out what distro we're running, if it knows it... | ||
| 42 | # &ConfigureForDistro - sets global variables based on the distro | ||
| 43 | # &GetGlobal - returns hash values defined in ConfigureForDistro | ||
| 44 | # | ||
| 45 | # &getGlobalConfig - returns value of hash set up by ReadConfig | ||
| 46 | # | ||
| 47 | # Logging Specific Stuff has moved to LogAPI.pm: | ||
| 48 | # | ||
| 49 | # &B_log(type,msg) -- takes care of all logging | ||
| 50 | # | ||
| 51 | # | ||
| 52 | # Input functions for the old input method... | ||
| 53 | # | ||
| 54 | # File open/close/backup functions | ||
| 55 | # | ||
| 56 | # &B_open * -- opens a file handle and logs the action/error (OLD WAY!) | ||
| 57 | # &B_open_plus -- opens a pair of file handles for the old and new version | ||
| 58 | # of a file; respects logonly flag. (NEW WAY) | ||
| 59 | # &B_close * -- closes a file handle and logs the action/error (OLD WAY!) | ||
| 60 | # &B_close_plus -- closes a pair of file handles opened by B_open_plus, | ||
| 61 | # backing up one file and renaming the new file to the | ||
| 62 | # old one's name, logging actions/errors. Respects the | ||
| 63 | # logonly flag -- needs B_backup file. Finally, sets | ||
| 64 | # new file's mode,uid,gid to old file's... (NEW WAY) | ||
| 65 | # &B_backup_file - backs up a file that is being changed/deleted into the | ||
| 66 | # $GLOBAL_BDIR{"backup"} directory. | ||
| 67 | # | ||
| 68 | # Non-content file modification functions | ||
| 69 | # | ||
| 70 | # &B_delete_file - deletes the named file, backing up a copy | ||
| 71 | # &B_create_file - creates the named file, if it doesn't exist | ||
| 72 | # | ||
| 73 | # &B_symlink - create a symlink to a file, recording the revert rm | ||
| 74 | # | ||
| 75 | # More stuff | ||
| 76 | # | ||
| 77 | # &B_createdir - make a directory, if it doesn't exist, record revert rmdir | ||
| 78 | # &B_cp - copy a file, respecting LOGONLY and revert func. | ||
| 79 | # &B_mknod - wrap mknod with revert and logonly and prefix functionality | ||
| 80 | # | ||
| 81 | # &B_read_sums - reads sum.csv file and parses input into the GLOBAL_SUM hash | ||
| 82 | # &B_write_sums - writes sum.csv file from GLOBAL_SUM hash | ||
| 83 | # &B_check_sum($) - take a file name and compares the stored cksum with the current | ||
| 84 | # cksum of said file | ||
| 85 | # &B_set_sum($) - takes a file name and gets that files current cksum then sets | ||
| 86 | # that sum in the GLOBAL_SUM hash | ||
| 87 | # &B_revert_log - create entry in shell script, executed later by bastille -r | ||
| 88 | # &showDisclaimer - Print the disclaimer and wait for 5 minutes for acceptance | ||
| 89 | ########################################################################### | ||
| 90 | # Note: GLOBAL_VERBOSE | ||
| 91 | # | ||
| 92 | # All logging functions now check GLOBAL_VERBOSE and, if set, will print | ||
| 93 | # all the information sent to log files to STDOUT/STDERR as well. | ||
| 94 | # | ||
| 95 | |||
| 96 | # | ||
| 97 | # Note: GLOBAL_LOGONLY | ||
| 98 | # | ||
| 99 | # All Bastille API functions now check for the existence of a GLOBAL_LOGONLY | ||
| 100 | # variable. When said variable is set, no function actually modifies the | ||
| 101 | # system. | ||
| 102 | # | ||
| 103 | # Note: GLOBAL_DEBUG | ||
| 104 | # | ||
| 105 | # The B_log("DEBUG",...) function now checks GLOBAL_DEBUG and, if set, it will | ||
| 106 | # print all the information to a new debug-log file. If GLOBAL_VERBOSE is | ||
| 107 | # set it might log to STDOUT/STDERR as well (not yet implemented, pending | ||
| 108 | # discussion). Developers should populate appropriate places with &B_log(DEBUG) | ||
| 109 | # in order to be able to tell users to use this options and send the logs | ||
| 110 | # for inspection and debugging. | ||
| 111 | # | ||
| 112 | # | ||
| 113 | |||
| 114 | |||
| 115 | # Libraries for the Backup_file routine: Cwd and File::Path | ||
| 116 | use Cwd; | ||
| 117 | use Bastille::OSX_API; | ||
| 118 | use Bastille::LogAPI; | ||
| 119 | use File::Path; | ||
| 120 | use File::Basename; | ||
| 121 | |||
| 122 | # Export the API functions listed below for use by the modules. | ||
| 123 | |||
| 124 | use Exporter; | ||
| 125 | @ISA = qw ( Exporter ); | ||
| 126 | @EXPORT = qw( | ||
| 127 | setOptions GetDistro ConfigureForDistro B_log B_revert_log | ||
| 128 | SanitizeEnv | ||
| 129 | B_open B_close B_symlink StopLogging | ||
| 130 | B_open_plus B_close_plus | ||
| 131 | B_isFileinSumDB | ||
| 132 | B_create_file B_read_sums B_check_sum B_set_sum isSumDifferent listModifiedFiles | ||
| 133 | B_create_dir B_create_log_file | ||
| 134 | B_delete_file | ||
| 135 | B_cp B_place B_mknod | ||
| 136 | showDisclaimer | ||
| 137 | getSupportedOSHash | ||
| 138 | B_Backtick | ||
| 139 | B_System | ||
| 140 | isProcessRunning | ||
| 141 | checkProcsForService | ||
| 142 | |||
| 143 | |||
| 144 | $GLOBAL_OS $GLOBAL_ACTUAL_OS $CLI | ||
| 145 | $GLOBAL_LOGONLY $GLOBAL_VERBOSE $GLOBAL_DEBUG $GLOBAL_AUDITONLY $GLOBAL_AUDIT_NO_BROWSER $errorFlag | ||
| 146 | %GLOBAL_BIN %GLOBAL_DIR %GLOBAL_FILE | ||
| 147 | %GLOBAL_BDIR %GLOBAL_BFILE | ||
| 148 | %GLOBAL_CONFIG %GLOBAL_SUM | ||
| 149 | |||
| 150 | %GLOBAL_SERVICE %GLOBAL_SERVTYPE %GLOBAL_PROCESS %GLOBAL_RC_CONFIG | ||
| 151 | %GLOBAL_TEST | ||
| 152 | |||
| 153 | getGlobal setGlobal getGlobalConfig | ||
| 154 | |||
| 155 | |||
| 156 | B_parse_fstab | ||
| 157 | B_parse_mtab B_is_rpm_up_to_date | ||
| 158 | |||
| 159 | NOTSECURE_CAN_CHANGE SECURE_CANT_CHANGE | ||
| 160 | NOT_INSTALLED INCONSISTENT MANUAL NOTEST SECURE_CAN_CHANGE | ||
| 161 | STRING_NOT_DEFINED NOT_INSTALLED_NOTSECURE DONT_KNOW | ||
| 162 | RELEVANT_HEADERQ NOTRELEVANT_HEADERQ | ||
| 163 | ); | ||
| 164 | |||
| 165 | |||
| 166 | |||
| 167 | ###################################################### | ||
| 168 | ###Testing Functions | ||
| 169 | ################################################################## | ||
| 170 | |||
| 171 | #Define "Constants" for test functions. Note these constants sometimes get | ||
| 172 | #interpreted as literal strings when used as hash references, so you may | ||
| 173 | # have to use CONSTANT() to disambiguate, like below. Sorry, it was either | ||
| 174 | # that or create even *more* global variables. | ||
| 175 | # See TestDriver.pm for definitions, and test design doc for full explaination | ||
| 176 | use constant { | ||
| 177 | NOTSECURE_CAN_CHANGE => 0, | ||
| 178 | SECURE_CANT_CHANGE => 1, | ||
| 179 | NOT_INSTALLED => 2, # (where the lack makes the system secure, eg telnet) | ||
| 180 | INCONSISTENT => 3, | ||
| 181 | MANUAL => 4, | ||
| 182 | NOTEST => 5, | ||
| 183 | SECURE_CAN_CHANGE => 6, | ||
| 184 | STRING_NOT_DEFINED => 7, | ||
| 185 | NOT_INSTALLED_NOTSECURE => 8, #(Where the missing s/w makes the system less secure eg IPFilter) | ||
| 186 | #Intentional duplicates follow | ||
| 187 | DONT_KNOW => 5, | ||
| 188 | RELEVANT_HEADERQ => 6, | ||
| 189 | NOTRELEVANT_HEADERQ => 0 | ||
| 190 | }; | ||
| 191 | |||
| 192 | &SanitizeEnv; | ||
| 193 | |||
| 194 | # Set up some common error messages. These are independent of | ||
| 195 | # operating system | ||
| 196 | |||
| 197 | # These will allow us to line up the warnings and error messages | ||
| 198 | my $err ="ERROR: "; | ||
| 199 | my $spc =" "; | ||
| 200 | my $GLOBAL_OS="None"; | ||
| 201 | my $GLOBAL_ACTUAL_OS="None"; | ||
| 202 | my %GLOBAL_SUMS=(); | ||
| 203 | my $CLI=''; | ||
| 204 | |||
| 205 | #OS independent Error Messages Follow, normally "bastille" script filters | ||
| 206 | #options before interactive or Bastille runs, so this check is often redundant | ||
| 207 | $GLOBAL_ERROR{"usage"}="\n". | ||
| 208 | "$spc Usage: bastille [ -b | -c | -x ] [ --os <version> ] [ -f <alternate config> ]\n". | ||
| 209 | "$spc bastille [ -r | --assess | --assessnobowser ]\n\n". | ||
| 210 | "$spc --assess : check status of system and report in browser\n". | ||
| 211 | "$spc --assessnobrowser : check status of system and list report locations\n". | ||
| 212 | "$spc -b : use a saved config file to apply changes\n". | ||
| 213 | "$spc directly to system\n". | ||
| 214 | "$spc -c : use the Curses (non-X11) TUI\n". | ||
| 215 | "$spc -f <alternate config>: populate answers with a different config file\n". | ||
| 216 | "$spc -r : revert all Bastille changes to-date\n". | ||
| 217 | "$spc -x : use the Perl/Tk (X11) GUI\n" . | ||
| 218 | "$spc --os <version> : ask all questions for the given operating system\n" . | ||
| 219 | "$spc version. e.g. --os RH6.0\n"; | ||
| 220 | |||
| 221 | # These options don't work universally, so it's best not to | ||
| 222 | # document them here (yet). Hopefully, we'll get them | ||
| 223 | # straightened out soon. | ||
| 224 | #"$spc --log : log-only option\n". | ||
| 225 | #"$spc -v : verbose mode\n". | ||
| 226 | #"$spc --debug : debug mode\n"; | ||
| 227 | |||
| 228 | |||
| 229 | ############################################################################## | ||
| 230 | # | ||
| 231 | # Directory structure for Bastille Linux v1.2 and up | ||
| 232 | # | ||
| 233 | ############################################################################## | ||
| 234 | # | ||
| 235 | # /usr/sbin/ -- location of Bastille binaries | ||
| 236 | # /usr/lib/Bastille -- location of Bastille modules | ||
| 237 | # /usr/share/Bastille -- location of Bastille data files | ||
| 238 | # /etc/Bastille -- location of Bastille config files | ||
| 239 | # | ||
| 240 | # /var/log/Bastille -- location of Bastille log files | ||
| 241 | # /var/log/Bastille/revert -- directory holding all Bastille-created revert scripts | ||
| 242 | # /var/log/Bastille/revert/backup -- directory holding the original files that | ||
| 243 | # Bastille modifies, with permissions intact | ||
| 244 | # | ||
| 245 | ############################################################################## | ||
| 246 | |||
| 247 | ############################################################################## | ||
| 248 | # | ||
| 249 | # Directory structure for HP-UX Bastille v2.0 and up | ||
| 250 | # | ||
| 251 | ############################################################################## | ||
| 252 | # | ||
| 253 | # /opt/sec_mgmt/bastille/bin/ -- location of Bastille binaries | ||
| 254 | # /opt/sec_mgmt/bastille/lib/ -- location of Bastille modules | ||
| 255 | # /etc/opt/sec_mgmt/bastille/ -- location of Bastille data and config files | ||
| 256 | # | ||
| 257 | # /var/opt/sec_mgmt/bastille/log/ -- location of Bastille log files | ||
| 258 | # /var/opt/sec_mgmt/bastille/revert -- directory holding all Bastille-created | ||
| 259 | # revert scripts and save files | ||
| 260 | # | ||
| 261 | ############################################################################## | ||
| 262 | |||
| 263 | |||
| 264 | ############################################################################## | ||
| 265 | ############################################################################## | ||
| 266 | ################## Actual functions start here... ########################### | ||
| 267 | ############################################################################## | ||
| 268 | ############################################################################## | ||
| 269 | |||
| 270 | ########################################################################### | ||
| 271 | # setOptions takes six arguments, $GLOBAL_DEBUG, $GLOBAL_LOGONLY, | ||
| 272 | # $GLOBAL_VERBOSE, $GLOBAL_AUDITONLY, $GLOBAL_AUDIT_NO_BROWSER, and GLOBAL_OS; | ||
| 273 | ########################################################################### | ||
| 274 | sub setOptions($$$$$$) { | ||
| 275 | ($GLOBAL_DEBUG,$GLOBAL_LOGONLY,$GLOBAL_VERBOSE,$GLOBAL_AUDITONLY, | ||
| 276 | $GLOBAL_AUDIT_NO_BROWSER,$GLOBAL_OS) = @_; | ||
| 277 | if ($GLOBAL_AUDIT_NO_BROWSER) { | ||
| 278 | $GLOBAL_AUDITONLY = 1; | ||
| 279 | } | ||
| 280 | if (not(defined($GLOBAL_OS))){ | ||
| 281 | $GLOBAL_OS="None"; | ||
| 282 | } | ||
| 283 | } | ||
| 284 | ########################################################################### | ||
| 285 | # | ||
| 286 | # SanitizeEnv load a proper environment so Bastille cannot be tricked | ||
| 287 | # and Perl modules work correctly. | ||
| 288 | # | ||
| 289 | ########################################################################### | ||
| 290 | sub SanitizeEnv { | ||
| 291 | delete @ENV{'IFS','CDPATH','ENV','BASH_ENV'}; | ||
| 292 | $ENV{CDPATH}="."; | ||
| 293 | $ENV{BASH_ENV}= ""; | ||
| 294 | # Bin is needed here or else /usr/lib/perl5/5.005/Cwd.pm | ||
| 295 | # will not find `pwd` | ||
| 296 | # Detected while testing with -w, jfs | ||
| 297 | $ENV{PATH} = "/bin:/usr/bin"; | ||
| 298 | # Giorgi, is /usr/local/bin needed? (jfs) | ||
| 299 | } | ||
| 300 | |||
| 301 | ########################################################################### | ||
| 302 | # | ||
| 303 | # GetDistro checks to see if the target is a known distribution and reports | ||
| 304 | # said distribution. | ||
| 305 | # | ||
| 306 | # This is used throughout the script, but also by ConfigureForDistro. | ||
| 307 | # | ||
| 308 | # | ||
| 309 | ########################################################################### | ||
| 310 | |||
| 311 | sub GetDistro() { | ||
| 312 | |||
| 313 | my ($release,$distro); | ||
| 314 | |||
| 315 | # Only read files for the distro once. | ||
| 316 | # if the --os option was used then | ||
| 317 | if ($GLOBAL_OS eq "None") { | ||
| 318 | if ( -e "/etc/mandrake-release" ) { | ||
| 319 | open(MANDRAKE_RELEASE,"/etc/mandrake-release"); | ||
| 320 | $release=<MANDRAKE_RELEASE>; | ||
| 321 | |||
| 322 | if ( ($release =~ /^Mandrake Linux release (\d+\.\d+\w*)/) or ($release =~ /^Linux Mandrake release (\d+\.\d+\w*)/) ) { | ||
| 323 | $distro="MN$1"; | ||
| 324 | } | ||
| 325 | elsif ( $release =~ /^Mandrakelinux release (\d+\.\d+)\b/ ) { | ||
| 326 | $distro="MN$1"; | ||
| 327 | } | ||
| 328 | else { | ||
| 329 | print STDERR "$err Couldn't determine Mandrake/Mandriva version! Setting to 10.1!\n"; | ||
| 330 | $distro="MN10.1"; | ||
| 331 | } | ||
| 332 | |||
| 333 | close(MANDRAKE_RELEASE); | ||
| 334 | } | ||
| 335 | elsif ( -e "/etc/immunix-release" ) { | ||
| 336 | open(IMMUNIX_RELEASE,"/etc/immunix-release"); | ||
| 337 | $release=<IMMUNIX_RELEASE>; | ||
| 338 | unless ($release =~ /^Immunix Linux release (\d+\.\d+\w*)/) { | ||
| 339 | print STDERR "$err Couldn't determine Immunix version! Setting to 6.2!\n"; | ||
| 340 | $distro="RH6.2"; | ||
| 341 | } | ||
| 342 | else { | ||
| 343 | $distro="RH$1"; | ||
| 344 | } | ||
| 345 | close(*IMMUNIX_RELEASE); | ||
| 346 | } | ||
| 347 | elsif ( -e '/etc/fedora-release' ) { | ||
| 348 | open(FEDORA_RELEASE,'/etc/fedora-release'); | ||
| 349 | $release=<FEDORA_RELEASE>; | ||
| 350 | close FEDORA_RELEASE; | ||
| 351 | if ($release =~ /^Fedora Core release (\d+\.?\d*)/) { | ||
| 352 | $distro = "RHFC$1"; | ||
| 353 | } | ||
| 354 | elsif ($release =~ /^Fedora release (\d+\.?\d*)/) { | ||
| 355 | $distro = "RHFC$1"; | ||
| 356 | } | ||
| 357 | else { | ||
| 358 | print STDERR "$err Could not determine Fedora version! Setting to Fedora Core 8\n"; | ||
| 359 | $distro='RHFC8'; | ||
| 360 | } | ||
| 361 | } | ||
| 362 | elsif ( -e "/etc/redhat-release" ) { | ||
| 363 | open(*REDHAT_RELEASE,"/etc/redhat-release"); | ||
| 364 | $release=<REDHAT_RELEASE>; | ||
| 365 | if ($release =~ /^Red Hat Linux release (\d+\.?\d*\w*)/) { | ||
| 366 | $distro="RH$1"; | ||
| 367 | } | ||
| 368 | elsif ($release =~ /^Red Hat Linux .+ release (\d+)\.?\d*([AEW]S)/) { | ||
| 369 | $distro="RHEL$1$2"; | ||
| 370 | } | ||
| 371 | elsif ($release =~ /^Red Hat Enterprise Linux ([AEW]S) release (\d+)/) { | ||
| 372 | $distro="RHEL$2$1"; | ||
| 373 | } | ||
| 374 | elsif ($release =~ /^CentOS release (\d+\.\d+)/) { | ||
| 375 | my $version = $1; | ||
| 376 | if ($version =~ /^4\./) { | ||
| 377 | $distro='RHEL4AS'; | ||
| 378 | } | ||
| 379 | elsif ($version =~ /^3\./) { | ||
| 380 | $distro='RHEL3AS'; | ||
| 381 | } | ||
| 382 | else { | ||
| 383 | print STDERR "$err Could not determine CentOS version! Setting to Red Hat Enterprise 4 AS.\n"; | ||
| 384 | $distro='RHEL4AS'; | ||
| 385 | } | ||
| 386 | } | ||
| 387 | else { | ||
| 388 | # JJB/HP - Should this be B_log? | ||
| 389 | print STDERR "$err Couldn't determine Red Hat version! Setting to 9!\n"; | ||
| 390 | $distro="RH9"; | ||
| 391 | } | ||
| 392 | close(REDHAT_RELEASE); | ||
| 393 | |||
| 394 | } | ||
| 395 | elsif ( -e "/etc/debian_version" ) { | ||
| 396 | $stable="3.1"; #Change this when Debian stable changes | ||
| 397 | open(*DEBIAN_RELEASE,"/etc/debian_version"); | ||
| 398 | $release=<DEBIAN_RELEASE>; | ||
| 399 | unless ($release =~ /^(\d+\.\d+\w*)/) { | ||
| 400 | print STDERR "$err System is not running a stable Debian GNU/Linux version. Setting to $stable.\n"; | ||
| 401 | $distro="DB$stable"; | ||
| 402 | } | ||
| 403 | else { | ||
| 404 | $distro="DB$1"; | ||
| 405 | } | ||
| 406 | close(DEBIAN_RELEASE); | ||
| 407 | } | ||
| 408 | elsif ( -e "/etc/SuSE-release" ) { | ||
| 409 | open(*SUSE_RELEASE,"/etc/SuSE-release"); | ||
| 410 | $release=<SUSE_RELEASE>; | ||
| 411 | if ($release =~ /^SuSE Linux (\d+\.\d+\w*)/i) { | ||
| 412 | $distro="SE$1"; | ||
| 413 | } | ||
| 414 | elsif ($release =~ /^SUSE LINUX Enterprise Server (\d+\.?\d?\w*)/i) { | ||
| 415 | $distro="SESLES$1"; | ||
| 416 | } | ||
| 417 | elsif ($release =~ /^SUSE Linux Enterprise Server (\d+\.?\d?\w*)/i) { | ||
| 418 | $distro="SESLES$1"; | ||
| 419 | } | ||
| 420 | elsif ($release =~ /^openSuSE (\d+\.\d+\w*)/i) { | ||
| 421 | $distro="SE$1"; | ||
| 422 | } | ||
| 423 | else { | ||
| 424 | print STDERR "$err Couldn't determine SuSE version! Setting to 10.3!\n"; | ||
| 425 | $distro="SE10.3"; | ||
| 426 | } | ||
| 427 | close(SUSE_RELEASE); | ||
| 428 | } | ||
| 429 | elsif ( -e "/etc/turbolinux-release") { | ||
| 430 | open(*TURBOLINUX_RELEASE,"/etc/turbolinux-release"); | ||
| 431 | $release=<TURBOLINUX_RELEASE>; | ||
| 432 | unless ($release =~ /^Turbolinux Workstation (\d+\.\d+\w*)/) { | ||
| 433 | print STDERR "$err Couldn't determine TurboLinux version! Setting to 7.0!\n"; | ||
| 434 | $distro="TB7.0"; | ||
| 435 | } | ||
| 436 | else { | ||
| 437 | $distro="TB$1"; | ||
| 438 | } | ||
| 439 | close(TURBOLINUX_RELEASE); | ||
| 440 | } | ||
| 441 | else { | ||
| 442 | # We're either on Mac OS X, HP-UX or an unsupported O/S. | ||
| 443 | if ( -x '/usr/bin/uname') { | ||
| 444 | # uname is in /usr/bin on Mac OS X and HP-UX | ||
| 445 | $release=`/usr/bin/uname -sr`; | ||
| 446 | } | ||
| 447 | else { | ||
| 448 | print STDERR "$err Could not determine operating system version!\n"; | ||
| 449 | $distro="unknown"; | ||
| 450 | } | ||
| 451 | |||
| 452 | # Figure out what kind of system we're on. | ||
| 453 | if ($release ne "") { | ||
| 454 | if ($release =~ /^Darwin\s+(\d+)\.(\d+)/) { | ||
| 455 | if ($1 == 6 ) { | ||
| 456 | $distro = "OSX10.2"; | ||
| 457 | } | ||
| 458 | elsif ($1 == 7) { | ||
| 459 | $distro = "OSX10.3"; | ||
| 460 | } | ||
| 461 | elsif ($1 == 8) { | ||
| 462 | $distro = "OSX10.3"; | ||
| 463 | } | ||
| 464 | else { | ||
| 465 | $distro = "unknown"; | ||
| 466 | } | ||
| 467 | } | ||
| 468 | elsif ( $release =~ /(^HP-UX)\s*B\.(\d+\.\d+)/ ) { | ||
| 469 | $distro="$1$2"; | ||
| 470 | } | ||
| 471 | else { | ||
| 472 | print STDERR "$err Could not determine operating system version!\n"; | ||
| 473 | $distro="unknown"; | ||
| 474 | } | ||
| 475 | } | ||
| 476 | } | ||
| 477 | |||
| 478 | $GLOBAL_OS=$distro; | ||
| 479 | } elsif (not (defined $GLOBAL_OS)) { | ||
| 480 | print "ERROR: GLOBAL OS Scoping Issue\n"; | ||
| 481 | } else { | ||
| 482 | $distro = $GLOBAL_OS; | ||
| 483 | } | ||
| 484 | |||
| 485 | return $distro; | ||
| 486 | } | ||
| 487 | |||
| 488 | ################################################################################### | ||
| 489 | # &getActualDistro; # | ||
| 490 | # # | ||
| 491 | # This subroutine returns the actual os version in which is running on. This # | ||
| 492 | # os version is independent of the --os switch feed to bastille. # | ||
| 493 | # # | ||
| 494 | ################################################################################### | ||
| 495 | sub getActualDistro { | ||
| 496 | # set local variable to $GLOBAL_OS | ||
| 497 | |||
| 498 | if ($GLOBAL_ACTUAL_OS eq "None") { | ||
| 499 | my $os = $GLOBAL_OS; | ||
| 500 | # undef GLOBAL_OS so that the GetDistro routine will return | ||
| 501 | # the actualDistro, it might otherwise return the distro set | ||
| 502 | # by the --os switch. | ||
| 503 | $GLOBAL_OS = "None"; | ||
| 504 | $GLOBAL_ACTUAL_OS = &GetDistro; | ||
| 505 | # reset the GLOBAL_OS variable | ||
| 506 | $GLOBAL_OS = $os; | ||
| 507 | } | ||
| 508 | return $GLOBAL_ACTUAL_OS; | ||
| 509 | } | ||
| 510 | # These are helper routines which used to be included inside GetDistro | ||
| 511 | sub is_OS_supported($) { | ||
| 512 | my $os=$_[0]; | ||
| 513 | my $supported=0; | ||
| 514 | my %supportedOSHash = &getSupportedOSHash; | ||
| 515 | |||
| 516 | foreach my $oSType (keys %supportedOSHash) { | ||
| 517 | foreach my $supported_os ( @{$supportedOSHash{$oSType}} ) { | ||
| 518 | if ( $supported_os eq $os ) { | ||
| 519 | $supported=1; | ||
| 520 | } | ||
| 521 | } | ||
| 522 | } | ||
| 523 | |||
| 524 | return $supported; | ||
| 525 | } | ||
| 526 | |||
| 527 | ############################################################################### | ||
| 528 | # getSupportedOSHash | ||
| 529 | # | ||
| 530 | # This subrountine returns a hash of supported OSTypes, which point to a | ||
| 531 | # a list of supported distros. When porting to a new distro, add the | ||
| 532 | # distro id to the hash in its appropriate list. | ||
| 533 | ############################################################################### | ||
| 534 | sub getSupportedOSHash () { | ||
| 535 | |||
| 536 | my %osHash = ("LINUX" => [ | ||
| 537 | "DB2.2", "DB3.0", | ||
| 538 | "RH6.0","RH6.1","RH6.2","RH7.0", | ||
| 539 | "RH7.1","RH7.2","RH7.3","RH8.0", | ||
| 540 | "RH9", | ||
| 541 | "RHEL5", | ||
| 542 | "RHEL4AS","RHEL4ES","RHEL4WS", | ||
| 543 | "RHEL3AS","RHEL3ES","RHEL3WS", | ||
| 544 | "RHEL2AS","RHEL2ES","RHEL2WS", | ||
| 545 | "RHFC1","RHFC2","RHFC3","RHFC4", | ||
| 546 | "RHFC5","RHFC6","RHFC7","RHFC8", | ||
| 547 | "MN6.0","MN6.1 ","MN7.0","MN7.1", | ||
| 548 | "MN7.2","MN8.0","MN8.1","MN8.2", | ||
| 549 | "MN10.1", | ||
| 550 | "SE7.2","SE7.3", "SE8.0","SE8.1","SE9.0","SE9.1", | ||
| 551 | "SE9.2","SE9.3","SE10.0","SE10.1","SE10.2","SE10.3", | ||
| 552 | "SESLES8","SESLES9","SESLES10", | ||
| 553 | "TB7.0" | ||
| 554 | ], | ||
| 555 | |||
| 556 | "HP-UX" => [ | ||
| 557 | "HP-UX11.00","HP-UX11.11", | ||
| 558 | "HP-UX11.22", "HP-UX11.23", | ||
| 559 | "HP-UX11.31" | ||
| 560 | ], | ||
| 561 | |||
| 562 | "OSX" => [ | ||
| 563 | 'OSX10.2','OSX10.3','OSX10.4' | ||
| 564 | ] | ||
| 565 | ); | ||
| 566 | |||
| 567 | return %osHash; | ||
| 568 | |||
| 569 | } | ||
| 570 | |||
| 571 | |||
| 572 | ############################################################################### | ||
| 573 | # setFileLocations(OSMapFile, currentDistro); | ||
| 574 | # | ||
| 575 | # Given a file map location this subroutine will create the GLOBAL_* | ||
| 576 | # hash entries specified within this file. | ||
| 577 | ############################################################################### | ||
| 578 | sub setFileLocations($$) { | ||
| 579 | |||
| 580 | my ($fileInfoFile,$currentDistro) = @_; | ||
| 581 | |||
| 582 | # define a mapping from the first argument to the proper hash | ||
| 583 | my %map = ("BIN" => \%GLOBAL_BIN, | ||
| 584 | "FILE" => \%GLOBAL_FILE, | ||
| 585 | "BFILE" => \%GLOBAL_BFILE, | ||
| 586 | "DIR" => \%GLOBAL_DIR, | ||
| 587 | "BDIR" => \%GLOBAL_BDIR | ||
| 588 | ); | ||
| 589 | my @fileInfo = (); | ||
| 590 | |||
| 591 | # File containing file location information | ||
| 592 | if(open(FILEINFO, "<$fileInfoFile" )) { | ||
| 593 | |||
| 594 | @fileInfo = <FILEINFO>; | ||
| 595 | |||
| 596 | close(FILEINFO); | ||
| 597 | |||
| 598 | } | ||
| 599 | else { | ||
| 600 | print STDERR "$err Unable to find file location information for '$distro'.\n" . | ||
| 601 | "$spc Contact the Bastille support list for details.\n"; | ||
| 602 | exit(1); | ||
| 603 | } | ||
| 604 | |||
| 605 | # Each line of the file map follows the pattern below: | ||
| 606 | # bdir,init.d,'/etc/rc.d/init.d',RH7.2,RH7.3 | ||
| 607 | # if the distro information is not available, e.g. | ||
| 608 | # bdir,init.d,'/etc/rc.d/init.d' | ||
| 609 | # then the line applies to all distros under the OSType | ||
| 610 | foreach my $file (@fileInfo) { | ||
| 611 | # Perl comments are allowed within the file but only entire line comments | ||
| 612 | if($file !~ /^\s+\#|^\s+$/) { | ||
| 613 | chomp $file; | ||
| 614 | # type relates to the map above, type bin will map to GLOBAL_BIN | ||
| 615 | # id is the identifier used as the hash key by the GLOBAL hash | ||
| 616 | # fileLocation is the full path to the file | ||
| 617 | # distroList is an optional list of distros that this particular | ||
| 618 | # file location, if no distro list is presented the file location | ||
| 619 | # is considered to apply to all distros | ||
| 620 | my ($type,$id,$fileLocation,@distroList) = split /\s*,\s*/, $file; | ||
| 621 | $fileLocation =~ s/^\'(.*)\'$/$1/; | ||
| 622 | if($#distroList == -1) { | ||
| 623 | $map{uc($type)}->{$id}=$fileLocation; | ||
| 624 | } | ||
| 625 | else { | ||
| 626 | foreach my $distro (@distroList) { | ||
| 627 | # if the current distro matches the distro listed then | ||
| 628 | # this file location applies | ||
| 629 | if($currentDistro =~ /$distro/) { | ||
| 630 | $map{uc($type)}->{$id}=$fileLocation; | ||
| 631 | } | ||
| 632 | } | ||
| 633 | } | ||
| 634 | } | ||
| 635 | } | ||
| 636 | unless(defined($map{uc("BFILE")}->{"current_config"})) { | ||
| 637 | &setGlobal("BFILE","current_config",&getGlobal("BFILE","config")); | ||
| 638 | } | ||
| 639 | } | ||
| 640 | |||
| 641 | ############################################################################### | ||
| 642 | # setServiceInfo($OSServiceMapFile, $currentDistro | ||
| 643 | # | ||
| 644 | # Given the location of an OS Service map file, which describes | ||
| 645 | # a service in terms of configurables, processes and a service type. | ||
| 646 | # The subroutine fills out the GLOBAL_SERVICE, $GLOBAL_RC_CONFIG, GLOBAL_SERVTYPE, and | ||
| 647 | # GLOBAL_PROCESS hashes for a given service ID. | ||
| 648 | ############################################################################### | ||
| 649 | sub setServiceInfo($$) { | ||
| 650 | my ($serviceInfoFile,$currentDistro) = @_; | ||
| 651 | my @serviceInfo = (); | ||
| 652 | |||
| 653 | if(open(SERVICEINFO, "<$serviceInfoFile" )) { | ||
| 654 | |||
| 655 | @serviceInfo = <SERVICEINFO>; | ||
| 656 | |||
| 657 | close(SERVICEINFO); | ||
| 658 | |||
| 659 | } | ||
| 660 | else { | ||
| 661 | print STDERR "$err Unable to find service, service type, and process information\n" . | ||
| 662 | "$spc for '$distro'.\n" . | ||
| 663 | "$spc Contact the Bastille support list for details.\n"; | ||
| 664 | exit(1); | ||
| 665 | } | ||
| 666 | |||
| 667 | |||
| 668 | # The following loop, parses the entire (YOUR OS).service file | ||
| 669 | # to provide service information for YOUR OS. | ||
| 670 | # The files format is as follows: | ||
| 671 | # serviceID,servType,('service' 'configuration' 'list'),('process' 'list')[,DISTROS]* | ||
| 672 | # if distros are not present then the service is assumed to be | ||
| 673 | # relevant the the current distro | ||
| 674 | |||
| 675 | |||
| 676 | # | ||
| 677 | # More specifically, this file's format for rc-based daemons is: | ||
| 678 | # | ||
| 679 | # script_name,rc,(rc-config-file rc-config-file ...),(rc-variable1 rc-variable2 ...),('program_name1 program_name2 ...') | ||
| 680 | # | ||
| 681 | # ...where script_name is a file in /etc/init.d/ and | ||
| 682 | # ...program_nameN is a program launced by the script. | ||
| 683 | # | ||
| 684 | # This file's format for inet-based daemons is: | ||
| 685 | # | ||
| 686 | # identifier, inet, line name/file name, program name | ||
| 687 | # | ||
| 688 | # label,inet,(port1 port2 ...),(daemon1 daemon2 ...) | ||
| 689 | # | ||
| 690 | # ...where label is arbitrary, portN is one of the ports | ||
| 691 | # ...this one listens on, and daemonN is a program launched | ||
| 692 | # ...in response to a connection on a port. | ||
| 693 | |||
| 694 | foreach my $service (@serviceInfo) { | ||
| 695 | # This file accepts simple whole line comments perl style | ||
| 696 | if($service !~ /^\s+\#|^\s+$/) { | ||
| 697 | chomp $service; | ||
| 698 | my ($serviceID,$servType,$strConfigList,$strServiceList, | ||
| 699 | $strProcessList,@distroList) = split /\s*,\s*/, $service; | ||
| 700 | |||
| 701 | sub MakeArrayFromString($){ | ||
| 702 | my $entryString = $_[0]; | ||
| 703 | my @destArray = (); | ||
| 704 | if ($entryString =~ /\'\S+\'/) { #Make sure we have something to extract before we try | ||
| 705 | @destArray = split /\'\s+\'/, $entryString; | ||
| 706 | $destArray[0] =~ s/^\(\'(.+)$/$1/; # Remove leading quotation mark | ||
| 707 | $destArray[$#destArray] =~ s/^(.*)\'\)$/$1/; #Remove trailing quotation mark | ||
| 708 | } | ||
| 709 | return @destArray; | ||
| 710 | } | ||
| 711 | |||
| 712 | # produce a list of configuration files from the files | ||
| 713 | # format ('configuration' 'files') | ||
| 714 | my @configList = MakeArrayFromString($strConfigList); | ||
| 715 | |||
| 716 | # produce a list of service configurables from the files | ||
| 717 | # format ('service' 'configurable') | ||
| 718 | my @serviceList = MakeArrayFromString($strServiceList); | ||
| 719 | |||
| 720 | # produce a list of process names from the files format | ||
| 721 | # ('my' 'process' 'list') | ||
| 722 | my @processList = MakeArrayFromString($strProcessList); | ||
| 723 | |||
| 724 | # if distros were not specified then accept the service information | ||
| 725 | if($#distroList == -1) { | ||
| 726 | @{$GLOBAL_SERVICE{$serviceID}} = @serviceList; | ||
| 727 | $GLOBAL_SERVTYPE{$serviceID} = $servType; | ||
| 728 | @{$GLOBAL_PROCESS{$serviceID}} = @processList; | ||
| 729 | @{$GLOBAL_RC_CONFIG{$serviceID}} = @configList; | ||
| 730 | } | ||
| 731 | else { | ||
| 732 | # only if the current distro matches one of the listed distros | ||
| 733 | # include the service information. | ||
| 734 | foreach my $distro (@distroList) { | ||
| 735 | if($currentDistro =~ /$distro/) { | ||
| 736 | @{$GLOBAL_SERVICE{$serviceID}} = @serviceList; | ||
| 737 | $GLOBAL_SERVTYPE{$serviceID} = $servType; | ||
| 738 | @{$GLOBAL_PROCESS{$serviceID}} = @processList; | ||
| 739 | @{$GLOBAL_RC_CONFIG{$serviceID}} = @configList; | ||
| 740 | } | ||
| 741 | } | ||
| 742 | } | ||
| 743 | } | ||
| 744 | } | ||
| 745 | } | ||
| 746 | |||
| 747 | |||
| 748 | |||
| 749 | ############################################################################### | ||
| 750 | # getFileAndServiceInfo($distro,$actualDistro) | ||
| 751 | # | ||
| 752 | # This subrountine, given distribution information, will import system file | ||
| 753 | # and service information into the GLOBA_* hashes. | ||
| 754 | # | ||
| 755 | # NOTE: $distro and $actualDistro will only differ when the --os switch is | ||
| 756 | # used to generate a configuration file for an arbitrary operating | ||
| 757 | # system. | ||
| 758 | # | ||
| 759 | ############################################################################### | ||
| 760 | sub getFileAndServiceInfo($$) { | ||
| 761 | |||
| 762 | my ($distro,$actualDistro) = @_; | ||
| 763 | |||
| 764 | # defines the path to the OS map information for any supported OS type. | ||
| 765 | # OS map information is used to determine file locations for a given | ||
| 766 | # distribution. | ||
| 767 | my %oSInfoPath = ( | ||
| 768 | "LINUX" => "/usr/share/Bastille/OSMap/", | ||
| 769 | "HP-UX" => "/etc/opt/sec_mgmt/bastille/OSMap/", | ||
| 770 | "OSX" => "/usr/share/Bastille/OSMap/" | ||
| 771 | ); | ||
| 772 | |||
| 773 | # returns the OS, LINUX, HP-UX, or OSX, associated with this | ||
| 774 | # distribution | ||
| 775 | my $actualOS = &getOSType($actualDistro); | ||
| 776 | my $oS = &getOSType($distro); | ||
| 777 | |||
| 778 | if(defined $actualOS && defined $oS) { | ||
| 779 | my $bastilleInfoFile = $oSInfoPath{$actualOS} . "${actualOS}.bastille"; | ||
| 780 | my $systemInfoFile = $oSInfoPath{$actualOS} . "${oS}.system"; | ||
| 781 | my $serviceInfoFile = $oSInfoPath{$actualOS} . "${oS}.service"; | ||
| 782 | |||
| 783 | if(-f $bastilleInfoFile) { | ||
| 784 | &setFileLocations($bastilleInfoFile,$actualDistro); | ||
| 785 | } | ||
| 786 | else { | ||
| 787 | print STDERR "$err Unable to find bastille file information.\n" . | ||
| 788 | "$spc $bastilleInfoFile does not exist on the system"; | ||
| 789 | exit(1); | ||
| 790 | } | ||
| 791 | |||
| 792 | if(-f $systemInfoFile) { | ||
| 793 | &setFileLocations($systemInfoFile,$distro); | ||
| 794 | } | ||
| 795 | else { | ||
| 796 | print STDERR "$err Unable to find system file information.\n" . | ||
| 797 | "$spc $systemInfoFile does not exist on the system"; | ||
| 798 | exit(1); | ||
| 799 | } | ||
| 800 | # Service info File is optional | ||
| 801 | if(-f $serviceInfoFile) { | ||
| 802 | &setServiceInfo($serviceInfoFile,$distro); | ||
| 803 | } | ||
| 804 | } | ||
| 805 | else { | ||
| 806 | print STDERR "$err Unable to determine operating system type\n" . | ||
| 807 | "$spc for $actualDistro or $distro\n"; | ||
| 808 | exit(1); | ||
| 809 | } | ||
| 810 | |||
| 811 | } | ||
| 812 | |||
| 813 | |||
| 814 | # returns the Operating System type associated with the specified | ||
| 815 | # distribution. | ||
| 816 | sub getOSType($) { | ||
| 817 | |||
| 818 | my $distro = $_[0]; | ||
| 819 | |||
| 820 | my %supportedOSHash = &getSupportedOSHash; | ||
| 821 | foreach my $oSType (keys %supportedOSHash) { | ||
| 822 | foreach my $oSDistro (@{$supportedOSHash{$oSType}}) { | ||
| 823 | if($distro eq $oSDistro) { | ||
| 824 | return $oSType; | ||
| 825 | } | ||
| 826 | } | ||
| 827 | } | ||
| 828 | |||
| 829 | return undef; | ||
| 830 | |||
| 831 | } | ||
| 832 | |||
| 833 | |||
| 834 | # Test subroutine used to debug file location info for new Distributions as | ||
| 835 | # they are ported. | ||
| 836 | sub dumpFileInfo { | ||
| 837 | print "Dumping File Information\n"; | ||
| 838 | foreach my $hashref (\%GLOBAL_BIN,\%GLOBAL_DIR,\%GLOBAL_FILE,\%GLOBAL_BFILE,\%GLOBAL_BDIR) { | ||
| 839 | foreach my $id (keys %{$hashref}) { | ||
| 840 | print "$id: ${$hashref}{$id}\n"; | ||
| 841 | } | ||
| 842 | print "-----------------------\n\n"; | ||
| 843 | } | ||
| 844 | } | ||
| 845 | |||
| 846 | # Test subroutine used to debug service info for new Distributions as | ||
| 847 | # they are ported. | ||
| 848 | sub dumpServiceInfo { | ||
| 849 | print "Dumping Service Information\n"; | ||
| 850 | foreach my $serviceId (keys %GLOBAL_SERVICE) { | ||
| 851 | print "$serviceId:\n"; | ||
| 852 | print "Type - $GLOBAL_SERVTYPE{$serviceId}\n"; | ||
| 853 | print "Service List:\n"; | ||
| 854 | foreach my $service (@{$GLOBAL_SERVICE{$serviceId}}) { | ||
| 855 | print "$service "; | ||
| 856 | } | ||
| 857 | print "\nProcess List:\n"; | ||
| 858 | foreach my $process (@{$GLOBAL_PROCESS{$serviceId}}) { | ||
| 859 | print "$process "; | ||
| 860 | } | ||
| 861 | print "\n----------------------\n"; | ||
| 862 | } | ||
| 863 | } | ||
| 864 | |||
| 865 | |||
| 866 | ########################################################################### | ||
| 867 | # | ||
| 868 | # &ConfigureForDistro configures the API for a given distribution. This | ||
| 869 | # includes setting global variables that tell the Bastille API about | ||
| 870 | # given binaries and directories. | ||
| 871 | # | ||
| 872 | # WARNING: If a distro is not covered here, Bastille may not be 100% | ||
| 873 | # compatible with it, though 1.1 is written to be much smarter | ||
| 874 | # about unknown distros... | ||
| 875 | # | ||
| 876 | ########################################################################### | ||
| 877 | sub ConfigureForDistro { | ||
| 878 | |||
| 879 | my $retval=1; | ||
| 880 | |||
| 881 | # checking to see if the os version given is in fact supported | ||
| 882 | my $distro = &GetDistro; | ||
| 883 | |||
| 884 | # checking to see if the actual os version is in fact supported | ||
| 885 | my $actualDistro = &getActualDistro; | ||
| 886 | $ENV{'LOCALE'}=''; # So that test cases checking for english results work ok. | ||
| 887 | if ((! &is_OS_supported($distro)) or (! &is_OS_supported($actualDistro)) ) { | ||
| 888 | # if either is not supported then print out a list of supported versions | ||
| 889 | if (! &is_OS_supported($distro)) { | ||
| 890 | print STDERR "$err '$distro' is not a supported operating system.\n"; | ||
| 891 | } | ||
| 892 | else { | ||
| 893 | print STDERR "$err Bastille is unable to operate correctly on this\n"; | ||
| 894 | print STDERR "$spc $distro operating system.\n"; | ||
| 895 | } | ||
| 896 | my %supportedOSHash = &getSupportedOSHash; | ||
| 897 | print STDERR "$spc Valid operating system versions are as follows:\n"; | ||
| 898 | |||
| 899 | foreach my $oSType (keys %supportedOSHash) { | ||
| 900 | |||
| 901 | print STDERR "$spc $oSType:\n$spc "; | ||
| 902 | |||
| 903 | my $os_number = 1; | ||
| 904 | foreach my $os (@{$supportedOSHash{$oSType}}) { | ||
| 905 | print STDERR "'$os' "; | ||
| 906 | if ($os_number == 5){ | ||
| 907 | print STDERR "\n$spc "; | ||
| 908 | $os_number = 1; | ||
| 909 | } | ||
| 910 | else { | ||
| 911 | $os_number++; | ||
| 912 | } | ||
| 913 | |||
| 914 | } | ||
| 915 | print STDERR "\n"; | ||
| 916 | } | ||
| 917 | |||
| 918 | print "\n" . $GLOBAL_ERROR{"usage"}; | ||
| 919 | exit(1); | ||
| 920 | } | ||
| 921 | |||
| 922 | # First, let's make sure that we do not create any files or | ||
| 923 | # directories with more permissive permissions than we | ||
| 924 | # intend via setting the Perl umask | ||
| 925 | umask(077); | ||
| 926 | |||
| 927 | &getFileAndServiceInfo($distro,$actualDistro); | ||
| 928 | |||
| 929 | # &dumpFileInfo; # great for debuging file location issues | ||
| 930 | # &dumpServiceInfo; # great for debuging service information issues | ||
| 931 | |||
| 932 | # OS dependent error messages (after configuring file locations) | ||
| 933 | my $nodisclaim_file = &getGlobal('BFILE', "nodisclaimer"); | ||
| 934 | |||
| 935 | $GLOBAL_ERROR{"disclaimer"}="$err Unable to touch $nodisclaim_file:" . | ||
| 936 | "$spc You must use Bastille\'s -n flag (for example:\n" . | ||
| 937 | "$spc bastille -f -n) or \'touch $nodisclaim_file \'\n"; | ||
| 938 | |||
| 939 | return $retval; | ||
| 940 | } | ||
| 941 | |||
| 942 | |||
| 943 | ########################################################################### | ||
| 944 | ########################################################################### | ||
| 945 | # # | ||
| 946 | # The B_<perl_function> file utilities are replacements for their Perl # | ||
| 947 | # counterparts. These replacements log their actions and their errors, # | ||
| 948 | # but are very similar to said counterparts. # | ||
| 949 | # # | ||
| 950 | ########################################################################### | ||
| 951 | ########################################################################### | ||
| 952 | |||
| 953 | |||
| 954 | ########################################################################### | ||
| 955 | # B_open is used for opening a file for reading. B_open_plus is the preferred | ||
| 956 | # function for writing, since it saves a backup copy of the file for | ||
| 957 | # later restoration. | ||
| 958 | # | ||
| 959 | # B_open opens the given file handle, associated with the given filename | ||
| 960 | # and logs appropriately. | ||
| 961 | # | ||
| 962 | ########################################################################### | ||
| 963 | |||
| 964 | sub B_open { | ||
| 965 | my $retval=1; | ||
| 966 | my ($handle,$filename)=@_; | ||
| 967 | |||
| 968 | unless ($GLOBAL_LOGONLY) { | ||
| 969 | $retval = open $handle,$filename; | ||
| 970 | } | ||
| 971 | |||
| 972 | ($handle) = "$_[0]" =~ /[^:]+::[^:]+::([^:]+)/; | ||
| 973 | &B_log("ACTION","open $handle,\"$filename\";\n"); | ||
| 974 | unless ($retval) { | ||
| 975 | &B_log("ERROR","open $handle, $filename failed...\n"); | ||
| 976 | } | ||
| 977 | |||
| 978 | return $retval; | ||
| 979 | } | ||
| 980 | |||
| 981 | ########################################################################### | ||
| 982 | # B_open_plus is the v1.1 open command. | ||
| 983 | # | ||
| 984 | # &B_open_plus($handle_file,$handle_original,$file) opens the file $file | ||
| 985 | # for reading and opens the file ${file}.bastille for writing. It is the | ||
| 986 | # counterpart to B_close_plus, which will move the original file to | ||
| 987 | # $GLOBAL_BDIR{"backup"} and will place the new file ${file}.bastille in its | ||
| 988 | # place. | ||
| 989 | # | ||
| 990 | # &B_open_plus makes the appropriate log entries in the action and error | ||
| 991 | # logs. | ||
| 992 | ########################################################################### | ||
| 993 | |||
| 994 | sub B_open_plus { | ||
| 995 | |||
| 996 | my ($handle_file,$handle_original,$file)=@_; | ||
| 997 | my $retval=1; | ||
| 998 | my $return_file=1; | ||
| 999 | my $return_old=1; | ||
| 1000 | |||
| 1001 | my $original_file = $file; | ||
| 1002 | |||
| 1003 | # Open the original file and open a copy for writing. | ||
| 1004 | unless ($GLOBAL_LOGONLY) { | ||
| 1005 | # if the temporary filename already exists then the open operation will fail. | ||
| 1006 | if ( $file eq "" ){ | ||
| 1007 | &B_log("ERROR","Internal Error - Attempt Made to Open Blank Filename"); | ||
| 1008 | $return_old=0; | ||
| 1009 | $return_file=0; | ||
| 1010 | return 0; #False | ||
| 1011 | } elsif (-e "${file}.bastille") { | ||
| 1012 | &B_log("ERROR","Unable to open $file as the swap file ". | ||
| 1013 | "${file}.bastille\" already exists. Rename the swap ". | ||
| 1014 | "file to allow Bastille to make desired file modifications."); | ||
| 1015 | $return_old=0; | ||
| 1016 | $return_file=0; | ||
| 1017 | } | ||
| 1018 | else { | ||
| 1019 | $return_old = open $handle_original,"$file"; | ||
| 1020 | $return_file = open $handle_file,("> $file.bastille"); | ||
| 1021 | } | ||
| 1022 | } | ||
| 1023 | |||
| 1024 | # Error handling/logging here... | ||
| 1025 | #&B_log("ACTION","# Modifying file $original_file via temporary file $original_file.bastille\n"); | ||
| 1026 | unless ($return_file) { | ||
| 1027 | $retval=0; | ||
| 1028 | &B_log("ERROR","open file: \"$original_file.bastille\" failed...\n"); | ||
| 1029 | } | ||
| 1030 | unless ($return_old) { | ||
| 1031 | $retval=0; | ||
| 1032 | &B_log("ERROR","open file: \"$original_file\" failed.\n"); | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | return $retval; | ||
| 1036 | |||
| 1037 | } | ||
| 1038 | |||
| 1039 | ########################################################################### | ||
| 1040 | # B_close was the v1.0 close command. It is still used in places in the | ||
| 1041 | # code. | ||
| 1042 | # However the use of B _close_plus, which implements a new, smarter, | ||
| 1043 | # backup scheme is preferred. | ||
| 1044 | # | ||
| 1045 | # B_close closes the given file handle, associated with the given filename | ||
| 1046 | # and logs appropriately. | ||
| 1047 | ########################################################################### | ||
| 1048 | |||
| 1049 | |||
| 1050 | sub B_close { | ||
| 1051 | my $retval=1; | ||
| 1052 | |||
| 1053 | unless ($GLOBAL_LOGONLY) { | ||
| 1054 | $retval = close $_[0]; | ||
| 1055 | } | ||
| 1056 | |||
| 1057 | &B_log("ACTION", "close $_[0];\n"); | ||
| 1058 | unless ($retval) { | ||
| 1059 | &B_log("ERROR", "close $_[0] failed...\n"); | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | return $retval; | ||
| 1063 | } | ||
| 1064 | |||
| 1065 | |||
| 1066 | ########################################################################### | ||
| 1067 | # B_close_plus is the v1.1 close command. | ||
| 1068 | # | ||
| 1069 | # &B_close_plus($handle_file,$handle_original,$file) closes the files | ||
| 1070 | # $file and ${file}.bastille, backs up $file to $GLOBAL_BDIR{"backup"} and | ||
| 1071 | # renames ${file}.bastille to $file. This backup is made using the | ||
| 1072 | # internal API function &B_backup_file. Further, it sets the new file's | ||
| 1073 | # permissions and uid/gid to the same as the old file. | ||
| 1074 | # | ||
| 1075 | # B_close_plus is the counterpart to B_open_plus, which opened $file and | ||
| 1076 | # $file.bastille with the file handles $handle_original and $handle_file, | ||
| 1077 | # respectively. | ||
| 1078 | # | ||
| 1079 | # &B_close_plus makes the appropriate log entries in the action and error | ||
| 1080 | # logs. | ||
| 1081 | ########################################################################### | ||
| 1082 | |||
| 1083 | sub B_close_plus { | ||
| 1084 | my ($handle_file,$handle_original,$file)=@_; | ||
| 1085 | my ($mode,$uid,$gid); | ||
| 1086 | my @junk; | ||
| 1087 | |||
| 1088 | my $original_file; | ||
| 1089 | |||
| 1090 | my $retval=1; | ||
| 1091 | my $return_file=1; | ||
| 1092 | my $return_old=1; | ||
| 1093 | |||
| 1094 | # Append the global prefix, but save the original for B_backup_file b/c | ||
| 1095 | # it appends the prefix on its own... | ||
| 1096 | |||
| 1097 | $original_file=$file; | ||
| 1098 | |||
| 1099 | # | ||
| 1100 | # Close the files and prepare for the rename | ||
| 1101 | # | ||
| 1102 | |||
| 1103 | if (($file eq "") or (not(-e $file ))) { | ||
| 1104 | &B_log("ERROR","Internal Error, attempted to close a blank filename ". | ||
| 1105 | "or nonexistent file."); | ||
| 1106 | return 0; #False | ||
| 1107 | } | ||
| 1108 | |||
| 1109 | unless ($GLOBAL_LOGONLY) { | ||
| 1110 | $return_file = close $handle_file; | ||
| 1111 | $return_old = close $handle_original; | ||
| 1112 | } | ||
| 1113 | |||
| 1114 | # Error handling/logging here... | ||
| 1115 | #&B_log("ACTION","#Closing $original_file and backing up to " . &getGlobal('BDIR', "backup")); | ||
| 1116 | #&B_log("ACTION","/$original_file\n"); | ||
| 1117 | |||
| 1118 | unless ($return_file) { | ||
| 1119 | $retval=0; | ||
| 1120 | &B_log("ERROR","close $original_file failed...\n"); | ||
| 1121 | } | ||
| 1122 | unless ($return_old) { | ||
| 1123 | $retval=0; | ||
| 1124 | &B_log("ERROR","close $original_file.bastille failed.\n"); | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | # | ||
| 1128 | # If we've had no errors, backup the old file and put the new one | ||
| 1129 | # in its place, with the Right permissions. | ||
| 1130 | # | ||
| 1131 | |||
| 1132 | unless ( ($retval == 0) or $GLOBAL_LOGONLY) { | ||
| 1133 | |||
| 1134 | # Read the permissions/owners on the old file | ||
| 1135 | |||
| 1136 | @junk=stat ($file); | ||
| 1137 | $mode=$junk[2]; | ||
| 1138 | $uid=$junk[4]; | ||
| 1139 | $gid=$junk[5]; | ||
| 1140 | |||
| 1141 | # Set the permissions/owners on the new file | ||
| 1142 | |||
| 1143 | chmod $mode, "$file.bastille" or &B_log("ERROR","Not able to retain permissions on $original_file!!!\n"); | ||
| 1144 | chown $uid, $gid, "$file.bastille" or &B_log("ERROR","Not able to retain owners on $original_file!!!\n"); | ||
| 1145 | |||
| 1146 | # Backup the old file and put a new one in place. | ||
| 1147 | |||
| 1148 | &B_backup_file($original_file); | ||
| 1149 | rename "$file.bastille", $file or | ||
| 1150 | &B_log("ERROR","B_close_plus: not able to move $original_file.bastille to $original_file\n"); | ||
| 1151 | |||
| 1152 | # We add the file to the GLOBAL_SUMS hash if it is not already present | ||
| 1153 | &B_set_sum($file); | ||
| 1154 | |||
| 1155 | } | ||
| 1156 | |||
| 1157 | return $retval; | ||
| 1158 | } | ||
| 1159 | |||
| 1160 | ########################################################################### | ||
| 1161 | # &B_backup_file ($file) makes a backup copy of the file $file in | ||
| 1162 | # &getGlobal('BDIR', "backup"). Note that this routine is intended for internal | ||
| 1163 | # use only -- only Bastille API functions should call B_backup_file. | ||
| 1164 | # | ||
| 1165 | ########################################################################### | ||
| 1166 | |||
| 1167 | sub B_backup_file { | ||
| 1168 | |||
| 1169 | my $file=$_[0]; | ||
| 1170 | my $complain = 1; | ||
| 1171 | my $original_file = $file; | ||
| 1172 | |||
| 1173 | my $backup_dir = &getGlobal('BDIR', "backup"); | ||
| 1174 | my $backup_file = $backup_dir . $original_file; | ||
| 1175 | |||
| 1176 | my $retval=1; | ||
| 1177 | |||
| 1178 | # First, separate the file into the directory and the relative filename | ||
| 1179 | |||
| 1180 | my $directory =""; | ||
| 1181 | if ($file =~ /^(.*)\/([^\/]+)$/) { | ||
| 1182 | #$relative_file=$2; | ||
| 1183 | $directory = $1; | ||
| 1184 | } else { | ||
| 1185 | $directory=cwd; | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | # Now, if the directory does not exist, create it. | ||
| 1189 | # Later: | ||
| 1190 | # Try to set the same permissions on the patch directory that the | ||
| 1191 | # original had...? | ||
| 1192 | |||
| 1193 | unless ( -d ($backup_dir . $directory) ) { | ||
| 1194 | mkpath(( $backup_dir . $directory),0,0700); | ||
| 1195 | |||
| 1196 | } | ||
| 1197 | |||
| 1198 | # Now we backup the file. If there is already a backup file there, | ||
| 1199 | # we will leave it alone, since it exists from a previous run and | ||
| 1200 | # should be the _original_ (possibly user-modified) distro's version | ||
| 1201 | # of the file. | ||
| 1202 | |||
| 1203 | if ( -e $file ) { | ||
| 1204 | |||
| 1205 | unless ( -e $backup_file ) { | ||
| 1206 | my $command=&getGlobal("BIN","cp"); | ||
| 1207 | &B_Backtick("$command -p $file $backup_file"); | ||
| 1208 | &B_revert_log (&getGlobal("BIN","mv"). " $backup_file $file"); | ||
| 1209 | } | ||
| 1210 | |||
| 1211 | } else { | ||
| 1212 | # The file we were trying to backup doesn't exist. | ||
| 1213 | |||
| 1214 | $retval=0; | ||
| 1215 | # This is a non-fatal error, not worth complaining about | ||
| 1216 | $complain = 0; | ||
| 1217 | #&ErrorLog ("# Failed trying to backup file $file -- it doesn't exist!\n"); | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | # Check to make sure that the file does exist in the backup location. | ||
| 1221 | |||
| 1222 | unless ( -e $backup_file ) { | ||
| 1223 | $retval=0; | ||
| 1224 | if ( $complain == 1 ) { | ||
| 1225 | &B_log("ERROR","Failed trying to backup $file -- the copy was not created.\n"); | ||
| 1226 | } | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | return $retval; | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | |||
| 1233 | ########################################################################### | ||
| 1234 | # &B_read_sums reads in the sum.csv file which contains information | ||
| 1235 | # about Bastille modified files. The file structure is as follows: | ||
| 1236 | # | ||
| 1237 | # filename,filesize,cksum | ||
| 1238 | # | ||
| 1239 | # It reads the information into the GLOBAL_SUM hash i.e. | ||
| 1240 | # $GLOBAL_SUM{$file}{sum} = $cksum | ||
| 1241 | # $GLOBAL_SUM{$file}{filesize} = $size | ||
| 1242 | # For the first run of Bastille on a given system this subroutine | ||
| 1243 | # is a no-op, and returns "undefined." | ||
| 1244 | ########################################################################### | ||
| 1245 | |||
| 1246 | sub B_read_sums { | ||
| 1247 | |||
| 1248 | my $sumFile = &getGlobal('BFILE',"sum.csv"); | ||
| 1249 | |||
| 1250 | if ( -e $sumFile ) { | ||
| 1251 | |||
| 1252 | open( SUM, "< $sumFile") or &B_log("ERROR","Unable to open $sumFile for read.\n$!\n"); | ||
| 1253 | |||
| 1254 | while( my $line = <SUM> ) { | ||
| 1255 | chomp $line; | ||
| 1256 | my ($file,$filesize,$sum,$flag) = split /,/, $line; | ||
| 1257 | if(-e $file) { | ||
| 1258 | $GLOBAL_SUM{"$file"}{filesize} = $filesize; | ||
| 1259 | $GLOBAL_SUM{"$file"}{sum} = $sum; | ||
| 1260 | } | ||
| 1261 | } | ||
| 1262 | |||
| 1263 | close(SUM); | ||
| 1264 | } else { | ||
| 1265 | return undef; | ||
| 1266 | } | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | |||
| 1270 | ########################################################################### | ||
| 1271 | # &B_write_sums writes out the sum.csv file which contains information | ||
| 1272 | # about Bastille modified files. The file structure is as follows: | ||
| 1273 | # | ||
| 1274 | # filename,filesize,cksum | ||
| 1275 | # | ||
| 1276 | # It writes the information from the GLOBAL_SUM hash i.e. | ||
| 1277 | # | ||
| 1278 | # $file,$GLOBAL_SUM{$file}{sum},$GLOBAL_SUM{$file}{filesize} | ||
| 1279 | # | ||
| 1280 | # This subroutine requires access to the GLOBAL_SUM hash. | ||
| 1281 | ########################################################################### | ||
| 1282 | |||
| 1283 | sub B_write_sums { | ||
| 1284 | |||
| 1285 | my $sumFile = &getGlobal('BFILE',"sum.csv"); | ||
| 1286 | |||
| 1287 | if ( %GLOBAL_SUM ) { | ||
| 1288 | |||
| 1289 | open( SUM, "> $sumFile") or &B_log("ERROR","Unable to open $sumFile for write.\n$!\n"); | ||
| 1290 | |||
| 1291 | for my $file (sort keys %GLOBAL_SUM) { | ||
| 1292 | if( -e $file) { | ||
| 1293 | print SUM "$file,$GLOBAL_SUM{\"$file\"}{filesize},$GLOBAL_SUM{\"$file\"}{sum}\n"; | ||
| 1294 | } | ||
| 1295 | } | ||
| 1296 | |||
| 1297 | close(SUM); | ||
| 1298 | } | ||
| 1299 | |||
| 1300 | } | ||
| 1301 | |||
| 1302 | |||
| 1303 | ########################################################################### | ||
| 1304 | # &B_check_sum($file) compares the stored cksum and filesize of the given | ||
| 1305 | # file compared to the current cksum and filesize respectively. | ||
| 1306 | # This subroutine also keeps the state of the sum check by setting the | ||
| 1307 | # checked flag which tells the subroutine that on this run this file | ||
| 1308 | # has already been checked. | ||
| 1309 | # | ||
| 1310 | # $GLOBAL_SUM{$file}{checked} = 1; | ||
| 1311 | # | ||
| 1312 | # This subroutine requires access to the GLOBAL_SUM hash. | ||
| 1313 | # | ||
| 1314 | # Returns 1 if sum checks out and 0 if not | ||
| 1315 | ########################################################################### | ||
| 1316 | |||
| 1317 | sub B_check_sum($) { | ||
| 1318 | my $file = $_[0]; | ||
| 1319 | my $cksum = &getGlobal('BIN',"cksum"); | ||
| 1320 | |||
| 1321 | if (not(%GLOBAL_SUM)) { | ||
| 1322 | &B_read_sums; | ||
| 1323 | } | ||
| 1324 | |||
| 1325 | if(-e $file) { | ||
| 1326 | my ($sum,$size,$ckfile) = split(/\s+/, `$cksum $file`); | ||
| 1327 | my $commandRetVal = ($? >> 8); # find the command's return value | ||
| 1328 | |||
| 1329 | if($commandRetVal != 0) { | ||
| 1330 | &B_log("ERROR","$cksum reported the following error:\n$!\n"); | ||
| 1331 | return 0; | ||
| 1332 | } else { | ||
| 1333 | if ( exists $GLOBAL_SUM{$file} ) { | ||
| 1334 | # if the file size or file sum differ from those recorded. | ||
| 1335 | if (( $GLOBAL_SUM{$file}{filesize} == $size) and | ||
| 1336 | ($GLOBAL_SUM{$file}{sum} == $sum )) { | ||
| 1337 | return 1; #True, since saved state matches up, all is well. | ||
| 1338 | } else { | ||
| 1339 | return 0; #False, since saved state doesn't match | ||
| 1340 | } | ||
| 1341 | } else { | ||
| 1342 | &B_log("ERROR","File: $file does not exist in sums database."); | ||
| 1343 | return 0; | ||
| 1344 | } | ||
| 1345 | } | ||
| 1346 | } else { | ||
| 1347 | &B_log("ERROR","The file: $file does not exist for comparison in B_check_sum."); | ||
| 1348 | return 0; | ||
| 1349 | } | ||
| 1350 | } | ||
| 1351 | |||
| 1352 | # Don't think we need this anymore as function now check_sums returns | ||
| 1353 | # results directly | ||
| 1354 | #sub isSumDifferent($) { | ||
| 1355 | # my $file = $_[0]; | ||
| 1356 | # if(exists $GLOBAL_SUM{$file}) { | ||
| 1357 | # return $GLOBAL_SUM{$file}{flag} | ||
| 1358 | # } | ||
| 1359 | #} | ||
| 1360 | |||
| 1361 | sub listModifiedFiles { | ||
| 1362 | my @listModifiedFiles=sort keys %GLOBAL_SUM; | ||
| 1363 | return @listModifiedFiles; | ||
| 1364 | } | ||
| 1365 | |||
| 1366 | ########################################################################### | ||
| 1367 | # &B_isFileinSumDB($file) checks to see if a given file's sum was saved. | ||
| 1368 | # | ||
| 1369 | # $GLOBAL_SUM{$file}{filesize} = $size; | ||
| 1370 | # $GLOBAL_SUM{$file}{sum} = $cksum; | ||
| 1371 | # | ||
| 1372 | # This subroutine requires access to the GLOBAL_SUM hash. | ||
| 1373 | ########################################################################### | ||
| 1374 | |||
| 1375 | sub B_isFileinSumDB($) { | ||
| 1376 | my $file = $_[0]; | ||
| 1377 | |||
| 1378 | if (not(%GLOBAL_SUM)) { | ||
| 1379 | &B_log("DEBUG","Reading in DB from B_isFileinSumDB"); | ||
| 1380 | &B_read_sums; | ||
| 1381 | } | ||
| 1382 | if (exists($GLOBAL_SUM{"$file"})){ | ||
| 1383 | &B_log("DEBUG","$file is in sum database"); | ||
| 1384 | return 1; #true | ||
| 1385 | } else { | ||
| 1386 | &B_log("DEBUG","$file is not in sum database"); | ||
| 1387 | return 0; #false | ||
| 1388 | } | ||
| 1389 | } | ||
| 1390 | |||
| 1391 | ########################################################################### | ||
| 1392 | # &B_set_sum($file) sets the current cksum and filesize of the given | ||
| 1393 | # file into the GLOBAL_SUM hash. | ||
| 1394 | # | ||
| 1395 | # $GLOBAL_SUM{$file}{filesize} = $size; | ||
| 1396 | # $GLOBAL_SUM{$file}{sum} = $cksum; | ||
| 1397 | # | ||
| 1398 | # This subroutine requires access to the GLOBAL_SUM hash. | ||
| 1399 | ########################################################################### | ||
| 1400 | |||
| 1401 | sub B_set_sum($) { | ||
| 1402 | |||
| 1403 | my $file = $_[0]; | ||
| 1404 | my $cksum = &getGlobal('BIN',"cksum"); | ||
| 1405 | if( -e $file) { | ||
| 1406 | |||
| 1407 | my ($sum,$size,$ckfile) = split(/\s+/, `$cksum $file`); | ||
| 1408 | my $commandRetVal = ($? >> 8); # find the command's return value | ||
| 1409 | |||
| 1410 | if($commandRetVal != 0) { | ||
| 1411 | |||
| 1412 | &B_log("ERROR","$cksum reported the following error:\n$!\n"); | ||
| 1413 | |||
| 1414 | } | ||
| 1415 | else { | ||
| 1416 | |||
| 1417 | # new file size and sum are added to the hash | ||
| 1418 | $GLOBAL_SUM{$file}{filesize} = $size; | ||
| 1419 | $GLOBAL_SUM{$file}{sum} = $sum; | ||
| 1420 | &B_write_sums; | ||
| 1421 | |||
| 1422 | } | ||
| 1423 | } else { | ||
| 1424 | &B_log("ERROR","Can not save chksum for file: $file since it does not exist"); | ||
| 1425 | } | ||
| 1426 | } | ||
| 1427 | |||
| 1428 | |||
| 1429 | ########################################################################### | ||
| 1430 | # | ||
| 1431 | # &B_delete_file ($file) deletes the file $file and makes a backup to | ||
| 1432 | # the backup directory. | ||
| 1433 | # | ||
| 1434 | ########################################################################## | ||
| 1435 | |||
| 1436 | |||
| 1437 | sub B_delete_file($) { #Currently Linux only (TMPDIR) | ||
| 1438 | #consideration: should create clear_sum routine if this is ever used to remove | ||
| 1439 | # A Bastille-generated file. | ||
| 1440 | |||
| 1441 | # | ||
| 1442 | # This API routine deletes the named file, backing it up first to the | ||
| 1443 | # backup directory. | ||
| 1444 | # | ||
| 1445 | |||
| 1446 | my $filename=shift @_; | ||
| 1447 | my $retval=1; | ||
| 1448 | |||
| 1449 | # We have to append the prefix ourselves since we don't use B_open_plus | ||
| 1450 | |||
| 1451 | my $original_filename=$filename; | ||
| 1452 | |||
| 1453 | &B_log("ACTION","Deleting (and backing-up) file $original_filename\n"); | ||
| 1454 | &B_log("ACTION","rm $original_filename\n"); | ||
| 1455 | |||
| 1456 | unless ($filename) { | ||
| 1457 | &B_log("ERROR","B_delete_file called with no arguments!\n"); | ||
| 1458 | } | ||
| 1459 | |||
| 1460 | unless ($GLOBAL_LOGONLY) { | ||
| 1461 | if ( B_backup_file($original_filename) ) { | ||
| 1462 | unless ( unlink $filename ) { | ||
| 1463 | &B_log("ERROR","Couldn't unlink file $original_filename"); | ||
| 1464 | $retval=0; | ||
| 1465 | } | ||
| 1466 | } | ||
| 1467 | else { | ||
| 1468 | $retval=0; | ||
| 1469 | &B_log("ERROR","B_delete_file did not delete $original_filename since it could not back it up\n"); | ||
| 1470 | } | ||
| 1471 | } | ||
| 1472 | |||
| 1473 | $retval; | ||
| 1474 | |||
| 1475 | } | ||
| 1476 | |||
| 1477 | |||
| 1478 | ########################################################################### | ||
| 1479 | # &B_create_file ($file) creates the file $file, if it doesn't already | ||
| 1480 | # exist. | ||
| 1481 | # It will set a default mode of 0700 and a default uid/gid or 0/0. | ||
| 1482 | # | ||
| 1483 | # &B_create_file, to support Bastille's revert functionality, writes an | ||
| 1484 | # rm $file command to the end of the file &getGlobal('BFILE', "created-files"). | ||
| 1485 | # | ||
| 1486 | ########################################################################## | ||
| 1487 | |||
| 1488 | |||
| 1489 | sub B_create_file($) { | ||
| 1490 | |||
| 1491 | my $file = $_[0]; | ||
| 1492 | my $retval=1; | ||
| 1493 | |||
| 1494 | # We have to create the file ourselves since we don't use B_open_plus | ||
| 1495 | |||
| 1496 | my $original_file = $file; | ||
| 1497 | |||
| 1498 | if ($file eq ""){ | ||
| 1499 | &B_log("ERROR","Internal Error, attempt made to create blank filename"); | ||
| 1500 | return 0; #False | ||
| 1501 | } | ||
| 1502 | |||
| 1503 | unless ( -e $file ) { | ||
| 1504 | |||
| 1505 | unless ($GLOBAL_LOGONLY) { | ||
| 1506 | |||
| 1507 | # find the directory in which the file is to reside. | ||
| 1508 | my $dirName = dirname($file); | ||
| 1509 | # if the directory does not exist then | ||
| 1510 | if(! -d $dirName) { | ||
| 1511 | # create it. | ||
| 1512 | mkpath ($dirName,0,0700); | ||
| 1513 | } | ||
| 1514 | |||
| 1515 | $retval=open CREATE_FILE,">$file"; | ||
| 1516 | |||
| 1517 | if ($retval) { | ||
| 1518 | close CREATE_FILE; | ||
| 1519 | chmod 0700,$file; | ||
| 1520 | # Make the revert functionality | ||
| 1521 | &B_revert_log( &getGlobal('BIN','rm') . " $original_file \n"); | ||
| 1522 | } else { | ||
| 1523 | &B_log("ERROR","Couldn't create file $original_file even though " . | ||
| 1524 | "it didn't already exist!\n"); | ||
| 1525 | } | ||
| 1526 | } | ||
| 1527 | &B_log("ACTION","Created file $original_file\n"); | ||
| 1528 | } else { | ||
| 1529 | &B_log("DEBUG","Didn't create file $original_file since it already existed.\n"); | ||
| 1530 | $retval=0; | ||
| 1531 | } | ||
| 1532 | |||
| 1533 | $retval; | ||
| 1534 | } | ||
| 1535 | |||
| 1536 | |||
| 1537 | ########################################################################### | ||
| 1538 | # &B_create_dir ($dir) creates the directory $dir, if it doesn't already | ||
| 1539 | # exist. | ||
| 1540 | # It will set a default mode of 0700 and a default uid/gid or 0/0. | ||
| 1541 | # | ||
| 1542 | ########################################################################## | ||
| 1543 | |||
| 1544 | |||
| 1545 | sub B_create_dir($) { | ||
| 1546 | |||
| 1547 | my $dir = $_[0]; | ||
| 1548 | my $retval=1; | ||
| 1549 | |||
| 1550 | # We have to append the prefix ourselves since we don't use B_open_plus | ||
| 1551 | |||
| 1552 | my $original_dir=$dir; | ||
| 1553 | |||
| 1554 | unless ( -d $dir ) { | ||
| 1555 | unless ($GLOBAL_LOGONLY) { | ||
| 1556 | $retval=mkdir $dir,0700; | ||
| 1557 | |||
| 1558 | if ($retval) { | ||
| 1559 | # Make the revert functionality | ||
| 1560 | &B_revert_log (&getGlobal('BIN','rmdir') . " $original_dir\n"); | ||
| 1561 | } | ||
| 1562 | else { | ||
| 1563 | &B_log("ERROR","Couldn't create dir $original_dir even though it didn't already exist!"); | ||
| 1564 | } | ||
| 1565 | |||
| 1566 | } | ||
| 1567 | &B_log("ACTION","Created directory $original_dir\n"); | ||
| 1568 | } | ||
| 1569 | else { | ||
| 1570 | &B_log("ACTION","Didn't create directory $original_dir since it already existed.\n"); | ||
| 1571 | $retval=0; | ||
| 1572 | } | ||
| 1573 | |||
| 1574 | $retval; | ||
| 1575 | } | ||
| 1576 | |||
| 1577 | |||
| 1578 | |||
| 1579 | ########################################################################### | ||
| 1580 | # &B_symlink ($original_file,$new_symlink) creates a symbolic link from | ||
| 1581 | # $original_file to $new_symlink. | ||
| 1582 | # | ||
| 1583 | # &B_symlink respects $GLOBAL_LOGONLY. It supports | ||
| 1584 | # the revert functionality that you've come to know and love by adding every | ||
| 1585 | # symbolic link it creates to &getGlobal('BFILE', "created-symlinks"), currently set to: | ||
| 1586 | # | ||
| 1587 | # /root/Bastille/revert/revert-created-symlinks | ||
| 1588 | # | ||
| 1589 | # The revert script, if it works like I think it should, will run this file, | ||
| 1590 | # which should be a script or rm's... | ||
| 1591 | # | ||
| 1592 | ########################################################################## | ||
| 1593 | |||
| 1594 | sub B_symlink($$) { | ||
| 1595 | my ($source_file,$new_symlink)=@_; | ||
| 1596 | my $retval=1; | ||
| 1597 | my $original_source = $source_file; | ||
| 1598 | my $original_symlink = $new_symlink; | ||
| 1599 | |||
| 1600 | unless ($GLOBAL_LOGONLY) { | ||
| 1601 | $retval=symlink $source_file,$new_symlink; | ||
| 1602 | if ($retval) { | ||
| 1603 | &B_revert_log (&getGlobal('BIN',"rm") . " $original_symlink\n"); | ||
| 1604 | } | ||
| 1605 | } | ||
| 1606 | |||
| 1607 | &B_log("ACTION", "Created a symbolic link called $original_symlink from $original_source\n"); | ||
| 1608 | &B_log("ACTION", "symlink \"$original_source\",\"$original_symlink\";\n"); | ||
| 1609 | unless ($retval) { | ||
| 1610 | &B_log("ERROR","Couldn't symlink $original_symlink -> $original_source\n"); | ||
| 1611 | } | ||
| 1612 | |||
| 1613 | $retval; | ||
| 1614 | |||
| 1615 | } | ||
| 1616 | |||
| 1617 | |||
| 1618 | sub B_cp($$) { | ||
| 1619 | |||
| 1620 | my ($source,$target)=@_; | ||
| 1621 | my $retval=0; | ||
| 1622 | |||
| 1623 | my $had_to_backup_target=0; | ||
| 1624 | |||
| 1625 | use File::Copy; | ||
| 1626 | |||
| 1627 | my $original_source=$source; | ||
| 1628 | my $original_target=$target; | ||
| 1629 | |||
| 1630 | if( -e $target and -f $target ) { | ||
| 1631 | &B_backup_file($original_target); | ||
| 1632 | &B_log("ACTION","About to copy $original_source to $original_target -- had to backup target\n"); | ||
| 1633 | $had_to_backup_target=1; | ||
| 1634 | } | ||
| 1635 | |||
| 1636 | $retval=copy($source,$target); | ||
| 1637 | if ($retval) { | ||
| 1638 | &B_log("ACTION","cp $original_source $original_target\n"); | ||
| 1639 | |||
| 1640 | # | ||
| 1641 | # We want to add a line to the &getGlobal('BFILE', "created-files") so that the | ||
| 1642 | # file we just put at $original_target gets deleted. | ||
| 1643 | # | ||
| 1644 | &B_revert_log(&getGlobal('BIN',"rm") . " $original_target\n"); | ||
| 1645 | } else { | ||
| 1646 | &B_log("ERROR","Failed to copy $original_source to $original_target\n"); | ||
| 1647 | } | ||
| 1648 | # We add the file to the GLOBAL_SUMS hash if it is not already present | ||
| 1649 | &B_set_sum($target); | ||
| 1650 | $retval; | ||
| 1651 | } | ||
| 1652 | |||
| 1653 | |||
| 1654 | |||
| 1655 | ############################################################################ | ||
| 1656 | # &B_place puts a file in place, using Perl's File::cp. This file is taken | ||
| 1657 | # from &getGlobal('BDIR', "share") and is used to place a file that came with | ||
| 1658 | # Bastille. | ||
| 1659 | # | ||
| 1660 | # This should be DEPRECATED in favor of &B_cp, since the only reason it exists | ||
| 1661 | # is because of GLOBAL_PREFIX, which has been broken for quite some time. | ||
| 1662 | # Otherwise, the two routines are identical. | ||
| 1663 | # | ||
| 1664 | # It respects $GLOBAL_LOGONLY. | ||
| 1665 | # If $target is an already-existing file, it is backed up. | ||
| 1666 | # | ||
| 1667 | # revert either appends another "rm $target" to &getGlobal('BFILE', "revert-actions") or | ||
| 1668 | # backs up the file that _was_ there into the &getGlobal('BDIR', "backup"), | ||
| 1669 | # appending a "mv" to revert-actions to put it back. | ||
| 1670 | # | ||
| 1671 | ############################################################################ | ||
| 1672 | |||
| 1673 | sub B_place { # Only Linux references left (Firewall / TMPDIR) | ||
| 1674 | |||
| 1675 | my ($source,$target)=@_; | ||
| 1676 | my $retval=0; | ||
| 1677 | |||
| 1678 | my $had_to_backup_target=0; | ||
| 1679 | |||
| 1680 | use File::Copy; | ||
| 1681 | |||
| 1682 | my $original_source=$source; | ||
| 1683 | $source = &getGlobal('BDIR', "share") . $source; | ||
| 1684 | my $original_target=$target; | ||
| 1685 | |||
| 1686 | if ( -e $target and -f $target ) { | ||
| 1687 | &B_backup_file($original_target); | ||
| 1688 | &B_log("ACTION","About to copy $original_source to $original_target -- had to backup target\n"); | ||
| 1689 | $had_to_backup_target=1; | ||
| 1690 | } | ||
| 1691 | $retval=copy($source,$target); | ||
| 1692 | if ($retval) { | ||
| 1693 | &B_log("ACTION","placed file $original_source as $original_target\n"); | ||
| 1694 | # | ||
| 1695 | # We want to add a line to the &getGlobal('BFILE', "created-files") so that the | ||
| 1696 | # file we just put at $original_target gets deleted. | ||
| 1697 | &B_revert_log(&getGlobal('BIN',"rm") . " $original_target\n"); | ||
| 1698 | } else { | ||
| 1699 | &B_log("ERROR","Failed to place $original_source as $original_target\n"); | ||
| 1700 | } | ||
| 1701 | |||
| 1702 | # We add the file to the GLOBAL_SUMS hash if it is not already present | ||
| 1703 | &B_set_sum($target); | ||
| 1704 | |||
| 1705 | $retval; | ||
| 1706 | } | ||
| 1707 | |||
| 1708 | |||
| 1709 | |||
| 1710 | |||
| 1711 | |||
| 1712 | ############################################################################# | ||
| 1713 | ############################################################################# | ||
| 1714 | ############################################################################# | ||
| 1715 | |||
| 1716 | ########################################################################### | ||
| 1717 | # &B_mknod ($file) creates the node $file, if it doesn't already | ||
| 1718 | # exist. It uses the prefix and suffix, like this: | ||
| 1719 | # | ||
| 1720 | # mknod $prefix $file $suffix | ||
| 1721 | # | ||
| 1722 | # This is just a wrapper to the mknod program, which tries to introduce | ||
| 1723 | # revert functionality, by writing rm $file to the end of the | ||
| 1724 | # file &getGlobal('BFILE', "created-files"). | ||
| 1725 | # | ||
| 1726 | ########################################################################## | ||
| 1727 | |||
| 1728 | |||
| 1729 | sub B_mknod($$$) { | ||
| 1730 | |||
| 1731 | my ($prefix,$file,$suffix) = @_; | ||
| 1732 | my $retval=1; | ||
| 1733 | |||
| 1734 | # We have to create the filename ourselves since we don't use B_open_plus | ||
| 1735 | |||
| 1736 | my $original_file = $file; | ||
| 1737 | |||
| 1738 | unless ( -e $file ) { | ||
| 1739 | my $command = &getGlobal("BIN","mknod") . " $prefix $file $suffix"; | ||
| 1740 | |||
| 1741 | if ( system($command) == 0) { | ||
| 1742 | # Since system will return 0 on success, invert the error code | ||
| 1743 | $retval=1; | ||
| 1744 | } | ||
| 1745 | else { | ||
| 1746 | $retval=0; | ||
| 1747 | } | ||
| 1748 | |||
| 1749 | if ($retval) { | ||
| 1750 | |||
| 1751 | # Make the revert functionality | ||
| 1752 | &B_revert_log(&getGlobal('BIN',"rm") . " $original_file\n"); | ||
| 1753 | } else { | ||
| 1754 | &B_log("ERROR","Couldn't mknod $prefix $original_file $suffix even though it didn't already exist!\n"); | ||
| 1755 | } | ||
| 1756 | |||
| 1757 | |||
| 1758 | &B_log("ACTION","mknod $prefix $original_file $suffix\n"); | ||
| 1759 | } | ||
| 1760 | else { | ||
| 1761 | &B_log("ACTION","Didn't mknod $prefix $original_file $suffix since $original_file already existed.\n"); | ||
| 1762 | $retval=0; | ||
| 1763 | } | ||
| 1764 | |||
| 1765 | $retval; | ||
| 1766 | } | ||
| 1767 | |||
| 1768 | ########################################################################### | ||
| 1769 | # &B_revert_log("reverse_command") prepends a command to a shell script. This | ||
| 1770 | # shell script is intended to be run by bastille -r to reverse the changes that | ||
| 1771 | # Bastille made, returning the files which Bastille changed to their original | ||
| 1772 | # state. | ||
| 1773 | ########################################################################### | ||
| 1774 | |||
| 1775 | sub B_revert_log($) { | ||
| 1776 | |||
| 1777 | my $revert_command = $_[0]; | ||
| 1778 | my $revert_actions = &getGlobal('BFILE', "revert-actions"); | ||
| 1779 | my $revertdir= &getGlobal('BDIR', "revert"); | ||
| 1780 | my @lines; | ||
| 1781 | |||
| 1782 | |||
| 1783 | if (! (-e $revert_actions)) { | ||
| 1784 | mkpath($revertdir); #if this doesn't work next line catches | ||
| 1785 | if (open REVERT_ACTIONS,">" . $revert_actions){ # create revert file | ||
| 1786 | close REVERT_ACTIONS; # chown to root, rwx------ | ||
| 1787 | chmod 0700,$revert_actions; | ||
| 1788 | chown 0,0,$revert_actions; | ||
| 1789 | } | ||
| 1790 | else { | ||
| 1791 | &B_log("FATAL","Can not create revert-actions file: $revert_actions.\n" . | ||
| 1792 | " Unable to add the following command to the revert\n" . | ||
| 1793 | " actions script: $revert_command\n"); | ||
| 1794 | } | ||
| 1795 | |||
| 1796 | } | ||
| 1797 | |||
| 1798 | &B_open_plus (*REVERT_NEW, *REVERT_OLD, $revert_actions); | ||
| 1799 | |||
| 1800 | while (my $line=<REVERT_OLD>) { #copy file into @lines | ||
| 1801 | push (@lines,$line); | ||
| 1802 | } | ||
| 1803 | print REVERT_NEW $revert_command . "\n"; #make the revert command first in the new file | ||
| 1804 | while (my $line = shift @lines) { #write the rest of the lines of the file | ||
| 1805 | print REVERT_NEW $line; | ||
| 1806 | } | ||
| 1807 | close REVERT_OLD; | ||
| 1808 | close REVERT_NEW; | ||
| 1809 | if (rename "${revert_actions}.bastille", $revert_actions) { #replace the old file with the new file we | ||
| 1810 | chmod 0700,$revert_actions; # just made / mirrors B_close_plus logic | ||
| 1811 | chown 0,0,$revert_actions; | ||
| 1812 | } else { | ||
| 1813 | &B_log("ERROR","B_revert_log: not able to move ${revert_actions}.bastille to ${revert_actions}!!! $!) !!!\n"); | ||
| 1814 | } | ||
| 1815 | } | ||
| 1816 | |||
| 1817 | |||
| 1818 | ########################################################################### | ||
| 1819 | # &getGlobalConfig($$) | ||
| 1820 | # | ||
| 1821 | # returns the requested GLOBAL_CONFIG hash value, ignoring the error | ||
| 1822 | # if the value does not exist (because every module uses this to find | ||
| 1823 | # out if the question was answered "Y") | ||
| 1824 | ########################################################################### | ||
| 1825 | sub getGlobalConfig ($$) { | ||
| 1826 | my $module = $_[0]; | ||
| 1827 | my $key = $_[1]; | ||
| 1828 | if (exists $GLOBAL_CONFIG{$module}{$key}) { | ||
| 1829 | my $answer=$GLOBAL_CONFIG{$module}{$key}; | ||
| 1830 | &B_log("ACTION","Answer to question $module.$key is \"$answer\".\n"); | ||
| 1831 | return $answer; | ||
| 1832 | } else { | ||
| 1833 | &B_log("ACTION","Answer to question $module.$key is undefined."); | ||
| 1834 | return undef; | ||
| 1835 | } | ||
| 1836 | } | ||
| 1837 | |||
| 1838 | ########################################################################### | ||
| 1839 | # &getGlobal($$) | ||
| 1840 | # | ||
| 1841 | # returns the requested GLOBAL_* hash value, and logs an error | ||
| 1842 | # if the variable does not exist. | ||
| 1843 | ########################################################################### | ||
| 1844 | sub getGlobal ($$) { | ||
| 1845 | my $type = uc($_[0]); | ||
| 1846 | my $key = $_[1]; | ||
| 1847 | |||
| 1848 | # define a mapping from the first argument to the proper hash | ||
| 1849 | my %map = ("BIN" => \%GLOBAL_BIN, | ||
| 1850 | "FILE" => \%GLOBAL_FILE, | ||
| 1851 | "BFILE" => \%GLOBAL_BFILE, | ||
| 1852 | "DIR" => \%GLOBAL_DIR, | ||
| 1853 | "BDIR" => \%GLOBAL_BDIR, | ||
| 1854 | "ERROR" => \%GLOBAL_ERROR, | ||
| 1855 | "SERVICE" => \%GLOBAL_SERVICE, | ||
| 1856 | "SERVTYPE" => \%GLOBAL_SERVTYPE, | ||
| 1857 | "PROCESS" => \%GLOBAL_PROCESS, | ||
| 1858 | "RCCONFIG" => \%GLOBAL_RC_CONFIG | ||
| 1859 | ); | ||
| 1860 | |||
| 1861 | # check to see if the desired key is in the desired hash | ||
| 1862 | if (exists $map{$type}->{$key}) { | ||
| 1863 | # get the value from the right hash with the key | ||
| 1864 | return $map{$type}->{$key}; | ||
| 1865 | } else { | ||
| 1866 | # i.e. Bastille tried to use $GLOBAL_BIN{'cp'} but it does not exist. | ||
| 1867 | # Note that we can't use B_log, since it uses getGlobal ... recursive before | ||
| 1868 | # configureForDistro is run. | ||
| 1869 | print STDERR "ERROR: Bastille tried to use \$GLOBAL_${type}\{\'$key\'} but it does not exist.\n"; | ||
| 1870 | return undef; | ||
| 1871 | } | ||
| 1872 | } | ||
| 1873 | |||
| 1874 | ########################################################################### | ||
| 1875 | # &getGlobal($$) | ||
| 1876 | # | ||
| 1877 | # sets the requested GLOBAL_* hash value | ||
| 1878 | ########################################################################### | ||
| 1879 | sub setGlobal ($$$) { | ||
| 1880 | my $type = uc($_[0]); | ||
| 1881 | my $key = $_[1]; | ||
| 1882 | my $input_value = $_[2]; | ||
| 1883 | |||
| 1884 | # define a mapping from the first argument to the proper hash | ||
| 1885 | my %map = ("BIN" => \%GLOBAL_BIN, | ||
| 1886 | "FILE" => \%GLOBAL_FILE, | ||
| 1887 | "BFILE" => \%GLOBAL_BFILE, | ||
| 1888 | "DIR" => \%GLOBAL_DIR, | ||
| 1889 | "BDIR" => \%GLOBAL_BDIR, | ||
| 1890 | "ERROR" => \%GLOBAL_ERROR, | ||
| 1891 | "SERVICE" => \%GLOBAL_SERVICE, | ||
| 1892 | "SERVTYPE" => \%GLOBAL_SERVTYPE, | ||
| 1893 | "PROCESS" => \%GLOBAL_PROCESS, | ||
| 1894 | ); | ||
| 1895 | |||
| 1896 | if ($map{$type}->{$key} = $input_value) { | ||
| 1897 | return 1; | ||
| 1898 | } else { | ||
| 1899 | &B_log('ERROR','Internal Error, Unable to set global config value:' . $type . ", " .$key); | ||
| 1900 | return 0; | ||
| 1901 | } | ||
| 1902 | } | ||
| 1903 | |||
| 1904 | |||
| 1905 | ########################################################################### | ||
| 1906 | # &showDisclaimer: | ||
| 1907 | # Print the disclaimer and wait for 2 minutes for acceptance | ||
| 1908 | # Do NOT do so if any of the following conditions hold | ||
| 1909 | # 1. the -n option was used | ||
| 1910 | # 2. the file ~/.bastille_disclaimer exists | ||
| 1911 | ########################################################################### | ||
| 1912 | |||
| 1913 | sub showDisclaimer($) { | ||
| 1914 | |||
| 1915 | my $nodisclaim = $_[0]; | ||
| 1916 | my $nodisclaim_file = &getGlobal('BFILE', "nodisclaimer"); | ||
| 1917 | my $response; | ||
| 1918 | my $WAIT_TIME = 300; # we'll wait for 5 minutes | ||
| 1919 | my $developersAnd; | ||
| 1920 | my $developersOr; | ||
| 1921 | if ($GLOBAL_OS =~ "^HP-UX") { | ||
| 1922 | $developersAnd ="HP AND ITS"; | ||
| 1923 | $developersOr ="HP OR ITS"; | ||
| 1924 | }else{ | ||
| 1925 | $developersAnd ="JAY BEALE, THE BASTILLE DEVELOPERS, AND THEIR"; | ||
| 1926 | $developersOr ="JAY BEALE, THE BASTILLE DEVELOPERS, OR THEIR"; | ||
| 1927 | } | ||
| 1928 | my $DISCLAIMER = | ||
| 1929 | "\n" . | ||
| 1930 | "Copyright (C) 1999-2006 Jay Beale\n" . | ||
| 1931 | "Copyright (C) 1999-2001 Peter Watkins\n" . | ||
| 1932 | "Copyright (C) 2000 Paul L. Allen\n" . | ||
| 1933 | "Copyright (C) 2001-2007 Hewlett-Packard Development Company, L.P.\n" . | ||
| 1934 | "Bastille is free software; you are welcome to redistribute it under\n" . | ||
| 1935 | "certain conditions. See the \'COPYING\' file in your distribution for terms.\n\n" . | ||
| 1936 | "DISCLAIMER. Use of Bastille can help optimize system security, but does not\n" . | ||
| 1937 | "guarantee system security. Information about security obtained through use of\n" . | ||
| 1938 | "Bastille is provided on an AS-IS basis only and is subject to change without\n" . | ||
| 1939 | "notice. Customer acknowledges they are responsible for their system\'s security.\n" . | ||
| 1940 | "TO THE EXTENT ALLOWED BY LOCAL LAW, Bastille (\"SOFTWARE\") IS PROVIDED TO YOU \n" . | ||
| 1941 | "\"AS IS\" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, WHETHER ORAL OR WRITTEN,\n" . | ||
| 1942 | "EXPRESS OR IMPLIED. $developersAnd SUPPLIERS\n" . | ||
| 1943 | "DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE \n" . | ||
| 1944 | "IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n" . | ||
| 1945 | "Some countries, states and provinces do not allow exclusions of implied\n" . | ||
| 1946 | "warranties or conditions, so the above exclusion may not apply to you. You may\n" . | ||
| 1947 | "have other rights that vary from country to country, state to state, or province\n" . | ||
| 1948 | "to province. EXCEPT TO THE EXTENT PROHIBITED BY LOCAL LAW, IN NO EVENT WILL\n" . | ||
| 1949 | "$developersOr SUBSIDIARIES, AFFILIATES OR\n" . | ||
| 1950 | "SUPPLIERS BE LIABLE FOR DIRECT, SPECIAL, INCIDENTAL, CONSEQUENTIAL OR OTHER\n" . | ||
| 1951 | "DAMAGES (INCLUDING LOST PROFIT, LOST DATA, OR DOWNTIME COSTS), ARISING OUT OF\n" . | ||
| 1952 | "THE USE, INABILITY TO USE, OR THE RESULTS OF USE OF THE SOFTWARE, WHETHER BASED\n" . | ||
| 1953 | "IN WARRANTY, CONTRACT, TORT OR OTHER LEGAL THEORY, AND WHETHER OR NOT ADVISED\n" . | ||
| 1954 | "OF THE POSSIBILITY OF SUCH DAMAGES. Your use of the Software is entirely at your\n" . | ||
| 1955 | "own risk. Should the Software prove defective, you assume the entire cost of all\n" . | ||
| 1956 | "service, repair or correction. Some countries, states and provinces do not allow\n" . | ||
| 1957 | "the exclusion or limitation of liability for incidental or consequential \n" . | ||
| 1958 | "damages, so the above limitation may not apply to you. This notice will only \n". | ||
| 1959 | "display on the first run on a given system.\n". | ||
| 1960 | "To suppress the disclaimer on other machines, use Bastille\'s -n flag (example: bastille -n).\n"; | ||
| 1961 | |||
| 1962 | |||
| 1963 | # If the user has specified not to show the disclaimer, or | ||
| 1964 | # the .bastille_disclaimer file already exists, then return | ||
| 1965 | if( ( $nodisclaim ) || -e $nodisclaim_file ) { return 1; } | ||
| 1966 | |||
| 1967 | # otherwise, show the disclaimer | ||
| 1968 | print ($DISCLAIMER); | ||
| 1969 | |||
| 1970 | # there is a response | ||
| 1971 | my $touch = &getGlobal('BIN', "touch"); | ||
| 1972 | my $retVal = system("$touch $nodisclaim_file"); | ||
| 1973 | if( $retVal != 0 ) { | ||
| 1974 | &ErrorLog ( &getGlobal('ERROR','disclaimer')); | ||
| 1975 | } | ||
| 1976 | } # showDisclaimer | ||
| 1977 | |||
| 1978 | |||
| 1979 | |||
| 1980 | |||
| 1981 | ################################################################ | ||
| 1982 | # &systemCall | ||
| 1983 | #Function used by exported methods B_Backtick and B_system | ||
| 1984 | #to handle the mechanics of system calls. | ||
| 1985 | # This function also manages error handling. | ||
| 1986 | # Input: a system call | ||
| 1987 | # Output: a list containing the status, sstdout and stderr | ||
| 1988 | # of the the system call | ||
| 1989 | # | ||
| 1990 | ################################################################ | ||
| 1991 | sub systemCall ($){ | ||
| 1992 | no strict; | ||
| 1993 | local $command=$_[0]; # changed scoping so eval below can read it | ||
| 1994 | |||
| 1995 | local $SIG{'ALRM'} = sub { die "timeout" }; # This subroutine exits the "eval" below. The program | ||
| 1996 | # can then move on to the next operation. Used "local" | ||
| 1997 | # to avoid name space collision with disclaim alarm. | ||
| 1998 | local $WAIT_TIME=120; # Wait X seconds for system commands | ||
| 1999 | local $commandOutput = ''; | ||
| 2000 | my $errOutput = ''; | ||
| 2001 | eval{ | ||
| 2002 | $errorFile = &getGlobal('BFILE','stderrfile'); | ||
| 2003 | unlink($errorFile); #To make sure we don't mix output | ||
| 2004 | alarm($WAIT_TIME); # start a time-out for command to complete. Some commands hang, and we want to | ||
| 2005 | # fail gracefully. When we call "die" it exits this eval statement | ||
| 2006 | # with a value we use below | ||
| 2007 | $commandOutput = `$command 2> $errorFile`; # run the command and gather its output | ||
| 2008 | my $commandRetVal = ($? >> 8); # find the commands return value | ||
| 2009 | if ($commandRetVal == 0) { | ||
| 2010 | &B_log("ACTION","Executed Command: " . $command . "\n"); | ||
| 2011 | &B_log("ACTION","Command Output: " . $commandOutput . "\n"); | ||
| 2012 | die "success"; | ||
| 2013 | } else { | ||
| 2014 | die "failure"; | ||
| 2015 | }; | ||
| 2016 | }; | ||
| 2017 | |||
| 2018 | my $exitcode=$@; | ||
| 2019 | alarm(0); # End of the timed operation | ||
| 2020 | |||
| 2021 | my $cat = &getGlobal("BIN","cat"); | ||
| 2022 | if ( -e $errorFile ) { | ||
| 2023 | $errOutput = `$cat $errorFile`; | ||
| 2024 | } | ||
| 2025 | |||
| 2026 | if ($exitcode) { # The eval command above will exit with one of the 3 values below | ||
| 2027 | if ($exitcode =~ /timeout/) { | ||
| 2028 | &B_log("WARNING","No response received from $command after $WAIT_TIME seconds.\n" . | ||
| 2029 | "Command Output: " . $commandOutput . "\n"); | ||
| 2030 | return (0,'',''); | ||
| 2031 | } elsif ($exitcode =~ /success/) { | ||
| 2032 | return (1,$commandOutput,$errOutput); | ||
| 2033 | } elsif ($exitcode =~ /failure/) { | ||
| 2034 | return (0,$commandOutput,$errOutput); | ||
| 2035 | } else { | ||
| 2036 | &B_log("FATAL","Unexpected return state from command execution: $command\n" . | ||
| 2037 | "Command Output: " . $commandOutput . "\n"); | ||
| 2038 | } | ||
| 2039 | } | ||
| 2040 | } | ||
| 2041 | |||
| 2042 | ############################################# | ||
| 2043 | # Use this **only** for commands used that are | ||
| 2044 | # intended to test system state and | ||
| 2045 | # not make any system change. Use this in place of the | ||
| 2046 | # prior use of "backticks throughout Bastille | ||
| 2047 | # Handles basic output redirection, but not for stdin | ||
| 2048 | # Input: Command | ||
| 2049 | # Output: Results | ||
| 2050 | ############################################# | ||
| 2051 | |||
| 2052 | sub B_Backtick($) { | ||
| 2053 | my $command=$_[0]; | ||
| 2054 | my $combineOutput=0; | ||
| 2055 | my $stdoutRedir = ""; | ||
| 2056 | my $stderrRedir = ""; | ||
| 2057 | my $echo = &getGlobal('BIN','echo'); | ||
| 2058 | |||
| 2059 | if (($command =~ s/2>&1//) or | ||
| 2060 | (s/>&2//)){ | ||
| 2061 | $combineOutput=1; | ||
| 2062 | } | ||
| 2063 | if ($command =~ s/>\s*([^>\s])+// ) { | ||
| 2064 | $stdoutRedir = $1; | ||
| 2065 | } | ||
| 2066 | if ($command =~ s/2>\s*([^>\s])+// ) { | ||
| 2067 | $stderrRedir = $1; | ||
| 2068 | } | ||
| 2069 | |||
| 2070 | my ($ranFine, $stdout, $stderr) = &systemCall($command); | ||
| 2071 | if ($ranFine) { | ||
| 2072 | &B_log("DEBUG","Command: $command succeeded for test with output: $stdout , ". | ||
| 2073 | "and stderr: $stderr"); | ||
| 2074 | } else { | ||
| 2075 | &B_log("DEBUG","Command: $command failed for test with output: $stdout , ". | ||
| 2076 | "and stderr: $stderr"); | ||
| 2077 | } | ||
| 2078 | if ($combineOutput) { | ||
| 2079 | $stdout .= $stderr; | ||
| 2080 | $stderr = $stdout; #these should be the same | ||
| 2081 | } | ||
| 2082 | if ($stdoutRedir ne "") { | ||
| 2083 | system("$echo \'$stdout\' > $stdoutRedir"); | ||
| 2084 | } | ||
| 2085 | if ($stderrRedir ne "") { | ||
| 2086 | system("$echo \'$stderr\' > $stderrRedir"); | ||
| 2087 | } | ||
| 2088 | return $stdout; | ||
| 2089 | } | ||
| 2090 | |||
| 2091 | #################################################################### | ||
| 2092 | # &B_System($command,$revertcommand); | ||
| 2093 | # This function executes a command, then places the associated | ||
| 2094 | # revert command in revert file. It takes two parameters, the | ||
| 2095 | # command and the command that reverts that command. | ||
| 2096 | # | ||
| 2097 | # uses ActionLog and ErrorLog for logging purposes. | ||
| 2098 | ################################################################### | ||
| 2099 | sub B_System ($$) { | ||
| 2100 | my ($command,$revertcmd)=@_; | ||
| 2101 | |||
| 2102 | my ($ranFine, $stdout, $stderr) = &systemCall($command); | ||
| 2103 | if ($ranFine) { | ||
| 2104 | &B_revert_log ("$revertcmd \n"); | ||
| 2105 | if ($stderr ne '' ) { | ||
| 2106 | &B_log("ACTION",$command . "suceeded with STDERR: " . | ||
| 2107 | $stderr . "\n"); | ||
| 2108 | } | ||
| 2109 | return 1; | ||
| 2110 | } else { | ||
| 2111 | my $warningString = "Command Failed: " . $command . "\n" . | ||
| 2112 | "Command Output: " . $stdout . "\n"; | ||
| 2113 | if ($stderr ne '') { | ||
| 2114 | $warningString .= "Error message: " . $stderr; | ||
| 2115 | } | ||
| 2116 | &B_log("WARNING", $warningString); | ||
| 2117 | return 0; | ||
| 2118 | } | ||
| 2119 | } | ||
| 2120 | |||
| 2121 | |||
| 2122 | ########################################################################### | ||
| 2123 | # &isProcessRunning($procPattern); | ||
| 2124 | # | ||
| 2125 | # If called in scalar context this subroutine will return a 1 if the | ||
| 2126 | # pattern specified can be matched against the process table. It will | ||
| 2127 | # return a 0 otherwise. | ||
| 2128 | # If called in the list context this subroutine will return the list | ||
| 2129 | # of processes which matched the pattern supplied | ||
| 2130 | # | ||
| 2131 | # scalar return values: | ||
| 2132 | # 0: pattern not in process table | ||
| 2133 | # 1: pattern is in process table | ||
| 2134 | # | ||
| 2135 | # list return values: | ||
| 2136 | # proc lines from the process table if they are found | ||
| 2137 | ########################################################################### | ||
| 2138 | sub isProcessRunning($) { | ||
| 2139 | |||
| 2140 | my $procPattern= $_[0]; | ||
| 2141 | my $ps = &getGlobal('BIN',"ps"); | ||
| 2142 | |||
| 2143 | my $isRunning=0; | ||
| 2144 | # process table. | ||
| 2145 | my @psTable = `$ps -elf`; | ||
| 2146 | # list of processes that match the $procPattern | ||
| 2147 | my @procList; | ||
| 2148 | foreach my $process (@psTable) { | ||
| 2149 | if($process =~ $procPattern) { | ||
| 2150 | $isRunning = 1; | ||
| 2151 | push @procList, $process . "\n"; | ||
| 2152 | } | ||
| 2153 | } | ||
| 2154 | |||
| 2155 | &B_log("DEBUG","$procPattern search yielded $isRunning\n\n"); | ||
| 2156 | # if this subroutine was called in scalar context | ||
| 2157 | if( ! wantarray ) { | ||
| 2158 | return $isRunning; | ||
| 2159 | } | ||
| 2160 | |||
| 2161 | return @procList; | ||
| 2162 | } | ||
| 2163 | |||
| 2164 | |||
| 2165 | ########################################################################### | ||
| 2166 | # &checkProcsForService($service); | ||
| 2167 | # | ||
| 2168 | # Checks if the given service is running by analyzing the process table. | ||
| 2169 | # This is a helper function to checkServiceOnLinux and checkServiceOnHP | ||
| 2170 | # | ||
| 2171 | # Return values: | ||
| 2172 | # SECURE_CANT_CHANGE() if the service is off | ||
| 2173 | # INCONSISTENT() if the state of the service cannot be determined | ||
| 2174 | # | ||
| 2175 | # Mostly used in "check service" direct-return context, but added option use. | ||
| 2176 | # to ignore warning if a check for a service ... where a found service doesn't | ||
| 2177 | # have direct security problems. | ||
| 2178 | # | ||
| 2179 | ########################################################################### | ||
| 2180 | sub checkProcsForService ($;$) { | ||
| 2181 | my $service=$_[0]; | ||
| 2182 | my $ignore_warning=$_[1]; | ||
| 2183 | |||
| 2184 | my @psnames=@{ &getGlobal('PROCESS',$service)}; | ||
| 2185 | |||
| 2186 | my @processes; | ||
| 2187 | # inetd services don't have a separate process | ||
| 2188 | foreach my $psname (@psnames) { | ||
| 2189 | my @procList = &isProcessRunning($psname); | ||
| 2190 | if(@procList >= 0){ | ||
| 2191 | splice @processes,$#processes+1,0,@procList; | ||
| 2192 | } | ||
| 2193 | } | ||
| 2194 | |||
| 2195 | if($#processes >= 0){ | ||
| 2196 | if ((defined($ignore_warning)) and ($ignore_warning eq "ignore_warning")) { | ||
| 2197 | &B_log("WARNING","The following processes were still running even though " . | ||
| 2198 | "the corresponding service appears to be turned off. Bastille " . | ||
| 2199 | "question and action will be skipped.\n\n" . | ||
| 2200 | "@processes\n\n"); | ||
| 2201 | # processes were still running, service is not off, but we don't know how | ||
| 2202 | # to configure it so we skip the question | ||
| 2203 | return INCONSISTENT(); | ||
| 2204 | } else { | ||
| 2205 | return NOTSECURE_CAN_CHANGE(); # In the case we're ignoring the warning, | ||
| 2206 | # ie: checking to make *sure* a process | ||
| 2207 | # is running, the answer isn't inconsistent | ||
| 2208 | } | ||
| 2209 | } else { | ||
| 2210 | &B_log("DEBUG","$service is off. Found no processes running on the system."); | ||
| 2211 | # no processes, so service is off | ||
| 2212 | return SECURE_CANT_CHANGE(); | ||
| 2213 | } | ||
| 2214 | # Can't determine the state of the service by looking at the processes, | ||
| 2215 | # so return INCONSISTENT(). | ||
| 2216 | return INCONSISTENT(); | ||
| 2217 | } | ||
| 2218 | |||
| 2219 | ########################################################################### | ||
| 2220 | # B_parse_fstab() | ||
| 2221 | # | ||
| 2222 | # Search the filesystem table for a specific mount point. | ||
| 2223 | # | ||
| 2224 | # scalar return value: | ||
| 2225 | # The line form the table that matched the mount point, or the null string | ||
| 2226 | # if no match was found. | ||
| 2227 | # | ||
| 2228 | # list return value: | ||
| 2229 | # A list of parsed values from the line of the table that matched, with | ||
| 2230 | # element [3] containing a reference to a hash of the mount options. The | ||
| 2231 | # keys are: acl, dev, exec, rw, suid, sync, or user. The value of each key | ||
| 2232 | # can be either 0 or 1. To access the hash, use code similar to this: | ||
| 2233 | # %HashResult = %{(&B_parse_fstab($MountPoint))[3]}; | ||
| 2234 | # | ||
| 2235 | ########################################################################### | ||
| 2236 | |||
| 2237 | sub B_parse_fstab($) | ||
| 2238 | { | ||
| 2239 | my $name = shift; | ||
| 2240 | my $file = &getGlobal('FILE','fstab'); | ||
| 2241 | my ($enable, $disable, $infile); | ||
| 2242 | my @lineopt; | ||
| 2243 | my $retline = ""; | ||
| 2244 | my @retlist = (); | ||
| 2245 | |||
| 2246 | unless (open FH, $file) { | ||
| 2247 | &B_log('ERROR',"B_parse_fstab couldn't open fstab file at path $file.\n"); | ||
| 2248 | return 0; | ||
| 2249 | } | ||
| 2250 | while (<FH>) { | ||
| 2251 | s/\#.*//; | ||
| 2252 | next unless /\S/; | ||
| 2253 | @retlist = split; | ||
| 2254 | next unless $retlist[1] eq $name; | ||
| 2255 | $retline .= $_; | ||
| 2256 | if (wantarray) { | ||
| 2257 | my $option = { # initialize to defaults | ||
| 2258 | acl => 0, # for ext2, etx3, reiserfs | ||
| 2259 | dev => 1, | ||
| 2260 | exec => 1, | ||
| 2261 | rw => 1, | ||
| 2262 | suid => 1, | ||
| 2263 | sync => 0, | ||
| 2264 | user => 0, | ||
| 2265 | }; | ||
| 2266 | |||
| 2267 | my @lineopt = split(',',$retlist[3]); | ||
| 2268 | foreach my $entry (@lineopt) { | ||
| 2269 | if ($entry eq 'acl') { | ||
| 2270 | $option->{'acl'} = 1; | ||
| 2271 | } | ||
| 2272 | elsif ($entry eq 'nodev') { | ||
| 2273 | $option->{'dev'} = 0; | ||
| 2274 | } | ||
| 2275 | elsif ($entry eq 'noexec') { | ||
| 2276 | $option->{'exec'} = 0; | ||
| 2277 | } | ||
| 2278 | elsif ($entry eq 'ro') { | ||
| 2279 | $option->{'rw'} = 0; | ||
| 2280 | } | ||
| 2281 | elsif ($entry eq 'nosuid') { | ||
| 2282 | $option->{'suid'} = 0; | ||
| 2283 | } | ||
| 2284 | elsif ($entry eq 'sync') { | ||
| 2285 | $option->{'sync'} = 1; | ||
| 2286 | } | ||
| 2287 | elsif ($entry eq 'user') { | ||
| 2288 | $option->{'user'} = 1; | ||
| 2289 | } | ||
| 2290 | } | ||
| 2291 | $retlist[3]= $option; | ||
| 2292 | } | ||
| 2293 | last; | ||
| 2294 | } | ||
| 2295 | |||
| 2296 | if (wantarray) | ||
| 2297 | { | ||
| 2298 | return @retlist; | ||
| 2299 | } | ||
| 2300 | else | ||
| 2301 | { | ||
| 2302 | return $retline; | ||
| 2303 | } | ||
| 2304 | |||
| 2305 | } | ||
| 2306 | |||
| 2307 | |||
| 2308 | ########################################################################### | ||
| 2309 | # B_parse_mtab() | ||
| 2310 | # | ||
| 2311 | # This routine returns a hash of devices and their mount points from mtab, | ||
| 2312 | # simply so you can get a list of mounted filesystems. | ||
| 2313 | # | ||
| 2314 | ########################################################################### | ||
| 2315 | |||
| 2316 | sub B_parse_mtab | ||
| 2317 | { | ||
| 2318 | my $mountpoints; | ||
| 2319 | open(MTAB,&getGlobal('FILE','mtab')); | ||
| 2320 | while(my $mtab_line = <MTAB>) { | ||
| 2321 | #test if it's a device | ||
| 2322 | if ($mtab_line =~ /^\//) | ||
| 2323 | { | ||
| 2324 | #parse out device and mount point | ||
| 2325 | $mtab_line =~ /^(\S+)\s+(\S+)/; | ||
| 2326 | $mountpoints->{$1} = $2; | ||
| 2327 | } | ||
| 2328 | } | ||
| 2329 | return $mountpoints; | ||
| 2330 | } | ||
| 2331 | |||
| 2332 | |||
| 2333 | ########################################################################### | ||
| 2334 | # B_is_rpm_up_to_date() | ||
| 2335 | # | ||
| 2336 | # | ||
| 2337 | ########################################################################### | ||
| 2338 | |||
| 2339 | sub B_is_rpm_up_to_date(@) | ||
| 2340 | { | ||
| 2341 | my($nameB,$verB,$relB,$epochB) = @_; | ||
| 2342 | my $installedpkg = $nameB; | ||
| 2343 | |||
| 2344 | if ($epochB =~ /(none)/) { | ||
| 2345 | $epochB = 0; | ||
| 2346 | } | ||
| 2347 | |||
| 2348 | my $rpmA = `rpm -q --qf '%{VERSION}-%{RELEASE}-%{EPOCH}\n' $installedpkg`; | ||
| 2349 | my $nameA = $nameB; | ||
| 2350 | my ($verA,$relA,$epochA); | ||
| 2351 | |||
| 2352 | my $retval; | ||
| 2353 | |||
| 2354 | # First, if the RPM isn't installed, let's handle that. | ||
| 2355 | if ($rpmA =~ /is not installed/) { | ||
| 2356 | $retval = -1; | ||
| 2357 | return $retval; | ||
| 2358 | } | ||
| 2359 | else { | ||
| 2360 | # Next, let's try to parse the EVR information without as few | ||
| 2361 | # calls as possible to rpm. | ||
| 2362 | if ($rpmA =~ /([^-]+)-([^-]+)-([^-]+)$/) { | ||
| 2363 | $verA = $1; | ||
| 2364 | $relA = $2; | ||
| 2365 | $epochA = $3; | ||
| 2366 | } | ||
| 2367 | else { | ||
| 2368 | $nameA = `rpm -q --qf '%{NAME}' $installedpkg`; | ||
| 2369 | $verA = `rpm -q --qf '%{VERSION}' $installedpkg`; | ||
| 2370 | $relA = `rpm -q --qf '%{RELEASE}' $installedpkg`; | ||
| 2371 | $epochA = `rpm -q --qf '%{EPOCH}' $installedpkg`; | ||
| 2372 | } | ||
| 2373 | } | ||
| 2374 | |||
| 2375 | # Parse "none" as 0. | ||
| 2376 | if ($epochA =~ /(none)/) { | ||
| 2377 | $epochA = 0; | ||
| 2378 | } | ||
| 2379 | |||
| 2380 | # Handle the case where only one of them is zero. | ||
| 2381 | if ($epochA == 0 xor $epochB == 0) | ||
| 2382 | { | ||
| 2383 | if ($epochA != 0) | ||
| 2384 | { | ||
| 2385 | $retval = 1; | ||
| 2386 | } | ||
| 2387 | else | ||
| 2388 | { | ||
| 2389 | $retval = 0; | ||
| 2390 | } | ||
| 2391 | } | ||
| 2392 | else | ||
| 2393 | { | ||
| 2394 | # ...otherwise they are either both 0 or both non-zero and | ||
| 2395 | # so the situation isn't trivial. | ||
| 2396 | |||
| 2397 | # Check epoch first - highest epoch wins. | ||
| 2398 | my $rpmcmp = &cmp_vers_part($epochA, $epochB); | ||
| 2399 | #print "epoch rpmcmp is $rpmcmp\n"; | ||
| 2400 | if ($rpmcmp > 0) | ||
| 2401 | { | ||
| 2402 | $retval = 1; | ||
| 2403 | } | ||
| 2404 | elsif ($rpmcmp < 0) | ||
| 2405 | { | ||
| 2406 | $retval = 0; | ||
| 2407 | } | ||
| 2408 | else | ||
| 2409 | { | ||
| 2410 | # Epochs were the same. Check Version now. | ||
| 2411 | $rpmcmp = &cmp_vers_part($verA, $verB); | ||
| 2412 | #print "epoch rpmcmp is $rpmcmp\n"; | ||
| 2413 | if ($rpmcmp > 0) | ||
| 2414 | { | ||
| 2415 | $retval = 1; | ||
| 2416 | } | ||
| 2417 | elsif ($rpmcmp < 0) | ||
| 2418 | { | ||
| 2419 | $retval = 0; | ||
| 2420 | } | ||
| 2421 | else | ||
| 2422 | { | ||
| 2423 | # Versions were the same. Check Release now. | ||
| 2424 | my $rpmcmp = &cmp_vers_part($relA, $relB); | ||
| 2425 | #print "epoch rpmcmp is $rpmcmp\n"; | ||
| 2426 | if ($rpmcmp >= 0) | ||
| 2427 | { | ||
| 2428 | $retval = 1; | ||
| 2429 | } | ||
| 2430 | elsif ($rpmcmp < 0) | ||
| 2431 | { | ||
| 2432 | $retval = 0; | ||
| 2433 | } | ||
| 2434 | } | ||
| 2435 | } | ||
| 2436 | } | ||
| 2437 | return $retval; | ||
| 2438 | } | ||
| 2439 | |||
| 2440 | ################################################# | ||
| 2441 | # Helper function for B_is_rpm_up_to_date() | ||
| 2442 | ################################################# | ||
| 2443 | |||
| 2444 | #This cmp_vers_part function taken from Kirk Bauer's Autorpm. | ||
| 2445 | # This version comparison code was sent in by Robert Mitchell and, although | ||
| 2446 | # not yet perfect, is better than the original one I had. He took the code | ||
| 2447 | # from freshrpms and did some mods to it. Further mods by Simon Liddington | ||
| 2448 | # <sjl96v@ecs.soton.ac.uk>. | ||
| 2449 | # | ||
| 2450 | # Splits string into minors on . and change from numeric to non-numeric | ||
| 2451 | # characters. Minors are compared from the beginning of the string. If the | ||
| 2452 | # minors are both numeric then they are numerically compared. If both minors | ||
| 2453 | # are non-numeric and a single character they are alphabetically compared, if | ||
| 2454 | # they are not a single character they are checked to be the same if the are not | ||
| 2455 | # the result is unknown (currently we say the first is newer so that we have | ||
| 2456 | # a choice to upgrade). If one minor is numeric and one non-numeric then the | ||
| 2457 | # numeric one is newer as it has a longer version string. | ||
| 2458 | # We also assume that (for example) .15 is equivalent to 0.15 | ||
| 2459 | |||
| 2460 | sub cmp_vers_part($$) { | ||
| 2461 | my($va, $vb) = @_; | ||
| 2462 | my(@va_dots, @vb_dots); | ||
| 2463 | my($a, $b); | ||
| 2464 | my($i); | ||
| 2465 | |||
| 2466 | if ($vb !~ /^pre/ and $va =~ s/^pre(\d+.*)$/$1/) { | ||
| 2467 | if ($va eq $vb) { return -1; } | ||
| 2468 | } elsif ($va !~ /^pre/ and $vb =~ s/^pre(\d+.*)$/$1/) { | ||
| 2469 | if ($va eq $vb) { return 1; } | ||
| 2470 | } | ||
| 2471 | |||
| 2472 | @va_dots = split(/\./, $va); | ||
| 2473 | @vb_dots = split(/\./, $vb); | ||
| 2474 | |||
| 2475 | $a = shift(@va_dots); | ||
| 2476 | $b = shift(@vb_dots); | ||
| 2477 | # We also assume that (for example) .15 is equivalent to 0.15 | ||
| 2478 | if ($a eq '' && $va ne '') { $a = "0"; } | ||
| 2479 | if ($b eq '' && $vb ne '') { $b = "0"; } | ||
| 2480 | while ((defined($a) && $a ne '') || (defined($b) && $b ne '')) { | ||
| 2481 | # compare each minor from left to right | ||
| 2482 | if ((not defined($a)) || ($a eq '')) { return -1; } # the longer version is newer | ||
| 2483 | if ((not defined($b)) || ($b eq '')) { return 1; } | ||
| 2484 | if ($a =~ /^\d+$/ && $b =~ /^\d+$/) { | ||
| 2485 | # I have changed this so that when the two strings are numeric, but one or both | ||
| 2486 | # of them start with a 0, then do a string compare - Kirk Bauer - 5/28/99 | ||
| 2487 | if ($a =~ /^0/ or $b =~ /^0/) { | ||
| 2488 | # We better string-compare so that netscape-4.6 is newer than netscape-4.08 | ||
| 2489 | if ($a ne $b) {return ($a cmp $b);} | ||
| 2490 | } | ||
| 2491 | # numeric compare | ||
| 2492 | if ($a != $b) { return $a <=> $b; } | ||
| 2493 | } elsif ($a =~ /^\D+$/ && $b =~ /^\D+$/) { | ||
| 2494 | # string compare | ||
| 2495 | if (length($a) == 1 && length($b) == 1) { | ||
| 2496 | # only minors with one letter seem to be useful for versioning | ||
| 2497 | if ($a ne $b) { return $a cmp $b; } | ||
| 2498 | } elsif (($a cmp $b) != 0) { | ||
| 2499 | # otherwise we should at least check they are the same and if not say unknown | ||
| 2500 | # say newer for now so at least we get choice whether to upgrade or not | ||
| 2501 | return -1; | ||
| 2502 | } | ||
| 2503 | } elsif ( ($a =~ /^\D+$/ && $b =~ /^\d+$/) || ($a =~ /^\d+$/ && $b =~ /^\D+$/) ) { | ||
| 2504 | # if we get a number in one and a word in another the one with a number | ||
| 2505 | # has a longer version string | ||
| 2506 | if ($a =~ /^\d+$/) { return 1; } | ||
| 2507 | if ($b =~ /^\d+$/) { return -1; } | ||
| 2508 | } else { | ||
| 2509 | # minor needs splitting | ||
| 2510 | $a =~ /\d+/ || $a =~ /\D+/; | ||
| 2511 | # split the $a minor into numbers and non-numbers | ||
| 2512 | my @va_bits = ($`, $&, $'); | ||
| 2513 | $b =~ /\d+/ || $b =~ /\D+/; | ||
| 2514 | # split the $b minor into numbers and non-numbers | ||
| 2515 | my @vb_bits = ($`, $&, $'); | ||
| 2516 | for ( my $j=2; $j >= 0; $j--) { | ||
| 2517 | if ($va_bits[$j] ne '') { unshift(@va_dots,$va_bits[$j]); } | ||
| 2518 | if ($vb_bits[$j] ne '') { unshift(@vb_dots,$vb_bits[$j]); } | ||
| 2519 | } | ||
| 2520 | } | ||
| 2521 | $a = shift(@va_dots); | ||
| 2522 | $b = shift(@vb_dots); | ||
| 2523 | } | ||
| 2524 | return 0; | ||
| 2525 | } | ||
| 2526 | |||
| 2527 | 1; | ||
| 2528 | |||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/AccountPermission.pm b/dynamic-layers/meta-perl/recipes-security/bastille/files/AccountPermission.pm new file mode 100644 index 0000000..132b30c --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/AccountPermission.pm | |||
| @@ -0,0 +1,1060 @@ | |||
| 1 | package Bastille::API::AccountPermission; | ||
| 2 | use strict; | ||
| 3 | |||
| 4 | use Bastille::API; | ||
| 5 | |||
| 6 | use Bastille::API::HPSpecific; | ||
| 7 | |||
| 8 | require Exporter; | ||
| 9 | our @ISA = qw(Exporter); | ||
| 10 | our @EXPORT_OK = qw( | ||
| 11 | B_chmod | ||
| 12 | B_chmod_if_exists | ||
| 13 | B_chown | ||
| 14 | B_chown_link | ||
| 15 | B_chgrp | ||
| 16 | B_chgrp_link | ||
| 17 | B_userdel | ||
| 18 | B_groupdel | ||
| 19 | B:remove_user_from_group | ||
| 20 | B_check_owner_group | ||
| 21 | B_is_unowned_file | ||
| 22 | B_is_ungrouped_file | ||
| 23 | B_check_permissions | ||
| 24 | B_permission_test | ||
| 25 | B_find_homes | ||
| 26 | B_is_executable | ||
| 27 | B_is_suid | ||
| 28 | B_is_sgid | ||
| 29 | B_get_user_list | ||
| 30 | B_get_group_list | ||
| 31 | B:remove_suid | ||
| 32 | ); | ||
| 33 | our @EXPORT = @EXPORT_OK; | ||
| 34 | |||
| 35 | ########################################################################### | ||
| 36 | # &B_chmod ($mode, $file) sets the mode of $file to $mode. $mode must | ||
| 37 | # be stored in octal, so if you want to give mode 700 to /etc/aliases, | ||
| 38 | # you need to use: | ||
| 39 | # | ||
| 40 | # &B_chmod ( 0700 , "/etc/aliases"); | ||
| 41 | # | ||
| 42 | # where the 0700 denotes "octal 7-0-0". | ||
| 43 | # | ||
| 44 | # &B_chmod ($mode_changes,$file) also respects the symbolic methods of | ||
| 45 | # changing file permissions, which are often what question authors are | ||
| 46 | # really seeking. | ||
| 47 | # | ||
| 48 | # &B_chmod ("u-s" , "/bin/mount") | ||
| 49 | # or | ||
| 50 | # &B_chmod ("go-rwx", "/bin/mount") | ||
| 51 | # | ||
| 52 | # | ||
| 53 | # &B_chmod respects GLOBAL_LOGONLY and uses | ||
| 54 | # &B_revert_log used to insert a shell command that will return | ||
| 55 | # the permissions to the pre-Bastille state. | ||
| 56 | # | ||
| 57 | # B_chmod allow for globbing now, as of 1.2.0. JJB | ||
| 58 | # | ||
| 59 | ########################################################################## | ||
| 60 | |||
| 61 | |||
| 62 | sub B_chmod($$) { | ||
| 63 | my ($new_perm,$file_expr)=@_; | ||
| 64 | my $old_perm; | ||
| 65 | my $old_perm_raw; | ||
| 66 | my $new_perm_formatted; | ||
| 67 | my $old_perm_formatted; | ||
| 68 | |||
| 69 | my $retval=1; | ||
| 70 | |||
| 71 | my $symbolic = 0; | ||
| 72 | my ($chmod_noun,$add_remove,$capability) = (); | ||
| 73 | # Handle symbolic possibilities too | ||
| 74 | if ($new_perm =~ /([ugo]+)([+-]{1})([rwxst]+)/) { | ||
| 75 | $symbolic = 1; | ||
| 76 | $chmod_noun = $1; | ||
| 77 | $add:remove = $2; | ||
| 78 | $capability = $3; | ||
| 79 | } | ||
| 80 | |||
| 81 | my $file; | ||
| 82 | my @files = glob ($file_expr); | ||
| 83 | |||
| 84 | foreach $file (@files) { | ||
| 85 | |||
| 86 | # Prepend global prefix, but save the original filename for B_backup_file | ||
| 87 | my $original_file=$file; | ||
| 88 | |||
| 89 | # Store the old permissions so that we can log them. | ||
| 90 | unless (stat $file) { | ||
| 91 | &B_log("ERROR","Couldn't stat $original_file from $old_perm to change permissions\n"); | ||
| 92 | next; | ||
| 93 | } | ||
| 94 | |||
| 95 | $old_perm_raw=(stat(_))[2]; | ||
| 96 | $old_perm= (($old_perm_raw/512) % 8) . | ||
| 97 | (($old_perm_raw/64) % 8) . | ||
| 98 | (($old_perm_raw/8) % 8) . | ||
| 99 | ($old_perm_raw % 8); | ||
| 100 | |||
| 101 | # If we've gone symbolic, calculate the new permissions in octal. | ||
| 102 | if ($symbolic) { | ||
| 103 | # | ||
| 104 | # We calculate the new permissions by applying a bitmask to | ||
| 105 | # the current permissions, by OR-ing (for +) or XOR-ing (for -). | ||
| 106 | # | ||
| 107 | # We create this mask by first calculating a perm_mask that forms | ||
| 108 | # the right side of this, then multiplying it by 8 raised to the | ||
| 109 | # appropriate power to affect the correct digit of the octal mask. | ||
| 110 | # This means that we raise 8 to the power of 0,1,2, or 3, based on | ||
| 111 | # the noun of "other","group","user", or "suid/sgid/sticky". | ||
| 112 | # | ||
| 113 | # Actually, we handle multiple nouns by summing powers of 8. | ||
| 114 | # | ||
| 115 | # The only tough part is that we have to handle suid/sgid/sticky | ||
| 116 | # differently. | ||
| 117 | # | ||
| 118 | |||
| 119 | # We're going to calculate a mask to OR or XOR with the current | ||
| 120 | # file mode. This mask is $mask. We calculate this by calculating | ||
| 121 | # a sum of powers of 8, corresponding to user/group/other, | ||
| 122 | # multiplied with a $premask. The $premask is simply the | ||
| 123 | # corresponding bitwise expression of the rwx bits. | ||
| 124 | # | ||
| 125 | # To handle SUID, SGID or sticky in the simplest way possible, we | ||
| 126 | # simply add their values to the $mask first. | ||
| 127 | |||
| 128 | my $perm_mask = 00; | ||
| 129 | my $mask = 00; | ||
| 130 | |||
| 131 | # Check for SUID, SGID or sticky as these are exceptional. | ||
| 132 | if ($capability =~ /s/) { | ||
| 133 | if ($chmod_noun =~ /u/) { | ||
| 134 | $mask += 04000; | ||
| 135 | } | ||
| 136 | if ($chmod_noun =~ /g/) { | ||
| 137 | $mask += 02000; | ||
| 138 | } | ||
| 139 | } | ||
| 140 | if ($capability =~ /t/) { | ||
| 141 | $mask += 01000; | ||
| 142 | } | ||
| 143 | |||
| 144 | # Now handle the normal attributes | ||
| 145 | if ($capability =~ /[rwx]/) { | ||
| 146 | if ($capability =~ /r/) { | ||
| 147 | $perm_mask |= 04; | ||
| 148 | } | ||
| 149 | if ($capability =~ /w/) { | ||
| 150 | $perm_mask |= 02; | ||
| 151 | } | ||
| 152 | if ($capability =~ /x/) { | ||
| 153 | $perm_mask |= 01; | ||
| 154 | } | ||
| 155 | |||
| 156 | # Now figure out which 3 bit octal digit we're affecting. | ||
| 157 | my $power = 0; | ||
| 158 | if ($chmod_noun =~ /u/) { | ||
| 159 | $mask += $perm_mask * 64; | ||
| 160 | } | ||
| 161 | if ($chmod_noun =~ /g/) { | ||
| 162 | $mask += $perm_mask * 8; | ||
| 163 | } | ||
| 164 | if ($chmod_noun =~ /o/) { | ||
| 165 | $mask += $perm_mask * 1; | ||
| 166 | } | ||
| 167 | } | ||
| 168 | # Now apply the mask to get the new permissions | ||
| 169 | if ($add_remove eq '+') { | ||
| 170 | $new_perm = $old_perm_raw | $mask; | ||
| 171 | } | ||
| 172 | elsif ($add_remove eq '-') { | ||
| 173 | $new_perm = $old_perm_raw & ( ~($mask) ); | ||
| 174 | } | ||
| 175 | } | ||
| 176 | |||
| 177 | # formating for simple long octal output of the permissions in string form | ||
| 178 | $new_perm_formatted=sprintf "%5lo",$new_perm; | ||
| 179 | $old_perm_formatted=sprintf "%5lo",$old_perm_raw; | ||
| 180 | |||
| 181 | &B_log("ACTION","change permissions on $original_file from $old_perm_formatted to $new_perm_formatted\n"); | ||
| 182 | |||
| 183 | &B_log("ACTION", "chmod $new_perm_formatted,\"$original_file\";\n"); | ||
| 184 | |||
| 185 | # Change the permissions on the file | ||
| 186 | |||
| 187 | if ( -e $file ) { | ||
| 188 | unless ($GLOBAL_LOGONLY) { | ||
| 189 | $retval=chmod $new_perm,$file; | ||
| 190 | if($retval){ | ||
| 191 | # if the distribution is HP-UX then the modifications should | ||
| 192 | # also be made to the IPD (installed product database) | ||
| 193 | if(&GetDistro =~ "^HP-UX"){ | ||
| 194 | &B_swmodify($file); | ||
| 195 | } | ||
| 196 | # making changes revert-able | ||
| 197 | &B_revert_log(&getGlobal('BIN', "chmod") . " $old_perm $file\n"); | ||
| 198 | } | ||
| 199 | } | ||
| 200 | unless ($retval) { | ||
| 201 | &B_log("ERROR","Couldn't change permissions on $original_file from $old_perm_formatted to $new_perm_formatted\n"); | ||
| 202 | $retval=0; | ||
| 203 | } | ||
| 204 | } | ||
| 205 | else { | ||
| 206 | &B_log("ERROR", "chmod: File $original_file doesn't exist!\n"); | ||
| 207 | $retval=0; | ||
| 208 | } | ||
| 209 | } | ||
| 210 | |||
| 211 | $retval; | ||
| 212 | |||
| 213 | } | ||
| 214 | |||
| 215 | ########################################################################### | ||
| 216 | # &B_chmod_if_exists ($mode, $file) sets the mode of $file to $mode *if* | ||
| 217 | # $file exists. $mode must be stored in octal, so if you want to give | ||
| 218 | # mode 700 to /etc/aliases, you need to use: | ||
| 219 | # | ||
| 220 | # &B_chmod_if_exists ( 0700 , "/etc/aliases"); | ||
| 221 | # | ||
| 222 | # where the 0700 denotes "octal 7-0-0". | ||
| 223 | # | ||
| 224 | # &B_chmod_if_exists respects GLOBAL_LOGONLY and uses | ||
| 225 | # &B_revert_log to reset the permissions of the file. | ||
| 226 | # | ||
| 227 | # B_chmod_if_exists allow for globbing now, as of 1.2.0. JJB | ||
| 228 | # | ||
| 229 | ########################################################################## | ||
| 230 | |||
| 231 | |||
| 232 | sub B_chmod_if_exists($$) { | ||
| 233 | my ($new_perm,$file_expr)=@_; | ||
| 234 | # If $file_expr has a glob character, pass it on (B_chmod won't complain | ||
| 235 | # about nonexistent files if given a glob pattern) | ||
| 236 | if ( $file_expr =~ /[\*\[\{]/ ) { # } just to match open brace for vi | ||
| 237 | &B_log("ACTION","Running chmod $new_perm $file_expr"); | ||
| 238 | return(&B_chmod($new_perm,$file_expr)); | ||
| 239 | } | ||
| 240 | # otherwise, test for file existence | ||
| 241 | if ( -e $file_expr ) { | ||
| 242 | &B_log("ACTION","File exists, running chmod $new_perm $file_expr"); | ||
| 243 | return(&B_chmod($new_perm,$file_expr)); | ||
| 244 | } | ||
| 245 | } | ||
| 246 | |||
| 247 | ########################################################################### | ||
| 248 | # &B_chown ($uid, $file) sets the owner of $file to $uid, like this: | ||
| 249 | # | ||
| 250 | # &B_chown ( 0 , "/etc/aliases"); | ||
| 251 | # | ||
| 252 | # &B_chown respects $GLOBAL_LOGONLY and uses | ||
| 253 | # &B_revert_log to insert a shell command that will return | ||
| 254 | # the file/directory owner to the pre-Bastille state. | ||
| 255 | # | ||
| 256 | # Unlike Perl, we've broken the chown function into B_chown/B_chgrp to | ||
| 257 | # make error checking simpler. | ||
| 258 | # | ||
| 259 | # As of 1.2.0, this now supports file globbing. JJB | ||
| 260 | # | ||
| 261 | ########################################################################## | ||
| 262 | |||
| 263 | |||
| 264 | sub B_chown($$) { | ||
| 265 | my ($newown,$file_expr)=@_; | ||
| 266 | my $oldown; | ||
| 267 | my $oldgown; | ||
| 268 | |||
| 269 | my $retval=1; | ||
| 270 | |||
| 271 | my $file; | ||
| 272 | my @files = glob($file_expr); | ||
| 273 | |||
| 274 | foreach $file (@files) { | ||
| 275 | |||
| 276 | # Prepend prefix, but save original filename | ||
| 277 | my $original_file=$file; | ||
| 278 | |||
| 279 | $oldown=(stat $file)[4]; | ||
| 280 | $oldgown=(stat $file)[5]; | ||
| 281 | |||
| 282 | &B_log("ACTION","change ownership on $original_file from $oldown to $newown\n"); | ||
| 283 | &B_log("ACTION","chown $newown,$oldgown,\"$original_file\";\n"); | ||
| 284 | if ( -e $file ) { | ||
| 285 | unless ($GLOBAL_LOGONLY) { | ||
| 286 | # changing the files owner using perl chown function | ||
| 287 | $retval = chown $newown,$oldgown,$file; | ||
| 288 | if($retval){ | ||
| 289 | # if the distribution is HP-UX then the modifications should | ||
| 290 | # also be made to the IPD (installed product database) | ||
| 291 | if(&GetDistro =~ "^HP-UX"){ | ||
| 292 | &B_swmodify($file); | ||
| 293 | } | ||
| 294 | # making ownership change revert-able | ||
| 295 | &B_revert_log(&getGlobal('BIN', "chown") . " $oldown $file\n"); | ||
| 296 | } | ||
| 297 | } | ||
| 298 | unless ($retval) { | ||
| 299 | &B_log("ERROR","Couldn't change ownership to $newown on file $original_file\n"); | ||
| 300 | } | ||
| 301 | } | ||
| 302 | else { | ||
| 303 | &B_log("ERROR","chown: File $original_file doesn't exist!\n"); | ||
| 304 | $retval=0; | ||
| 305 | } | ||
| 306 | } | ||
| 307 | |||
| 308 | $retval; | ||
| 309 | } | ||
| 310 | |||
| 311 | ########################################################################### | ||
| 312 | # &B_chown_link just like &B_chown but one exception: | ||
| 313 | # if the input file is a link it will not change the target's ownship, it only change the link itself's ownship | ||
| 314 | ########################################################################### | ||
| 315 | sub B_chown_link($$){ | ||
| 316 | my ($newown,$file_expr)=@_; | ||
| 317 | my $chown = &getGlobal("BIN","chown"); | ||
| 318 | my @files = glob($file_expr); | ||
| 319 | my $retval = 1; | ||
| 320 | |||
| 321 | foreach my $file (@files) { | ||
| 322 | # Prepend prefix, but save original filename | ||
| 323 | my $original_file=$file; | ||
| 324 | my $oldown=(stat $file)[4]; | ||
| 325 | my $oldgown=(stat $file)[5]; | ||
| 326 | |||
| 327 | &B_log("ACTION","change ownership on $original_file from $oldown to $newown\n"); | ||
| 328 | &B_log("ACTION","chown -h $newown,\"$original_file\";\n"); | ||
| 329 | if ( -e $file ) { | ||
| 330 | unless ($GLOBAL_LOGONLY) { | ||
| 331 | `$chown -h $newown $file`; | ||
| 332 | $retval = ($? >> 8); | ||
| 333 | if($retval == 0 ){ | ||
| 334 | # if the distribution is HP-UX then the modifications should | ||
| 335 | # also be made to the IPD (installed product database) | ||
| 336 | if(&GetDistro =~ "^HP-UX"){ | ||
| 337 | &B_swmodify($file); | ||
| 338 | } | ||
| 339 | # making ownership change revert-able | ||
| 340 | &B_revert_log("$chown -h $oldown $file\n"); | ||
| 341 | } | ||
| 342 | } | ||
| 343 | unless ( ! $retval) { | ||
| 344 | &B_log("ERROR","Couldn't change ownership to $newown on file $original_file\n"); | ||
| 345 | } | ||
| 346 | } | ||
| 347 | else { | ||
| 348 | &B_log("ERROR","chown: File $original_file doesn't exist!\n"); | ||
| 349 | $retval=0; | ||
| 350 | } | ||
| 351 | } | ||
| 352 | } | ||
| 353 | |||
| 354 | |||
| 355 | ########################################################################### | ||
| 356 | # &B_chgrp ($gid, $file) sets the group owner of $file to $gid, like this: | ||
| 357 | # | ||
| 358 | # &B_chgrp ( 0 , "/etc/aliases"); | ||
| 359 | # | ||
| 360 | # &B_chgrp respects $GLOBAL_LOGONLY and uses | ||
| 361 | # &B_revert_log to insert a shell command that will return | ||
| 362 | # the file/directory group to the pre-Bastille state. | ||
| 363 | # | ||
| 364 | # Unlike Perl, we've broken the chown function into B_chown/B_chgrp to | ||
| 365 | # make error checking simpler. | ||
| 366 | # | ||
| 367 | # As of 1.2.0, this now supports file globbing. JJB | ||
| 368 | # | ||
| 369 | ########################################################################## | ||
| 370 | |||
| 371 | |||
| 372 | sub B_chgrp($$) { | ||
| 373 | my ($newgown,$file_expr)=@_; | ||
| 374 | my $oldown; | ||
| 375 | my $oldgown; | ||
| 376 | |||
| 377 | my $retval=1; | ||
| 378 | |||
| 379 | my $file; | ||
| 380 | my @files = glob($file_expr); | ||
| 381 | |||
| 382 | foreach $file (@files) { | ||
| 383 | |||
| 384 | # Prepend global prefix, but save original filename for &B_backup_file | ||
| 385 | my $original_file=$file; | ||
| 386 | |||
| 387 | $oldown=(stat $file)[4]; | ||
| 388 | $oldgown=(stat $file)[5]; | ||
| 389 | |||
| 390 | &B_log("ACTION", "Change group ownership on $original_file from $oldgown to $newgown\n"); | ||
| 391 | &B_log("ACTION", "chown $oldown,$newgown,\"$original_file\";\n"); | ||
| 392 | if ( -e $file ) { | ||
| 393 | unless ($GLOBAL_LOGONLY) { | ||
| 394 | # changing the group for the file/directory | ||
| 395 | $retval = chown $oldown,$newgown,$file; | ||
| 396 | if($retval){ | ||
| 397 | # if the distribution is HP-UX then the modifications should | ||
| 398 | # also be made to the IPD (installed product database) | ||
| 399 | if(&GetDistro =~ "^HP-UX"){ | ||
| 400 | &B_swmodify($file); | ||
| 401 | } | ||
| 402 | &B_revert_log(&getGlobal('BIN', "chgrp") . " $oldgown $file\n"); | ||
| 403 | } | ||
| 404 | } | ||
| 405 | unless ($retval) { | ||
| 406 | &B_log("ERROR","Couldn't change ownership to $newgown on file $original_file\n"); | ||
| 407 | } | ||
| 408 | } | ||
| 409 | else { | ||
| 410 | &B_log("ERROR","chgrp: File $original_file doesn't exist!\n"); | ||
| 411 | $retval=0; | ||
| 412 | } | ||
| 413 | } | ||
| 414 | |||
| 415 | $retval; | ||
| 416 | } | ||
| 417 | |||
| 418 | ########################################################################### | ||
| 419 | # &B_chgrp_link just like &B_chgrp but one exception: | ||
| 420 | # if the input file is a link | ||
| 421 | # it will not change the target's ownship, it only change the link itself's ownship | ||
| 422 | ########################################################################### | ||
| 423 | sub B_chgrp_link($$) { | ||
| 424 | my ($newgown,$file_expr)=@_; | ||
| 425 | my $chgrp = &getGlobal("BIN","chgrp"); | ||
| 426 | my @files = glob($file_expr); | ||
| 427 | my $retval=1; | ||
| 428 | |||
| 429 | foreach my $file (@files) { | ||
| 430 | # Prepend prefix, but save original filename | ||
| 431 | my $original_file=$file; | ||
| 432 | my $oldgown=(stat $file)[5]; | ||
| 433 | |||
| 434 | &B_log("ACTION","change group ownership on $original_file from $oldgown to $newgown\n"); | ||
| 435 | &B_log("ACTION","chgrp -h $newgown \"$original_file\";\n"); | ||
| 436 | if ( -e $file ) { | ||
| 437 | unless ($GLOBAL_LOGONLY) { | ||
| 438 | # do not follow link with option -h | ||
| 439 | `$chgrp -h $newgown $file`; | ||
| 440 | $retval = ($? >> 8); | ||
| 441 | if($retval == 0 ){ | ||
| 442 | # if the distribution is HP-UX then the modifications should | ||
| 443 | # also be made to the IPD (installed product database) | ||
| 444 | if(&GetDistro =~ "^HP-UX"){ | ||
| 445 | &B_swmodify($file); | ||
| 446 | } | ||
| 447 | # making ownership change revert-able | ||
| 448 | &B_revert_log("$chgrp" . " -h $oldgown $file\n"); | ||
| 449 | } | ||
| 450 | } | ||
| 451 | unless (! $retval) { | ||
| 452 | &B_log("ERROR","Couldn't change group ownership to $newgown on file $original_file\n"); | ||
| 453 | } | ||
| 454 | } | ||
| 455 | else { | ||
| 456 | &B_log("ERROR","chgrp: File $original_file doesn't exist!\n"); | ||
| 457 | $retval=0; | ||
| 458 | } | ||
| 459 | } | ||
| 460 | } | ||
| 461 | |||
| 462 | ########################################################################### | ||
| 463 | # B_userdel($user) removes $user from the system, chmoding her home | ||
| 464 | # directory to 000, root:root owned, and removes the user from all | ||
| 465 | # /etc/passwd, /etc/shadow and /etc/group lines. | ||
| 466 | # | ||
| 467 | # In the future, we may also choose to make a B_lock_account routine. | ||
| 468 | # | ||
| 469 | # This routine depends on B:remove_user_from_group. | ||
| 470 | ########################################################################### | ||
| 471 | |||
| 472 | sub B_userdel($) { | ||
| 473 | |||
| 474 | my $user_to_remove = $_[0]; | ||
| 475 | |||
| 476 | if (&GetDistro =~ /^HP-UX/) { | ||
| 477 | return 0; | ||
| 478 | |||
| 479 | # Not yet suported on HP-UX, where we'd need to support | ||
| 480 | # the TCB files and such. | ||
| 481 | } | ||
| 482 | |||
| 483 | # | ||
| 484 | # First, let's chmod/chown/chgrp the user's home directory. | ||
| 485 | # | ||
| 486 | |||
| 487 | # Get the user's home directory from /etc/passwd | ||
| 488 | if (open PASSWD,&getGlobal('FILE','passwd')) { | ||
| 489 | my @lines=<PASSWD>; | ||
| 490 | close PASSWD; | ||
| 491 | |||
| 492 | # Get the home directory | ||
| 493 | my $user_line = grep '^\s*$user_to_remove\s*:',@lines; | ||
| 494 | my $home_directory = (split /\s*:\s*/,$user_line)[5]; | ||
| 495 | |||
| 496 | # Chmod that home dir to 0000,owned by uid 0, gid 0. | ||
| 497 | if (&B_chmod_if_exists(0000,$home_directory)) { | ||
| 498 | &B_chown(0,$home_directory); | ||
| 499 | &B_chgrp(0,$home_directory); | ||
| 500 | } | ||
| 501 | } | ||
| 502 | else { | ||
| 503 | &B_log('ERROR',"B_userdel couldn't open the passwd file to remove a user."); | ||
| 504 | return 0; | ||
| 505 | } | ||
| 506 | |||
| 507 | # | ||
| 508 | # Next find out what groups the user is in, so we can call | ||
| 509 | # B:remove_user_from_group($user,$group) | ||
| 510 | # | ||
| 511 | # TODO: add this to the helper functions for the test suite. | ||
| 512 | # | ||
| 513 | |||
| 514 | my @groups = (); | ||
| 515 | |||
| 516 | # Parse /etc/group, looking for our user. | ||
| 517 | if (open GROUP,&getGlobal('FILE','group')) { | ||
| 518 | my @lines = <GROUP>; | ||
| 519 | close GROUP; | ||
| 520 | |||
| 521 | foreach my $line (@lines) { | ||
| 522 | |||
| 523 | # Parse the line -- first field is group, last is users in group. | ||
| 524 | if ($line =~ /([^\#^:]+):[^:]+:[^:]+:(.*)/) { | ||
| 525 | my $group = $1; | ||
| 526 | my $users_section = $2; | ||
| 527 | |||
| 528 | # Get the user list and check if our user is in it. | ||
| 529 | my @users = split /\s*,\s*/,$users_section; | ||
| 530 | foreach my $user (@users) { | ||
| 531 | if ($user_to_remove eq $user) { | ||
| 532 | push @groups,$group; | ||
| 533 | last; | ||
| 534 | } | ||
| 535 | } | ||
| 536 | } | ||
| 537 | } | ||
| 538 | } | ||
| 539 | |||
| 540 | # Now remove the user from each of those groups. | ||
| 541 | foreach my $group (@groups) { | ||
| 542 | &B_remove_user_from_group($user_to_remove,$group); | ||
| 543 | } | ||
| 544 | |||
| 545 | # Remove the user's /etc/passwd and /etc/shadow lines | ||
| 546 | &B_delete_line(&getGlobal('FILE','passwd'),"^$user_to_remove\\s*:"); | ||
| 547 | &B_delete_line(&getGlobal('FILE','shadow'),"^$user_to_remove\\s*:"); | ||
| 548 | |||
| 549 | |||
| 550 | # | ||
| 551 | # We should delete the user's group as well, if it's a single-user group. | ||
| 552 | # | ||
| 553 | if (open ETCGROUP,&getGlobal('FILE','group')) { | ||
| 554 | my @group_lines = <ETCGROUP>; | ||
| 555 | close ETCGROUP; | ||
| 556 | chomp @group_lines; | ||
| 557 | |||
| 558 | if (grep /^$user_to_remove\s*:[^:]*:[^:]*:\s*$/,@group_lines > 0) { | ||
| 559 | &B_groupdel($user_to_remove); | ||
| 560 | } | ||
| 561 | } | ||
| 562 | |||
| 563 | } | ||
| 564 | |||
| 565 | ########################################################################### | ||
| 566 | # B_groupdel($group) removes $group from /etc/group. | ||
| 567 | ########################################################################### | ||
| 568 | |||
| 569 | sub B_groupdel($) { | ||
| 570 | |||
| 571 | my $group = $_[0]; | ||
| 572 | |||
| 573 | # First read /etc/group to make sure the group is in there. | ||
| 574 | if (open GROUP,&getGlobal('FILE','group')) { | ||
| 575 | my @lines=<GROUP>; | ||
| 576 | close GROUP; | ||
| 577 | |||
| 578 | # Delete the line in /etc/group if present | ||
| 579 | if (grep /^$group:/,@lines > 0) { | ||
| 580 | # The group is named in /etc/group | ||
| 581 | &B_delete_line(&getGlobal('FILE','group'),"^$group:/"); | ||
| 582 | } | ||
| 583 | } | ||
| 584 | |||
| 585 | } | ||
| 586 | |||
| 587 | |||
| 588 | ########################################################################### | ||
| 589 | # B:remove_user_from_group($user,$group) removes $user from $group, | ||
| 590 | # by modifying $group's /etc/group line, pulling the user out. This | ||
| 591 | # uses B_chunk_replace thrice to replace these patterns: | ||
| 592 | # | ||
| 593 | # ":\s*$user\s*," --> ":" | ||
| 594 | # ",\s*$user" -> "" | ||
| 595 | # | ||
| 596 | ########################################################################### | ||
| 597 | |||
| 598 | sub B:remove_user_from_group($$) { | ||
| 599 | |||
| 600 | my ($user_to_remove,$group) = @_; | ||
| 601 | |||
| 602 | # | ||
| 603 | # We need to find the line from /etc/group that defines the group, parse | ||
| 604 | # it, and put it back together without this user. | ||
| 605 | # | ||
| 606 | |||
| 607 | # Open the group file | ||
| 608 | unless (open GROUP,&getGlobal('FILE','group')) { | ||
| 609 | &B_log('ERROR',"&B_remove_user_from_group couldn't read /etc/group to remove $user_to_remove from $group.\n"); | ||
| 610 | return 0; | ||
| 611 | } | ||
| 612 | my @lines = <GROUP>; | ||
| 613 | close GROUP; | ||
| 614 | chomp @lines; | ||
| 615 | |||
| 616 | # | ||
| 617 | # Read through the lines to find the one we care about. We'll construct a | ||
| 618 | # replacement and then use B_replace_line to make the switch. | ||
| 619 | # | ||
| 620 | |||
| 621 | foreach my $line (@lines) { | ||
| 622 | |||
| 623 | if ($line =~ /^\s*$group\s*:/) { | ||
| 624 | |||
| 625 | # Parse this line. | ||
| 626 | my @group_entries = split ':',$line; | ||
| 627 | my @users = split ',',($group_entries[3]); | ||
| 628 | |||
| 629 | # Now, recreate it. | ||
| 630 | my $first_user = 1; | ||
| 631 | my $group_line = $group_entries[0] . ':' . $group_entries[1] . ':' . $group_entries[2] . ':'; | ||
| 632 | |||
| 633 | # Add every user except the one we're removing. | ||
| 634 | foreach my $user (@users) { | ||
| 635 | |||
| 636 | # Remove whitespace. | ||
| 637 | $user =~ s/\s+//g; | ||
| 638 | |||
| 639 | if ($user ne $user_to_remove) { | ||
| 640 | # Add the user to the end of the line, prefacing | ||
| 641 | # it with a comma if it's not the first user. | ||
| 642 | |||
| 643 | if ($first_user) { | ||
| 644 | $group_line .= "$user"; | ||
| 645 | $first_user = 0; | ||
| 646 | } | ||
| 647 | else { | ||
| 648 | $group_line .= ",$user"; | ||
| 649 | } | ||
| 650 | } | ||
| 651 | } | ||
| 652 | |||
| 653 | # The line is now finished. Replace the original line. | ||
| 654 | $group_line .= "\n"; | ||
| 655 | &B_replace_line(&getGlobal('FILE','group'),"^\\s*$group\\s*:",$group_line); | ||
| 656 | } | ||
| 657 | |||
| 658 | } | ||
| 659 | return 1; | ||
| 660 | } | ||
| 661 | |||
| 662 | ########################################################################### | ||
| 663 | # &B_check_owner_group($$$) | ||
| 664 | # | ||
| 665 | # Checks if the given file has the given owner and/or group. | ||
| 666 | # If the given owner is "", checks group only. | ||
| 667 | # If the given group is "", checks owner only. | ||
| 668 | # | ||
| 669 | # return values: | ||
| 670 | # 1: file has the given owner and/or group | ||
| 671 | # or file exists, and both the given owner and group are "" | ||
| 672 | # 0: file does not has the given owner or group | ||
| 673 | # or file does not exists | ||
| 674 | ############################################################################ | ||
| 675 | |||
| 676 | sub B_check_owner_group ($$$){ | ||
| 677 | my ($fileName, $owner, $group) = @_; | ||
| 678 | |||
| 679 | if (-e $fileName) { | ||
| 680 | my @junk=stat ($fileName); | ||
| 681 | my $uid=$junk[4]; | ||
| 682 | my $gid=$junk[5]; | ||
| 683 | |||
| 684 | # Check file owner | ||
| 685 | if ($owner ne "") { | ||
| 686 | if (getpwnam($owner) != $uid) { | ||
| 687 | return 0; | ||
| 688 | } | ||
| 689 | } | ||
| 690 | |||
| 691 | # Check file group | ||
| 692 | if ($group ne "") { | ||
| 693 | if (getgrnam($group) != $gid) { | ||
| 694 | return 0; | ||
| 695 | } | ||
| 696 | } | ||
| 697 | |||
| 698 | return 1; | ||
| 699 | } | ||
| 700 | else { | ||
| 701 | # Something is wrong if the file not exist | ||
| 702 | return 0; | ||
| 703 | } | ||
| 704 | } | ||
| 705 | |||
| 706 | ########################################################################## | ||
| 707 | # this subroutine will test whether the given file is unowned | ||
| 708 | ########################################################################## | ||
| 709 | sub B_is_unowned_file($) { | ||
| 710 | my $file =$_; | ||
| 711 | my $uid = (stat($file))[4]; | ||
| 712 | my $uname = (getpwuid($uid))[0]; | ||
| 713 | if ( $uname =~ /.+/ ) { | ||
| 714 | return 1; | ||
| 715 | } | ||
| 716 | return 0; | ||
| 717 | } | ||
| 718 | |||
| 719 | ########################################################################## | ||
| 720 | # this subroutine will test whether the given file is ungrouped | ||
| 721 | ########################################################################## | ||
| 722 | sub B_is_ungrouped_file($){ | ||
| 723 | my $file =$_; | ||
| 724 | my $gid = (stat($file))[5]; | ||
| 725 | my $gname = (getgrgid($gid))[0]; | ||
| 726 | if ( $gname =~ /.+/ ) { | ||
| 727 | return 1; | ||
| 728 | } | ||
| 729 | return 0; | ||
| 730 | } | ||
| 731 | |||
| 732 | |||
| 733 | |||
| 734 | |||
| 735 | ########################################################################### | ||
| 736 | # &B_check_permissions($$) | ||
| 737 | # | ||
| 738 | # Checks if the given file has the given permissions or stronger, where we | ||
| 739 | # define stronger as "less accessible." The file argument must be fully | ||
| 740 | # qualified, i.e. contain the absolute path. | ||
| 741 | # | ||
| 742 | # return values: | ||
| 743 | # 1: file has the given permissions or better | ||
| 744 | # 0: file does not have the given permsssions | ||
| 745 | # undef: file permissions cannot be determined | ||
| 746 | ########################################################################### | ||
| 747 | |||
| 748 | sub B_check_permissions ($$){ | ||
| 749 | my ($fileName, $reqdPerms) = @_; | ||
| 750 | my $filePerms; # actual permissions | ||
| 751 | |||
| 752 | |||
| 753 | if (-e $fileName) { | ||
| 754 | if (stat($fileName)) { | ||
| 755 | $filePerms = (stat($fileName))[2] & 07777; | ||
| 756 | } | ||
| 757 | else { | ||
| 758 | &B_log ("ERROR", "Can't stat $fileName.\n"); | ||
| 759 | return undef; | ||
| 760 | } | ||
| 761 | } | ||
| 762 | else { | ||
| 763 | # If the file does not exist, permissions are as good as they can get. | ||
| 764 | return 1; | ||
| 765 | } | ||
| 766 | |||
| 767 | # | ||
| 768 | # We can check whether the $filePerms are as strong by | ||
| 769 | # bitwise ANDing them with $reqdPerms and checking if the | ||
| 770 | # result is still equal to $filePerms. If it is, the | ||
| 771 | # $filePerms are strong enough. | ||
| 772 | # | ||
| 773 | if ( ($filePerms & $reqdPerms) == $filePerms ) { | ||
| 774 | return 1; | ||
| 775 | } | ||
| 776 | else { | ||
| 777 | return 0; | ||
| 778 | } | ||
| 779 | |||
| 780 | } | ||
| 781 | |||
| 782 | ########################################################################## | ||
| 783 | # B_permission_test($user, $previlege,$file) | ||
| 784 | # $user can be | ||
| 785 | # "owner" | ||
| 786 | # "group" | ||
| 787 | # "other" | ||
| 788 | # $previlege can be: | ||
| 789 | # "r" | ||
| 790 | # "w" | ||
| 791 | # "x" | ||
| 792 | # "suid" | ||
| 793 | # "sgid" | ||
| 794 | # "sticky" | ||
| 795 | # if previlege is set to suid or sgid or sticky, then $user can be empty | ||
| 796 | # this sub routine test whether the $user has the specified previlige to $file | ||
| 797 | ########################################################################## | ||
| 798 | |||
| 799 | sub B_permission_test($$$){ | ||
| 800 | my ($user, $previlege, $file) = @_; | ||
| 801 | |||
| 802 | if (-e $file ) { | ||
| 803 | my $mode = (stat($file))[2]; | ||
| 804 | my $bitpos; | ||
| 805 | # bitmap is | suid sgid sticky | rwx | rwx | rwx | ||
| 806 | if ($previlege =~ /suid/ ) { | ||
| 807 | $bitpos = 11; | ||
| 808 | } | ||
| 809 | elsif ($previlege =~ /sgid/ ) { | ||
| 810 | $bitpos = 10; | ||
| 811 | } | ||
| 812 | elsif ($previlege =~ /sticky/ ) { | ||
| 813 | $bitpos = 9; | ||
| 814 | } | ||
| 815 | else { | ||
| 816 | if ( $user =~ /owner/) { | ||
| 817 | if ($previlege =~ /r/) { | ||
| 818 | $bitpos = 8; | ||
| 819 | } | ||
| 820 | elsif ($previlege =~ /w/) { | ||
| 821 | $bitpos =7; | ||
| 822 | } | ||
| 823 | elsif ($previlege =~ /x/) { | ||
| 824 | $bitpos =6; | ||
| 825 | } | ||
| 826 | else { | ||
| 827 | return 0; | ||
| 828 | } | ||
| 829 | } | ||
| 830 | elsif ( $user =~ /group/) { | ||
| 831 | if ($previlege =~ /r/) { | ||
| 832 | $bitpos =5; | ||
| 833 | } | ||
| 834 | elsif ($previlege =~ /w/) { | ||
| 835 | $bitpos =4; | ||
| 836 | } | ||
| 837 | elsif ($previlege =~ /x/) { | ||
| 838 | $bitpos =3; | ||
| 839 | } | ||
| 840 | else { | ||
| 841 | return 0; | ||
| 842 | } | ||
| 843 | } | ||
| 844 | elsif ( $user =~ /other/) { | ||
| 845 | if ($previlege =~ /r/) { | ||
| 846 | $bitpos =2; | ||
| 847 | } | ||
| 848 | elsif ($previlege =~ /w/) { | ||
| 849 | $bitpos =1; | ||
| 850 | } | ||
| 851 | elsif ($previlege =~ /x/) { | ||
| 852 | $bitpos =0; | ||
| 853 | } | ||
| 854 | else { | ||
| 855 | return 0; | ||
| 856 | } | ||
| 857 | } | ||
| 858 | else { | ||
| 859 | return 0; | ||
| 860 | } | ||
| 861 | } | ||
| 862 | $mode /= 2**$bitpos; | ||
| 863 | if ($mode % 2) { | ||
| 864 | return 1; | ||
| 865 | } | ||
| 866 | return 0; | ||
| 867 | } | ||
| 868 | } | ||
| 869 | |||
| 870 | ########################################################################## | ||
| 871 | # this subroutine will return a list of home directory | ||
| 872 | ########################################################################## | ||
| 873 | sub B_find_homes(){ | ||
| 874 | # find loginable homes | ||
| 875 | my $logins = &getGlobal("BIN","logins"); | ||
| 876 | my @lines = `$logins -ox`; | ||
| 877 | my @homes; | ||
| 878 | foreach my $line (@lines) { | ||
| 879 | chomp $line; | ||
| 880 | my @data = split /:/, $line; | ||
| 881 | if ($data[7] =~ /PS/ && $data[5] =~ /home/) { | ||
| 882 | push @homes, $data[5]; | ||
| 883 | } | ||
| 884 | } | ||
| 885 | return @homes; | ||
| 886 | } | ||
| 887 | |||
| 888 | |||
| 889 | ########################################################################### | ||
| 890 | # B_is_executable($) | ||
| 891 | # | ||
| 892 | # This routine reports on whether a file is executable by the current | ||
| 893 | # process' effective UID. | ||
| 894 | # | ||
| 895 | # scalar return values: | ||
| 896 | # 0: file is not executable | ||
| 897 | # 1: file is executable | ||
| 898 | # | ||
| 899 | ########################################################################### | ||
| 900 | |||
| 901 | sub B_is_executable($) | ||
| 902 | { | ||
| 903 | my $name = shift; | ||
| 904 | my $executable = 0; | ||
| 905 | |||
| 906 | if (-x $name) { | ||
| 907 | $executable = 1; | ||
| 908 | } | ||
| 909 | return $executable; | ||
| 910 | } | ||
| 911 | |||
| 912 | ########################################################################### | ||
| 913 | # B_is_suid($) | ||
| 914 | # | ||
| 915 | # This routine reports on whether a file is Set-UID and owned by root. | ||
| 916 | # | ||
| 917 | # scalar return values: | ||
| 918 | # 0: file is not SUID root | ||
| 919 | # 1: file is SUID root | ||
| 920 | # | ||
| 921 | ########################################################################### | ||
| 922 | |||
| 923 | sub B_is_suid($) | ||
| 924 | { | ||
| 925 | my $name = shift; | ||
| 926 | |||
| 927 | my @FileStatus = stat($name); | ||
| 928 | my $IsSuid = 0; | ||
| 929 | |||
| 930 | if (-u $name) #Checks existence and suid | ||
| 931 | { | ||
| 932 | if($FileStatus[4] == 0) { | ||
| 933 | $IsSuid = 1; | ||
| 934 | } | ||
| 935 | } | ||
| 936 | |||
| 937 | return $IsSuid; | ||
| 938 | } | ||
| 939 | |||
| 940 | ########################################################################### | ||
| 941 | # B_is_sgid($) | ||
| 942 | # | ||
| 943 | # This routine reports on whether a file is SGID and group owned by | ||
| 944 | # group root (gid 0). | ||
| 945 | # | ||
| 946 | # scalar return values: | ||
| 947 | # 0: file is not SGID root | ||
| 948 | # 1: file is SGID root | ||
| 949 | # | ||
| 950 | ########################################################################### | ||
| 951 | |||
| 952 | sub B_is_sgid($) | ||
| 953 | { | ||
| 954 | my $name = shift; | ||
| 955 | |||
| 956 | my @FileStatus = stat($name); | ||
| 957 | my $IsSgid = 0; | ||
| 958 | |||
| 959 | if (-g $name) #checks existence and sgid | ||
| 960 | { | ||
| 961 | if($FileStatus[5] == 0) { | ||
| 962 | $IsSgid = 1; | ||
| 963 | } | ||
| 964 | } | ||
| 965 | |||
| 966 | return $IsSgid; | ||
| 967 | } | ||
| 968 | |||
| 969 | ########################################################################### | ||
| 970 | # B_get_user_list() | ||
| 971 | # | ||
| 972 | # This routine outputs a list of users on the system. | ||
| 973 | # | ||
| 974 | ########################################################################### | ||
| 975 | |||
| 976 | sub B_get_user_list() | ||
| 977 | { | ||
| 978 | my @users; | ||
| 979 | open(PASSWD,&getGlobal('FILE','passwd')); | ||
| 980 | while(<PASSWD>) { | ||
| 981 | #Get the users | ||
| 982 | if (/^([^:]+):/) | ||
| 983 | { | ||
| 984 | push (@users,$1); | ||
| 985 | } | ||
| 986 | } | ||
| 987 | return @users; | ||
| 988 | } | ||
| 989 | |||
| 990 | ########################################################################### | ||
| 991 | # B_get_group_list() | ||
| 992 | # | ||
| 993 | # This routine outputs a list of groups on the system. | ||
| 994 | # | ||
| 995 | ########################################################################### | ||
| 996 | |||
| 997 | sub B_get_group_list() | ||
| 998 | { | ||
| 999 | my @groups; | ||
| 1000 | open(GROUP,&getGlobal('FILE','group')); | ||
| 1001 | while(my $group_line = <GROUP>) { | ||
| 1002 | #Get the groups | ||
| 1003 | if ($group_line =~ /^([^:]+):/) | ||
| 1004 | { | ||
| 1005 | push (@groups,$1); | ||
| 1006 | } | ||
| 1007 | } | ||
| 1008 | return @groups; | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | |||
| 1012 | ########################################################################### | ||
| 1013 | # &B_remove_suid ($file) removes the suid bit from $file if it | ||
| 1014 | # is set and the file exist. If you would like to remove the suid bit | ||
| 1015 | # from /bin/ping then you need to use: | ||
| 1016 | # | ||
| 1017 | # &B_remove_suid("/bin/ping"); | ||
| 1018 | # | ||
| 1019 | # &B_remove_suid respects GLOBAL_LOGONLY. | ||
| 1020 | # &B_remove_suid uses &B_chmod to make the permission changes | ||
| 1021 | # &B_remove_suid allows for globbing. tyler_e | ||
| 1022 | # | ||
| 1023 | ########################################################################### | ||
| 1024 | |||
| 1025 | sub B:remove_suid($) { | ||
| 1026 | my $file_expr = $_[0]; | ||
| 1027 | |||
| 1028 | &B_log("ACTION","Removing SUID bit from \"$file_expr\"."); | ||
| 1029 | unless ($GLOBAL_LOGONLY) { | ||
| 1030 | my @files = glob($file_expr); | ||
| 1031 | |||
| 1032 | foreach my $file (@files) { | ||
| 1033 | # check file existence | ||
| 1034 | if(-e $file){ | ||
| 1035 | # stat current file to get raw permissions | ||
| 1036 | my $old_perm_raw = (stat $file)[2]; | ||
| 1037 | # test to see if suidbit is set | ||
| 1038 | my $suid_bit = (($old_perm_raw/2048) % 2); | ||
| 1039 | if($suid_bit == 1){ | ||
| 1040 | # new permission without the suid bit | ||
| 1041 | my $new_perm = ((($old_perm_raw/512) % 8 ) - 4) . | ||
| 1042 | (($old_perm_raw/64) % 8 ) . | ||
| 1043 | (($old_perm_raw/8) % 8 ) . | ||
| 1044 | (($old_perm_raw) % 8 ); | ||
| 1045 | if(&B_chmod(oct($new_perm), $file)){ | ||
| 1046 | &B_log("ACTION","Removed SUID bit from \"$file\"."); | ||
| 1047 | } | ||
| 1048 | else { | ||
| 1049 | &B_log("ERROR","Could not remove SUID bit from \"$file\"."); | ||
| 1050 | } | ||
| 1051 | } # No action if SUID bit is not set | ||
| 1052 | }# No action if file does not exist | ||
| 1053 | }# Repeat for each file in the file glob | ||
| 1054 | } # unless Global_log | ||
| 1055 | } | ||
| 1056 | |||
| 1057 | |||
| 1058 | |||
| 1059 | 1; | ||
| 1060 | |||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/FileContent.pm b/dynamic-layers/meta-perl/recipes-security/bastille/files/FileContent.pm new file mode 100644 index 0000000..1ef89dd --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/FileContent.pm | |||
| @@ -0,0 +1,1153 @@ | |||
| 1 | package Bastille::API::FileContent; | ||
| 2 | use strict; | ||
| 3 | |||
| 4 | use Bastille::API; | ||
| 5 | |||
| 6 | require Exporter; | ||
| 7 | our @ISA = qw(Exporter); | ||
| 8 | our @EXPORT_OK = qw( | ||
| 9 | B_blank_file | ||
| 10 | B_insert_line_after | ||
| 11 | B_insert_line_before | ||
| 12 | B_insert_line | ||
| 13 | B:append_line | ||
| 14 | B:prepend_line | ||
| 15 | B_replace_line | ||
| 16 | B_replace_lines | ||
| 17 | B_replace_pattern | ||
| 18 | B_match_line | ||
| 19 | B_match_line_only | ||
| 20 | B_match_chunk | ||
| 21 | B_return_matched_lines | ||
| 22 | B_hash_comment_line | ||
| 23 | B_hash_uncomment_line | ||
| 24 | B_delete_line | ||
| 25 | B_chunk_replace | ||
| 26 | B_print | ||
| 27 | B_getValueFromFile | ||
| 28 | B_getValueFromString | ||
| 29 | |||
| 30 | B_TODO | ||
| 31 | B_TODOFlags | ||
| 32 | ); | ||
| 33 | our @EXPORT = @EXPORT_OK; | ||
| 34 | |||
| 35 | |||
| 36 | |||
| 37 | ########################################################################### | ||
| 38 | # &B_blank_file ($filename,$pattern) blanks the file $filename, unless the | ||
| 39 | # pattern $pattern is present in the file. This lets us completely redo | ||
| 40 | # a file, if it isn't the one we put in place on a previous run... | ||
| 41 | # | ||
| 42 | # B_blank_file respects $GLOBAL_LOGONLY and uses B_open_plus and B_close_plus | ||
| 43 | # so that it makes backups and only modifies files when we're not in "-v" | ||
| 44 | # mode... | ||
| 45 | # | ||
| 46 | # If the file does not exist, the function does nothing, and gives an error | ||
| 47 | # to the Error Log | ||
| 48 | # | ||
| 49 | ########################################################################### | ||
| 50 | |||
| 51 | sub B_blank_file($$) { | ||
| 52 | |||
| 53 | my ($filename,$pattern) = @_; | ||
| 54 | my $retval; | ||
| 55 | |||
| 56 | # If this variable is true, we won't blank the file... | ||
| 57 | |||
| 58 | my $found_pattern=0; | ||
| 59 | |||
| 60 | if ($retval=&B_open_plus (*BLANK_NEW,*BLANK_OLD,$filename) ) { | ||
| 61 | |||
| 62 | my @lines; | ||
| 63 | |||
| 64 | while (my $line = <BLANK_OLD>) { | ||
| 65 | |||
| 66 | push @lines,$line; | ||
| 67 | if ($line =~ $pattern) { | ||
| 68 | $found_pattern=1; | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | # Only copy the old file if the new one didn't match. | ||
| 73 | if ($found_pattern) { | ||
| 74 | while ( my $line = shift @lines ) { | ||
| 75 | &B_print(*BLANK_NEW,$line); | ||
| 76 | } | ||
| 77 | } | ||
| 78 | else { | ||
| 79 | &B_log("ACTION","Blanked file $filename\n"); | ||
| 80 | } | ||
| 81 | &B_close_plus(*BLANK_NEW,*BLANK_OLD,$filename); | ||
| 82 | } | ||
| 83 | else { | ||
| 84 | &B_log("ERROR","Couldn't blank file $filename since we couldn't open it or its replacement\n"); | ||
| 85 | } | ||
| 86 | |||
| 87 | return $retval; | ||
| 88 | |||
| 89 | } | ||
| 90 | |||
| 91 | ########################################################################### | ||
| 92 | # &B_insert_line_after ($filename,$pattern,$line_to_insert,$line_to_follow) | ||
| 93 | # modifies $filename, inserting $line_to_insert unless one or more lines | ||
| 94 | # in the file matches $pattern. The $line_to_insert will be placed | ||
| 95 | # immediately after $line_to_follow, if it exists. If said line does not | ||
| 96 | # exist, the line will not be inserted and this routine will return 0. | ||
| 97 | # | ||
| 98 | # B_insert_line uses B_open_plus and B_close_plus, so that the file | ||
| 99 | # modified is backed up... | ||
| 100 | # | ||
| 101 | # Here's examples of where you might use this: | ||
| 102 | # | ||
| 103 | # You'd like to insert a line in Apache's configuration file, in a | ||
| 104 | # particular section. | ||
| 105 | # | ||
| 106 | ########################################################################### | ||
| 107 | |||
| 108 | sub B_insert_line_after($$$$) { | ||
| 109 | |||
| 110 | my ($filename,$pattern,$line_to_insert,$line_to_follow) = @_; | ||
| 111 | |||
| 112 | my @lines; | ||
| 113 | my $found_pattern=0; | ||
| 114 | my $found_line_to_follow=0; | ||
| 115 | |||
| 116 | my $retval=1; | ||
| 117 | |||
| 118 | if ( &B_open_plus (*INSERT_NEW,*INSERT_OLD,$filename) ) { | ||
| 119 | |||
| 120 | # Read through the file looking for a match both on the $pattern | ||
| 121 | # and the line we are supposed to be inserting after... | ||
| 122 | |||
| 123 | my $ctr=1; | ||
| 124 | while (my $line=<INSERT_OLD>) { | ||
| 125 | push (@lines,$line); | ||
| 126 | if ($line =~ $pattern) { | ||
| 127 | $found_pattern=1; | ||
| 128 | } | ||
| 129 | if ( ($found_line_to_follow < 1) and ($line =~ $line_to_follow)) { | ||
| 130 | $found_line_to_follow=$ctr; | ||
| 131 | } | ||
| 132 | $ctr++; | ||
| 133 | } | ||
| 134 | |||
| 135 | # Log an error if we never found the line we were to insert after | ||
| 136 | unless ($found_line_to_follow ) { | ||
| 137 | $retval=0; | ||
| 138 | &B_log("ERROR","Never found the line that we were supposed to insert after in $filename\n"); | ||
| 139 | } | ||
| 140 | |||
| 141 | # Now print the file back out, inserting our line if we should... | ||
| 142 | |||
| 143 | $ctr=1; | ||
| 144 | while (my $line = shift @lines) { | ||
| 145 | &B_print(*INSERT_NEW,$line); | ||
| 146 | if ( ($ctr == $found_line_to_follow) and ($found_pattern == 0) ) { | ||
| 147 | &B_print(*INSERT_NEW,$line_to_insert); | ||
| 148 | &B_log("ACTION","Inserted the following line in $filename:\n"); | ||
| 149 | &B_log("ACTION","$line_to_insert"); | ||
| 150 | } | ||
| 151 | $ctr++; | ||
| 152 | } | ||
| 153 | |||
| 154 | &B_close_plus (*INSERT_NEW,*INSERT_OLD,$filename); | ||
| 155 | |||
| 156 | } | ||
| 157 | else { | ||
| 158 | $retval=0; | ||
| 159 | &B_log("ERROR","Couldn't insert line to $filename, since open failed."); | ||
| 160 | } | ||
| 161 | |||
| 162 | return $retval; | ||
| 163 | |||
| 164 | } | ||
| 165 | ########################################################################### | ||
| 166 | # &B_insert_line_before ($filename,$pattern,$line_to_insert,$line_to_preceed) | ||
| 167 | # modifies $filename, inserting $line_to_insert unless one or more lines | ||
| 168 | # in the file matches $pattern. The $line_to_insert will be placed | ||
| 169 | # immediately before $line_to_preceed, if it exists. If said line does not | ||
| 170 | # exist, the line will not be inserted and this routine will return 0. | ||
| 171 | # | ||
| 172 | # B_insert_line uses B_open_plus and B_close_plus, so that the file | ||
| 173 | # modified is backed up... | ||
| 174 | # | ||
| 175 | # Here's examples of where you might use this: | ||
| 176 | # | ||
| 177 | # You'd like to insert a line in Apache's configuration file, in a | ||
| 178 | # particular section. | ||
| 179 | # | ||
| 180 | ########################################################################### | ||
| 181 | |||
| 182 | sub B_insert_line_before($$$$) { | ||
| 183 | |||
| 184 | my ($filename,$pattern,$line_to_insert,$line_to_preceed) = @_; | ||
| 185 | |||
| 186 | my @lines; | ||
| 187 | my $found_pattern=0; | ||
| 188 | my $found_line_to_preceed=0; | ||
| 189 | |||
| 190 | my $retval=1; | ||
| 191 | |||
| 192 | if ( &B_open_plus (*INSERT_NEW,*INSERT_OLD,$filename) ) { | ||
| 193 | |||
| 194 | # Read through the file looking for a match both on the $pattern | ||
| 195 | # and the line we are supposed to be inserting after... | ||
| 196 | |||
| 197 | my $ctr=1; | ||
| 198 | while (my $line=<INSERT_OLD>) { | ||
| 199 | push (@lines,$line); | ||
| 200 | if ($line =~ $pattern) { | ||
| 201 | $found_pattern=1; | ||
| 202 | } | ||
| 203 | if ( ($found_line_to_preceed < 1) and ($line =~ $line_to_preceed)) { | ||
| 204 | $found_line_to_preceed=$ctr; | ||
| 205 | } | ||
| 206 | $ctr++; | ||
| 207 | } | ||
| 208 | |||
| 209 | # Log an error if we never found the line we were to preceed | ||
| 210 | unless ($found_line_to_preceed ) { | ||
| 211 | $retval=0; | ||
| 212 | &B_log("ERROR","Never found the line that we were supposed to insert before in $filename\n"); | ||
| 213 | } | ||
| 214 | |||
| 215 | # Now print the file back out, inserting our line if we should... | ||
| 216 | |||
| 217 | $ctr=1; | ||
| 218 | while (my $line = shift @lines) { | ||
| 219 | if ( ($ctr == $found_line_to_preceed) and ($found_pattern == 0) ) { | ||
| 220 | &B_print(*INSERT_NEW,$line_to_insert); | ||
| 221 | &B_log("ACTION","Inserted the following line in $filename:\n"); | ||
| 222 | &B_log("ACTION","$line_to_insert"); | ||
| 223 | } | ||
| 224 | &B_print(*INSERT_NEW,$line); | ||
| 225 | $ctr++; | ||
| 226 | } | ||
| 227 | |||
| 228 | &B_close_plus (*INSERT_NEW,*INSERT_OLD,$filename); | ||
| 229 | |||
| 230 | } | ||
| 231 | else { | ||
| 232 | $retval=0; | ||
| 233 | &B_log("ERROR","Couldn't insert line to $filename, since open failed."); | ||
| 234 | } | ||
| 235 | |||
| 236 | return $retval; | ||
| 237 | |||
| 238 | } | ||
| 239 | |||
| 240 | ########################################################################### | ||
| 241 | # &B_insert_line ($filename,$pattern,$line_to_insert,$line_to_follow) | ||
| 242 | # | ||
| 243 | # has been renamed to B_insert_line_after() | ||
| 244 | # | ||
| 245 | # This name will continue to work, as a shim for code that has not been | ||
| 246 | # transitioned. | ||
| 247 | ########################################################################### | ||
| 248 | |||
| 249 | sub B_insert_line($$$$) { | ||
| 250 | |||
| 251 | my $rtn_value = &B_insert_line_after(@_); | ||
| 252 | |||
| 253 | return ($rtn_value); | ||
| 254 | } | ||
| 255 | |||
| 256 | |||
| 257 | ########################################################################### | ||
| 258 | # &B_append_line ($filename,$pattern,$line_to_append) modifies $filename, | ||
| 259 | # appending $line_to_append unless one or more lines in the file matches | ||
| 260 | # $pattern. This is an enhancement to the append_line_if_no_such_line_exists | ||
| 261 | # idea. | ||
| 262 | # | ||
| 263 | # Additionally, if $pattern is set equal to "", the line is always appended. | ||
| 264 | # | ||
| 265 | # B:append_line uses B_open_plus and B_close_plus, so that the file | ||
| 266 | # modified is backed up... | ||
| 267 | # | ||
| 268 | # Here's examples of where you might use this: | ||
| 269 | # | ||
| 270 | # You'd like to add a root line to /etc/ftpusers if none exists. | ||
| 271 | # You'd like to add a Options Indexes line to Apache's config. file, | ||
| 272 | # after you delete all Options lines from said config file. | ||
| 273 | # | ||
| 274 | ########################################################################### | ||
| 275 | |||
| 276 | sub B:append_line($$$) { | ||
| 277 | |||
| 278 | my ($filename,$pattern,$line_to_append) = @_; | ||
| 279 | |||
| 280 | my $found_pattern=0; | ||
| 281 | my $retval=1; | ||
| 282 | |||
| 283 | if ( &B_open_plus (*APPEND_NEW,*APPEND_OLD,$filename) ) { | ||
| 284 | while (my $line=<APPEND_OLD>) { | ||
| 285 | &B_print(*APPEND_NEW,$line); | ||
| 286 | if ($line =~ $pattern) { | ||
| 287 | $found_pattern=1; | ||
| 288 | } | ||
| 289 | } | ||
| 290 | # Changed != 0 to $pattern so that "" works instead of 0 and perl | ||
| 291 | # does not give the annoying | ||
| 292 | # Argument "XX" isn't numeric in ne at ... | ||
| 293 | if ( $pattern eq "" or ! $found_pattern ) { | ||
| 294 | &B_print(*APPEND_NEW,$line_to_append); | ||
| 295 | &B_log("ACTION","Appended the following line to $filename:\n"); | ||
| 296 | &B_log("ACTION","$line_to_append"); | ||
| 297 | } | ||
| 298 | &B_close_plus (*APPEND_NEW,*APPEND_OLD,$filename); | ||
| 299 | } | ||
| 300 | else { | ||
| 301 | $retval=0; | ||
| 302 | &B_log("ERROR","# Couldn't append line to $filename, since open failed."); | ||
| 303 | } | ||
| 304 | |||
| 305 | return $retval; | ||
| 306 | |||
| 307 | } | ||
| 308 | |||
| 309 | ########################################################################### | ||
| 310 | # &B_prepend_line ($filename,$pattern,$line_to_prepend) modifies $filename, | ||
| 311 | # pre-pending $line_to:prepend unless one or more lines in the file matches | ||
| 312 | # $pattern. This is an enhancement to the prepend_line_if_no_such_line_exists | ||
| 313 | # idea. | ||
| 314 | # | ||
| 315 | # B:prepend_line uses B_open_plus and B_close_plus, so that the file | ||
| 316 | # modified is backed up... | ||
| 317 | # | ||
| 318 | # Here's examples of where you might use this: | ||
| 319 | # | ||
| 320 | # You'd like to insert the line "auth required pam_deny.so" to the top | ||
| 321 | # of the PAM stack file /etc/pam.d/rsh to totally deactivate rsh. | ||
| 322 | # | ||
| 323 | ########################################################################### | ||
| 324 | |||
| 325 | sub B:prepend_line($$$) { | ||
| 326 | |||
| 327 | my ($filename,$pattern,$line_to_prepend) = @_; | ||
| 328 | |||
| 329 | my @lines; | ||
| 330 | my $found_pattern=0; | ||
| 331 | my $retval=1; | ||
| 332 | |||
| 333 | if ( &B_open_plus (*PREPEND_NEW,*PREPEND_OLD,$filename) ) { | ||
| 334 | while (my $line=<PREPEND_OLD>) { | ||
| 335 | push (@lines,$line); | ||
| 336 | if ($line =~ $pattern) { | ||
| 337 | $found_pattern=1; | ||
| 338 | } | ||
| 339 | } | ||
| 340 | unless ($found_pattern) { | ||
| 341 | &B_print(*PREPEND_NEW,$line_to_prepend); | ||
| 342 | } | ||
| 343 | while (my $line = shift @lines) { | ||
| 344 | &B_print(*PREPEND_NEW,$line); | ||
| 345 | } | ||
| 346 | |||
| 347 | &B_close_plus (*PREPEND_NEW,*PREPEND_OLD,$filename); | ||
| 348 | |||
| 349 | # Log the action | ||
| 350 | &B_log("ACTION","Pre-pended the following line to $filename:\n"); | ||
| 351 | &B_log("ACTION","$line_to:prepend"); | ||
| 352 | } | ||
| 353 | else { | ||
| 354 | $retval=0; | ||
| 355 | &B_log("ERROR","Couldn't prepend line to $filename, since open failed.\n"); | ||
| 356 | } | ||
| 357 | |||
| 358 | return $retval; | ||
| 359 | |||
| 360 | } | ||
| 361 | |||
| 362 | |||
| 363 | ########################################################################### | ||
| 364 | # &B_replace_line ($filename,$pattern,$line_to_switch_in) modifies $filename, | ||
| 365 | # replacing any lines matching $pattern with $line_to_switch_in. | ||
| 366 | # | ||
| 367 | # It returns the number of lines it replaced (or would have replaced, if | ||
| 368 | # LOGONLY mode wasn't on...) | ||
| 369 | # | ||
| 370 | # B_replace_line uses B_open_plus and B_close_plus, so that the file | ||
| 371 | # modified is backed up... | ||
| 372 | # | ||
| 373 | # Here an example of where you might use this: | ||
| 374 | # | ||
| 375 | # You'd like to replace any Options lines in Apache's config file with: | ||
| 376 | # Options Indexes FollowSymLinks | ||
| 377 | # | ||
| 378 | ########################################################################### | ||
| 379 | |||
| 380 | sub B_replace_line($$$) { | ||
| 381 | |||
| 382 | my ($filename,$pattern,$line_to_switch_in) = @_; | ||
| 383 | my $retval=0; | ||
| 384 | |||
| 385 | if ( &B_open_plus (*REPLACE_NEW,*REPLACE_OLD,$filename) ) { | ||
| 386 | while (my $line=<REPLACE_OLD>) { | ||
| 387 | unless ($line =~ $pattern) { | ||
| 388 | &B_print(*REPLACE_NEW,$line); | ||
| 389 | } | ||
| 390 | else { | ||
| 391 | # Don't replace the line if it's already there. | ||
| 392 | unless ($line eq $line_to_switch_in) { | ||
| 393 | &B_print(*REPLACE_NEW,$line_to_switch_in); | ||
| 394 | |||
| 395 | $retval++; | ||
| 396 | &B_log("ACTION","File modification in $filename -- replaced line\n" . | ||
| 397 | "$line\n" . | ||
| 398 | "with:\n" . | ||
| 399 | "$line_to_switch_in"); | ||
| 400 | } | ||
| 401 | # But if it is there, make sure it stays there! (by Paul Allen) | ||
| 402 | else { | ||
| 403 | &B_print(*REPLACE_NEW,$line); | ||
| 404 | } | ||
| 405 | } | ||
| 406 | } | ||
| 407 | &B_close_plus (*REPLACE_NEW,*REPLACE_OLD,$filename); | ||
| 408 | } | ||
| 409 | else { | ||
| 410 | $retval=0; | ||
| 411 | &B_log("ERROR","Couldn't replace line(s) in $filename because open failed.\n"); | ||
| 412 | } | ||
| 413 | |||
| 414 | return $retval; | ||
| 415 | } | ||
| 416 | |||
| 417 | ########################################################################### | ||
| 418 | # &B_replace_lines ($filename,$patterns_and_substitutes) modifies $filename, | ||
| 419 | # replacing the line matching the nth $pattern specified in $patterns_and_substitutes->[n]->[0] | ||
| 420 | # with the corresponding substitutes in $patterns_and_substitutes->[n]->-[1] | ||
| 421 | # | ||
| 422 | # It returns the number of lines it replaced (or would have replaced, if | ||
| 423 | # LOGONLY mode wasn't on...) | ||
| 424 | # | ||
| 425 | # B_replace_lines uses B_open_plus and B_close_plus, so that the file | ||
| 426 | # modified is backed up... | ||
| 427 | # | ||
| 428 | # Here an example of where you might use this: | ||
| 429 | # | ||
| 430 | # You'd like to replace /etc/opt/ssh/sshd_config file | ||
| 431 | # (^#|^)Protocol\s+(.*)\s*$ ==> Protocol 2 | ||
| 432 | # (^#|^)X11Forwarding\s+(.*)\s*$ ==> X11Forwarding yes | ||
| 433 | # (^#|^)IgnoreRhosts\s+(.*)\s*$ ==> gnoreRhosts yes | ||
| 434 | # (^#|^)RhostsAuthentication\s+(.*)\s*$ ==> RhostsAuthentication no | ||
| 435 | # (^#|^)RhostsRSAAuthentication\s+(.*)\s*$ ==> RhostsRSAAuthentication no | ||
| 436 | # (^#|^)PermitRootLogin\s+(.*)\s*$ ==> PermitRootLogin no | ||
| 437 | # (^#|^)PermitEmptyPasswords\s+(.*)\s*$ ==> PermitEmptyPasswords no | ||
| 438 | # my $patterns_and_substitutes = [ | ||
| 439 | # [ '(^#|^)Protocol\s+(.*)\s*$' => 'Protocol 2'], | ||
| 440 | # ['(^#|^)X11Forwarding\s+(.*)\s*$' => 'X11Forwarding yes'], | ||
| 441 | # ['(^#|^)IgnoreRhosts\s+(.*)\s*$' => 'gnoreRhosts yes'], | ||
| 442 | # ['(^#|^)RhostsAuthentication\s+(.*)\s*$' => 'RhostsAuthentication no'], | ||
| 443 | # ['(^#|^)RhostsRSAAuthentication\s+(.*)\s*$' => 'RhostsRSAAuthentication no'], | ||
| 444 | # ['(^#|^)PermitRootLogin\s+(.*)\s*$' => 'PermitRootLogin no'], | ||
| 445 | # ['(^#|^)PermitEmptyPasswords\s+(.*)\s*$' => 'PermitEmptyPasswords no'] | ||
| 446 | #] | ||
| 447 | # B_replaces_lines($sshd_config,$patterns_and_substitutes); | ||
| 448 | ########################################################################### | ||
| 449 | |||
| 450 | sub B_replace_lines($$){ | ||
| 451 | my ($filename, $pairs) = @_; | ||
| 452 | my $retval = 0; | ||
| 453 | if ( &B_open_plus (*REPLACE_NEW,*REPLACE_OLD,$filename) ) { | ||
| 454 | while (my $line = <REPLACE_OLD>) { | ||
| 455 | my $switch; | ||
| 456 | my $switch_before = $line; | ||
| 457 | chomp($line); | ||
| 458 | foreach my $pair (@$pairs) { | ||
| 459 | $switch = 0; | ||
| 460 | |||
| 461 | my $pattern = $pair->[0] ; | ||
| 462 | my $replace = $pair->[1]; | ||
| 463 | my $evalstr = '$line' . "=~ s/$pattern/$replace/"; | ||
| 464 | eval $evalstr; | ||
| 465 | if ($@) { | ||
| 466 | &B_log("ERROR", "eval $evalstr failed.\n"); | ||
| 467 | } | ||
| 468 | #if ( $line =~ s/$pair->[0]/$pair->[1]/) { | ||
| 469 | # $switch = 1; | ||
| 470 | # last; | ||
| 471 | #} | ||
| 472 | } | ||
| 473 | &B_print(*REPLACE_NEW,"$line\n"); | ||
| 474 | if ($switch) { | ||
| 475 | $retval++; | ||
| 476 | B_log("ACTION","File modification in $filename -- replaced line\n" . | ||
| 477 | "$switch_before\n" . | ||
| 478 | "with:\n" . | ||
| 479 | "$line\n"); | ||
| 480 | } | ||
| 481 | } | ||
| 482 | &B_close_plus (*REPLACE_NEW,*REPLACE_OLD,$filename); | ||
| 483 | return 1; | ||
| 484 | } | ||
| 485 | else { | ||
| 486 | $retval=0; | ||
| 487 | &B_log("ERROR","Couldn't replace line(s) in $filename because open failed.\n"); | ||
| 488 | } | ||
| 489 | } | ||
| 490 | |||
| 491 | ################################################################################################ | ||
| 492 | # &B_replace_pattern ($filename,$pattern,$pattern_to_remove,$text_to_switch_in) | ||
| 493 | # modifies $filename, acting on only lines that match $pattern, replacing a | ||
| 494 | # string that matches $pattern_to_remove with $text_to_switch_in. | ||
| 495 | # | ||
| 496 | # Ex: | ||
| 497 | # B_replace_pattern('/etc/httpd.conf','^\s*Options.*\bIncludes\b','Includes','IncludesNoExec') | ||
| 498 | # | ||
| 499 | # replaces all "Includes" with "IncludesNoExec" on Apache Options lines. | ||
| 500 | # | ||
| 501 | # It returns the number of lines it altered (or would have replaced, if | ||
| 502 | # LOGONLY mode wasn't on...) | ||
| 503 | # | ||
| 504 | # B_replace_pattern uses B_open_plus and B_close_plus, so that the file | ||
| 505 | # modified is backed up... | ||
| 506 | # | ||
| 507 | ################################################################################################# | ||
| 508 | |||
| 509 | sub B_replace_pattern($$$$) { | ||
| 510 | |||
| 511 | my ($filename,$pattern,$pattern_to_remove,$text_to_switch_in) = @_; | ||
| 512 | my $retval=0; | ||
| 513 | |||
| 514 | if ( &B_open_plus (*REPLACE_NEW,*REPLACE_OLD,$filename) ) { | ||
| 515 | while (my $line=<REPLACE_OLD>) { | ||
| 516 | unless ($line =~ $pattern) { | ||
| 517 | &B_print(*REPLACE_NEW,$line); | ||
| 518 | } | ||
| 519 | else { | ||
| 520 | my $orig_line =$line; | ||
| 521 | $line =~ s/$pattern_to_remove/$text_to_switch_in/; | ||
| 522 | |||
| 523 | &B_print(*REPLACE_NEW,$line); | ||
| 524 | |||
| 525 | $retval++; | ||
| 526 | &B_log("ACTION","File modification in $filename -- replaced line\n" . | ||
| 527 | "$orig_line\n" . | ||
| 528 | "via pattern with:\n" . | ||
| 529 | "$line\n\n"); | ||
| 530 | } | ||
| 531 | } | ||
| 532 | &B_close_plus (*REPLACE_NEW,*REPLACE_OLD,$filename); | ||
| 533 | } | ||
| 534 | else { | ||
| 535 | $retval=0; | ||
| 536 | &B_log("ERROR","Couldn't pattern-replace line(s) in $filename because open failed.\n"); | ||
| 537 | } | ||
| 538 | |||
| 539 | return $retval; | ||
| 540 | } | ||
| 541 | |||
| 542 | |||
| 543 | ########################################################################### | ||
| 544 | # &B_match_line($file,$pattern); | ||
| 545 | # | ||
| 546 | # This subroutine will return a 1 if the pattern specified can be matched | ||
| 547 | # against the file specified. It will return a 0 otherwise. | ||
| 548 | # | ||
| 549 | # return values: | ||
| 550 | # 0: pattern not in file or the file is not readable | ||
| 551 | # 1: pattern is in file | ||
| 552 | ########################################################################### | ||
| 553 | sub B_match_line($$) { | ||
| 554 | # file to be checked and pattern to check for. | ||
| 555 | my ($file,$pattern) = @_; | ||
| 556 | # if the file is readable then | ||
| 557 | if(-r $file) { | ||
| 558 | # if the file can be opened then | ||
| 559 | if(open FILE,"<$file") { | ||
| 560 | # look at each line in the file | ||
| 561 | while (my $line = <FILE>) { | ||
| 562 | # if a line matches the pattern provided then | ||
| 563 | if($line =~ $pattern) { | ||
| 564 | # return the pattern was found | ||
| 565 | B_log('DEBUG','Pattern: ' . $pattern . ' matched in file: ' . | ||
| 566 | $file . "\n"); | ||
| 567 | return 1; | ||
| 568 | } | ||
| 569 | } | ||
| 570 | } | ||
| 571 | # if the file cann't be opened then | ||
| 572 | else { | ||
| 573 | # send a note to that affect to the errorlog | ||
| 574 | &B_log("ERROR","Unable to open file for read.\n$file\n$!\n"); | ||
| 575 | } | ||
| 576 | } | ||
| 577 | B_log('DEBUG','Pattern: ' . $pattern . ' not matched in file: ' . | ||
| 578 | $file . "\n"); | ||
| 579 | # the provided pattern was not matched against a line in the file | ||
| 580 | return 0; | ||
| 581 | } | ||
| 582 | |||
| 583 | ########################################################################### | ||
| 584 | # &B_match_line_only($file,$pattern); | ||
| 585 | # | ||
| 586 | # This subroutine checks if the specified pattern can be matched and if | ||
| 587 | # it's the only content in the file. The only content means it's only but | ||
| 588 | # may have several copies in the file. | ||
| 589 | # | ||
| 590 | # return values: | ||
| 591 | # 0: pattern not in file or pattern is not the only content | ||
| 592 | # or the file is not readable | ||
| 593 | # 1: pattern is in file and it's the only content | ||
| 594 | ############################################################################ | ||
| 595 | sub B_match_line_only($$) { | ||
| 596 | my ($file,$pattern) = @_; | ||
| 597 | |||
| 598 | # if matched, set to 1 later | ||
| 599 | my $retval = 0; | ||
| 600 | |||
| 601 | # if the file is readable then | ||
| 602 | if(-r $file) { | ||
| 603 | # if the file can be opened then | ||
| 604 | if(&B_open(*FILED, $file)) { | ||
| 605 | # pattern should be matched at least once | ||
| 606 | # pattern can not be mismatched | ||
| 607 | while (my $line = <FILED>) { | ||
| 608 | if ($line =~ $pattern) { | ||
| 609 | $retval = 1; | ||
| 610 | } | ||
| 611 | else { | ||
| 612 | &B_close(*FILED); | ||
| 613 | return 0; | ||
| 614 | } | ||
| 615 | } | ||
| 616 | } | ||
| 617 | &B_close(*FILED); | ||
| 618 | } | ||
| 619 | |||
| 620 | return $retval; | ||
| 621 | } | ||
| 622 | |||
| 623 | ########################################################################### | ||
| 624 | # &B_return_matched_lines($file,$pattern); | ||
| 625 | # | ||
| 626 | # This subroutine returns lines in a file matching a given regular | ||
| 627 | # expression, when called in the default list mode. When called in scalar | ||
| 628 | # mode, returns the number of elements found. | ||
| 629 | ########################################################################### | ||
| 630 | sub B_return_matched_lines($$) | ||
| 631 | { | ||
| 632 | my ($filename,$pattern) = @_; | ||
| 633 | my @lines = (); | ||
| 634 | |||
| 635 | open(READFILE, $filename); | ||
| 636 | while (<READFILE>) { | ||
| 637 | chomp; | ||
| 638 | next unless /$pattern/; | ||
| 639 | push(@lines, $_); | ||
| 640 | } | ||
| 641 | if (wantarray) | ||
| 642 | { | ||
| 643 | return @lines; | ||
| 644 | } | ||
| 645 | else | ||
| 646 | { | ||
| 647 | return scalar (@lines); | ||
| 648 | } | ||
| 649 | } | ||
| 650 | |||
| 651 | ########################################################################### | ||
| 652 | # &B_match_chunk($file,$pattern); | ||
| 653 | # | ||
| 654 | # This subroutine will return a 1 if the pattern specified can be matched | ||
| 655 | # against the file specified on a line-agnostic form. This allows for | ||
| 656 | # patterns which by necessity must match against a multi-line pattern. | ||
| 657 | # This is the natural analogue to B_replace_chunk, which was created to | ||
| 658 | # provide multi-line capability not provided by B_replace_line. | ||
| 659 | # | ||
| 660 | # return values: | ||
| 661 | # 0: pattern not in file or the file is not readable | ||
| 662 | # 1: pattern is in file | ||
| 663 | ########################################################################### | ||
| 664 | |||
| 665 | sub B_match_chunk($$) { | ||
| 666 | |||
| 667 | my ($file,$pattern) = @_; | ||
| 668 | my @lines; | ||
| 669 | my $big_long_line; | ||
| 670 | my $retval=1; | ||
| 671 | |||
| 672 | open CHUNK_FILE,$file; | ||
| 673 | |||
| 674 | # Read all lines into one scalar. | ||
| 675 | @lines = <CHUNK_FILE>; | ||
| 676 | close CHUNK_FILE; | ||
| 677 | |||
| 678 | foreach my $line ( @lines ) { | ||
| 679 | $big_long_line .= $line; | ||
| 680 | } | ||
| 681 | |||
| 682 | # Substitution routines get weird unless last line is terminated with \n | ||
| 683 | chomp $big_long_line; | ||
| 684 | $big_long_line .= "\n"; | ||
| 685 | |||
| 686 | # Exit if we don't find a match | ||
| 687 | unless ($big_long_line =~ $pattern) { | ||
| 688 | $retval = 0; | ||
| 689 | } | ||
| 690 | |||
| 691 | return $retval; | ||
| 692 | } | ||
| 693 | |||
| 694 | ########################################################################### | ||
| 695 | # &B_hash_comment_line ($filename,$pattern) modifies $filename, replacing | ||
| 696 | # any lines matching $pattern with a "hash-commented" version, like this: | ||
| 697 | # | ||
| 698 | # | ||
| 699 | # finger stream tcp nowait nobody /usr/sbin/tcpd in.fingerd | ||
| 700 | # becomes: | ||
| 701 | # #finger stream tcp nowait nobody /usr/sbin/tcpd in.fingerd | ||
| 702 | # | ||
| 703 | # Also: | ||
| 704 | # tftp dgram udp wait root /usr/lbin/tftpd tftpd\ | ||
| 705 | # /opt/ignite\ | ||
| 706 | # /var/opt/ignite | ||
| 707 | # becomes: | ||
| 708 | # #tftp dgram udp wait root /usr/lbin/tftpd tftpd\ | ||
| 709 | # # /opt/ignite\ | ||
| 710 | # # /var/opt/ignite | ||
| 711 | # | ||
| 712 | # | ||
| 713 | # B_hash_comment_line uses B_open_plus and B_close_plus, so that the file | ||
| 714 | # modified is backed up... | ||
| 715 | # | ||
| 716 | ########################################################################### | ||
| 717 | |||
| 718 | sub B_hash_comment_line($$) { | ||
| 719 | |||
| 720 | my ($filename,$pattern) = @_; | ||
| 721 | my $retval=1; | ||
| 722 | |||
| 723 | if ( &B_open_plus (*HASH_NEW,*HASH_OLD,$filename) ) { | ||
| 724 | my $line; | ||
| 725 | while ($line=<HASH_OLD>) { | ||
| 726 | unless ( ($line =~ $pattern) and ($line !~ /^\s*\#/) ) { | ||
| 727 | &B_print(*HASH_NEW,$line); | ||
| 728 | } | ||
| 729 | else { | ||
| 730 | &B_print(*HASH_NEW,"#$line"); | ||
| 731 | &B_log("ACTION","File modification in $filename -- hash commented line\n" . | ||
| 732 | "$line\n" . | ||
| 733 | "like this:\n" . | ||
| 734 | "#$line\n\n"); | ||
| 735 | # while the line has a trailing \ then we should also comment out the line below | ||
| 736 | while($line =~ m/\\\n$/) { | ||
| 737 | if($line=<HASH_OLD>) { | ||
| 738 | &B_print(*HASH_NEW,"#$line"); | ||
| 739 | &B_log("ACTION","File modification in $filename -- hash commented line\n" . | ||
| 740 | "$line\n" . | ||
| 741 | "like this:\n" . | ||
| 742 | "#$line\n\n"); | ||
| 743 | } | ||
| 744 | else { | ||
| 745 | $line = ""; | ||
| 746 | } | ||
| 747 | } | ||
| 748 | |||
| 749 | } | ||
| 750 | } | ||
| 751 | &B_close_plus (*HASH_NEW,*HASH_OLD,$filename); | ||
| 752 | } | ||
| 753 | else { | ||
| 754 | $retval=0; | ||
| 755 | &B_log("ERROR","Couldn't hash-comment line(s) in $filename because open failed.\n"); | ||
| 756 | } | ||
| 757 | |||
| 758 | return $retval; | ||
| 759 | } | ||
| 760 | |||
| 761 | |||
| 762 | ########################################################################### | ||
| 763 | # &B_hash_uncomment_line ($filename,$pattern) modifies $filename, | ||
| 764 | # removing any commenting from lines that match $pattern. | ||
| 765 | # | ||
| 766 | # #finger stream tcp nowait nobody /usr/sbin/tcpd in.fingerd | ||
| 767 | # becomes: | ||
| 768 | # finger stream tcp nowait nobody /usr/sbin/tcpd in.fingerd | ||
| 769 | # | ||
| 770 | # | ||
| 771 | # B_hash_uncomment_line uses B_open_plus and B_close_plus, so that the file | ||
| 772 | # modified is backed up... | ||
| 773 | # | ||
| 774 | ########################################################################### | ||
| 775 | |||
| 776 | sub B_hash_uncomment_line($$) { | ||
| 777 | |||
| 778 | my ($filename,$pattern) = @_; | ||
| 779 | my $retval=1; | ||
| 780 | |||
| 781 | if ( &B_open_plus (*HASH_NEW,*HASH_OLD,$filename) ) { | ||
| 782 | my $line; | ||
| 783 | while ($line=<HASH_OLD>) { | ||
| 784 | unless ( ($line =~ $pattern) and ($line =~ /^\s*\#/) ) { | ||
| 785 | &B_print(*HASH_NEW,$line); | ||
| 786 | } | ||
| 787 | else { | ||
| 788 | $line =~ /^\s*\#+(.*)$/; | ||
| 789 | $line = "$1\n"; | ||
| 790 | |||
| 791 | &B_print(*HASH_NEW,"$line"); | ||
| 792 | &B_log("ACTION","File modification in $filename -- hash uncommented line\n"); | ||
| 793 | &B_log("ACTION",$line); | ||
| 794 | # while the line has a trailing \ then we should also uncomment out the line below | ||
| 795 | while($line =~ m/\\\n$/) { | ||
| 796 | if($line=<HASH_OLD>) { | ||
| 797 | $line =~ /^\s*\#+(.*)$/; | ||
| 798 | $line = "$1\n"; | ||
| 799 | &B_print(*HASH_NEW,"$line"); | ||
| 800 | &B_log("ACTION","File modification in $filename -- hash uncommented line\n"); | ||
| 801 | &B_log("ACTION","#$line"); | ||
| 802 | &B_log("ACTION","like this:\n"); | ||
| 803 | &B_log("ACTION","$line"); | ||
| 804 | } | ||
| 805 | else { | ||
| 806 | $line = ""; | ||
| 807 | } | ||
| 808 | } | ||
| 809 | } | ||
| 810 | } | ||
| 811 | &B_close_plus (*HASH_NEW,*HASH_OLD,$filename); | ||
| 812 | } | ||
| 813 | else { | ||
| 814 | $retval=0; | ||
| 815 | &B_log("ERROR","Couldn't hash-uncomment line(s) in $filename because open failed.\n"); | ||
| 816 | } | ||
| 817 | |||
| 818 | return $retval; | ||
| 819 | } | ||
| 820 | |||
| 821 | |||
| 822 | |||
| 823 | ########################################################################### | ||
| 824 | # &B_delete_line ($filename,$pattern) modifies $filename, deleting any | ||
| 825 | # lines matching $pattern. It uses B_replace_line to do this. | ||
| 826 | # | ||
| 827 | # B_replace_line uses B_open_plus and B_close_plus, so that the file | ||
| 828 | # modified is backed up... | ||
| 829 | # | ||
| 830 | # Here an example of where you might use this: | ||
| 831 | # | ||
| 832 | # You'd like to remove any timeout= lines in /etc/lilo.conf, so that your | ||
| 833 | # delay=1 modification will work. | ||
| 834 | |||
| 835 | # | ||
| 836 | ########################################################################### | ||
| 837 | |||
| 838 | |||
| 839 | sub B_delete_line($$) { | ||
| 840 | |||
| 841 | my ($filename,$pattern)=@_; | ||
| 842 | my $retval=&B_replace_line($filename,$pattern,""); | ||
| 843 | |||
| 844 | return $retval; | ||
| 845 | } | ||
| 846 | |||
| 847 | |||
| 848 | ########################################################################### | ||
| 849 | # &B_chunk_replace ($file,$pattern,$replacement) reads $file replacing the | ||
| 850 | # first occurrence of $pattern with $replacement. | ||
| 851 | # | ||
| 852 | ########################################################################### | ||
| 853 | |||
| 854 | sub B_chunk_replace($$$) { | ||
| 855 | |||
| 856 | my ($file,$pattern,$replacement) = @_; | ||
| 857 | |||
| 858 | my @lines; | ||
| 859 | my $big_long_line; | ||
| 860 | my $retval=1; | ||
| 861 | |||
| 862 | &B_open (*OLDFILE,$file); | ||
| 863 | |||
| 864 | # Read all lines into one scalar. | ||
| 865 | @lines = <OLDFILE>; | ||
| 866 | &B_close (*OLDFILE); | ||
| 867 | foreach my $line ( @lines ) { | ||
| 868 | $big_long_line .= $line; | ||
| 869 | } | ||
| 870 | |||
| 871 | # Substitution routines get weird unless last line is terminated with \n | ||
| 872 | chomp $big_long_line; | ||
| 873 | $big_long_line .= "\n"; | ||
| 874 | |||
| 875 | # Exit if we don't find a match | ||
| 876 | unless ($big_long_line =~ $pattern) { | ||
| 877 | return 0; | ||
| 878 | } | ||
| 879 | |||
| 880 | $big_long_line =~ s/$pattern/$replacement/s; | ||
| 881 | |||
| 882 | $retval=&B_open_plus (*NEWFILE,*OLDFILE,$file); | ||
| 883 | if ($retval) { | ||
| 884 | &B_print (*NEWFILE,$big_long_line); | ||
| 885 | &B_close_plus (*NEWFILE,*OLDFILE,$file); | ||
| 886 | } | ||
| 887 | |||
| 888 | return $retval; | ||
| 889 | } | ||
| 890 | |||
| 891 | ########################################################################### | ||
| 892 | # &B_print ($handle,@list) prints the items of @list to the file handle | ||
| 893 | # $handle. It logs the action and respects the $GLOBAL_LOGONLY variable. | ||
| 894 | # | ||
| 895 | ########################################################################### | ||
| 896 | |||
| 897 | sub B_print { | ||
| 898 | my $handle=shift @_; | ||
| 899 | |||
| 900 | my $result=1; | ||
| 901 | |||
| 902 | unless ($GLOBAL_LOGONLY) { | ||
| 903 | $result=print $handle @_; | ||
| 904 | } | ||
| 905 | |||
| 906 | ($handle) = "$handle" =~ /[^:]+::[^:]+::([^:]+)/; | ||
| 907 | |||
| 908 | $result; | ||
| 909 | } | ||
| 910 | |||
| 911 | |||
| 912 | ########################################################################## | ||
| 913 | # &B_getValueFromFile($regex,$file); | ||
| 914 | # Takes a regex with a single group "()" and returns the unique value | ||
| 915 | # on any non-commented lines | ||
| 916 | # This (and B_return_matched_lines are only used in this file, though are | ||
| 917 | # probably more generally useful. For now, leaving these here serve the following | ||
| 918 | #functions: | ||
| 919 | # a) still gets exported/associated as part of the Test_API package, and | ||
| 920 | # is still availble for a couple operations that can't be deferred to the | ||
| 921 | # main test loop, as they save values so that individual tests don't have to | ||
| 922 | # recreate (copy / paste) the logic to get them. | ||
| 923 | # | ||
| 924 | # It also avoids the circular "use" if we incldued "use Test API" at the top | ||
| 925 | # of this file (Test API "uses" this file. | ||
| 926 | # Returns the uncommented, unique values of a param=value pair. | ||
| 927 | # | ||
| 928 | # Return values: | ||
| 929 | # 'Not Defined' if the value is not present or not uniquely defined. | ||
| 930 | # $value if the value is present and unique | ||
| 931 | # | ||
| 932 | ########################################################################### | ||
| 933 | sub B_getValueFromFile ($$){ | ||
| 934 | my $inputRegex=$_[0]; | ||
| 935 | my $file=$_[1]; | ||
| 936 | my ($lastvalue,$value)=''; | ||
| 937 | |||
| 938 | my @lines=&B_return_matched_lines($file, $inputRegex); | ||
| 939 | |||
| 940 | return &B_getValueFromString($inputRegex,join('/n',@lines)); | ||
| 941 | } | ||
| 942 | |||
| 943 | ########################################################################## | ||
| 944 | # &B_getValueFromString($param,$string); | ||
| 945 | # Takes a regex with a single group "()" and returns the unique value | ||
| 946 | # on any non-commented lines | ||
| 947 | # This (and B_return_matched_lines are only used in this file, though are | ||
| 948 | # probably more generally useful. For now, leaving these here serve the following | ||
| 949 | #functions: | ||
| 950 | # a) still gets exported/associated as part of the Test_API package, and | ||
| 951 | # is still availble for a couple operations that can't be deferred to the | ||
| 952 | # main test loop, as they save values so that individual tests don't have to | ||
| 953 | # recreate (copy / paste) the logic to get them. | ||
| 954 | # | ||
| 955 | # It also avoids the circular "use" if we incldued "use Test API" at the top | ||
| 956 | # of this file (Test API "uses" this file. | ||
| 957 | # Returns the uncommented, unique values of a param=value pair. | ||
| 958 | # | ||
| 959 | # Return values: | ||
| 960 | # 'Not Unique' if the value is not uniquely defined. | ||
| 961 | # undef if the value isn't defined at all | ||
| 962 | # $value if the value is present and unique | ||
| 963 | # | ||
| 964 | ########################################################################### | ||
| 965 | sub B_getValueFromString ($$){ | ||
| 966 | my $inputRegex=$_[0]; | ||
| 967 | my $inputString=$_[1]; | ||
| 968 | my $lastValue=''; | ||
| 969 | my $value=''; | ||
| 970 | |||
| 971 | my @lines=split(/\n/,$inputString); | ||
| 972 | |||
| 973 | &B_log("DEBUG","B_getvaluefromstring called with regex: $inputRegex and input: " . | ||
| 974 | $inputString); | ||
| 975 | foreach my $line (grep(/$inputRegex/,@lines)) { | ||
| 976 | $line =~ /$inputRegex/; | ||
| 977 | $value=$1; | ||
| 978 | if (($lastValue eq '') and ($value ne '')) { | ||
| 979 | $lastValue = $value; | ||
| 980 | } elsif (($lastValue ne $value) and ($value ne '')) { | ||
| 981 | B_log("DEBUG","getvaluefromstring returned Not Unique"); | ||
| 982 | return 'Not Unique'; | ||
| 983 | } | ||
| 984 | } | ||
| 985 | if ((not(defined($value))) or ($value eq '')) { | ||
| 986 | &B_log("DEBUG","Could not find regex match in string"); | ||
| 987 | return undef; | ||
| 988 | } else { | ||
| 989 | &B_log("DEBUG","B_getValueFromString Found: $value ; using: $inputRegex"); | ||
| 990 | return $value; | ||
| 991 | } | ||
| 992 | } | ||
| 993 | |||
| 994 | ############################################################### | ||
| 995 | # This function adds something to the To Do List. | ||
| 996 | # Arguments: | ||
| 997 | # 1) The string you want to add to the To Do List. | ||
| 998 | # 2) Optional: Question whose TODOFlag should be set to indicate | ||
| 999 | # A pending manual action in subsequent reports. Only skip this | ||
| 1000 | # If there's no security-audit relevant action you need the user to | ||
| 1001 | # accomplish | ||
| 1002 | # Ex: | ||
| 1003 | # &B_TODO("------\nInstalling IPFilter\n----\nGo get Ipfilter","IPFilter.install_ipfilter"); | ||
| 1004 | # | ||
| 1005 | # | ||
| 1006 | # Returns: | ||
| 1007 | # 0 - If error condition | ||
| 1008 | # True, if sucess, specifically: | ||
| 1009 | # "appended" if the append operation was successful | ||
| 1010 | # "exists" if no change was made since the entry was already present | ||
| 1011 | ############################################################### | ||
| 1012 | sub B_TODO ($;$) { | ||
| 1013 | my $text = $_[0]; | ||
| 1014 | my $FlaggedQuestion = $_[1]; | ||
| 1015 | my $multilineString = ""; | ||
| 1016 | |||
| 1017 | # trim off any leading and trailing new lines, regexes separated for "clarity" | ||
| 1018 | $text =~ s/^\n+(.*)/$1/; | ||
| 1019 | $text =~ s/(.*)\n+$/$1/; | ||
| 1020 | |||
| 1021 | if ( ! -e &getGlobal('BFILE',"TODO") ) { | ||
| 1022 | # Make the TODO list file for HP-UX Distro | ||
| 1023 | &B_create_file(&getGlobal('BFILE', "TODO")); | ||
| 1024 | &B_append_line(&getGlobal('BFILE', "TODO"),'a$b', | ||
| 1025 | "Please take the steps below to make your system more secure,\n". | ||
| 1026 | "then delete the item from this file and record what you did along\n". | ||
| 1027 | "with the date and time in your system administration log. You\n". | ||
| 1028 | "will need that information in case you ever need to revert your\n". | ||
| 1029 | "changes.\n\n"); | ||
| 1030 | } | ||
| 1031 | |||
| 1032 | |||
| 1033 | if (open(TODO,"<" . &getGlobal('BFILE', "TODO"))) { | ||
| 1034 | while (my $line = <TODO>) { | ||
| 1035 | # getting rid of all meta characters. | ||
| 1036 | $line =~ s/(\\|\||\(|\)|\[|\]|\{|\}|\^|\$|\*|\+|\?|\.)//g; | ||
| 1037 | $multilineString .= $line; | ||
| 1038 | } | ||
| 1039 | chomp $multilineString; | ||
| 1040 | $multilineString .= "\n"; | ||
| 1041 | |||
| 1042 | close(TODO); | ||
| 1043 | } | ||
| 1044 | else { | ||
| 1045 | &B_log("ERROR","Unable to read TODO.txt file.\n" . | ||
| 1046 | "The following text could not be appended to the TODO list:\n" . | ||
| 1047 | $text . | ||
| 1048 | "End of TODO text\n"); | ||
| 1049 | return 0; #False | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | my $textPattern = $text; | ||
| 1053 | |||
| 1054 | # getting rid of all meta characters. | ||
| 1055 | $textPattern =~ s/(\\|\||\(|\)|\[|\]|\{|\}|\^|\$|\*|\+|\?|\.)//g; | ||
| 1056 | |||
| 1057 | if( $multilineString !~ "$textPattern") { | ||
| 1058 | my $datestamp = "{" . localtime() . "}"; | ||
| 1059 | unless ( &B_append_line(&getGlobal('BFILE', "TODO"), "", $datestamp . "\n" . $text . "\n\n\n") ) { | ||
| 1060 | &B_log("ERROR","TODO Failed for text: " . $text ); | ||
| 1061 | } | ||
| 1062 | #Note that we only set the flag on the *initial* entry in the TODO File | ||
| 1063 | #Not on subsequent detection. This is to avoid the case where Bastille | ||
| 1064 | #complains on a subsequent Bastille run of an already-performed manual | ||
| 1065 | #action that the user neglected to delete from the TODO file. | ||
| 1066 | # It does, however lead to a report of "nonsecure" when the user | ||
| 1067 | #asked for the TODO item, performed it, Bastille detected that and cleared the | ||
| 1068 | # Item, and then the user unperformed the action. I think this is proper behavior. | ||
| 1069 | # rwf 06/06 | ||
| 1070 | |||
| 1071 | if (defined($FlaggedQuestion)) { | ||
| 1072 | &B_TODOFlags("set",$FlaggedQuestion); | ||
| 1073 | } | ||
| 1074 | return "appended"; #evals to true, and also notes what happened | ||
| 1075 | } else { | ||
| 1076 | return "exists"; #evals to true, and also | ||
| 1077 | } | ||
| 1078 | |||
| 1079 | } | ||
| 1080 | |||
| 1081 | |||
| 1082 | ##################################################################### | ||
| 1083 | # &B_TODOFlags() | ||
| 1084 | # | ||
| 1085 | # This is the interface to the TODO flags. Test functions set these when they | ||
| 1086 | # require a TODO item to be completed to get to a "secure" state. | ||
| 1087 | # The prune/reporting function checks these to ensure no flags are set before | ||
| 1088 | # reporting an item "secure" | ||
| 1089 | # "Methods" are load | save | isSet <Question> | set <Question> | unset <Question> | ||
| 1090 | # | ||
| 1091 | ###################################################################### | ||
| 1092 | |||
| 1093 | sub B_TODOFlags($;$) { | ||
| 1094 | my $action = $_[0]; | ||
| 1095 | my $module = $_[1]; | ||
| 1096 | |||
| 1097 | use File::Spec; | ||
| 1098 | |||
| 1099 | my $todo_flag = &getGlobal("BFILE","TODOFlag"); | ||
| 1100 | |||
| 1101 | &B_log("DEBUG","B_TODOFlags action: $action , module: $module"); | ||
| 1102 | |||
| 1103 | if ($action eq "load") { | ||
| 1104 | if (-e $todo_flag ) { | ||
| 1105 | &B_open(*TODO_FLAGS, $todo_flag); | ||
| 1106 | my @lines = <TODO_FLAGS>; | ||
| 1107 | foreach my $line (@lines) { | ||
| 1108 | chomp($line); | ||
| 1109 | $GLOBAL_CONFIG{"$line"}{"TODOFlag"}="yes"; | ||
| 1110 | } | ||
| 1111 | return (&B_close(*TODO_FLAGS)); #return success of final close | ||
| 1112 | } else { | ||
| 1113 | return 1; #No-op is okay | ||
| 1114 | } | ||
| 1115 | } elsif ($action eq "save") { | ||
| 1116 | # Make sure the file exists, else create | ||
| 1117 | #Note we use open_plus and and create file, so if Bastille is | ||
| 1118 | #reverted, all the flags will self-clear (file deleted) | ||
| 1119 | my $flagNumber = 0; | ||
| 1120 | my $flagData = ''; | ||
| 1121 | foreach my $key (keys %GLOBAL_CONFIG) { | ||
| 1122 | if ($GLOBAL_CONFIG{$key}{"TODOFlag"} eq "yes") { | ||
| 1123 | ++$flagNumber; | ||
| 1124 | $flagData .= "$key\n"; | ||
| 1125 | } | ||
| 1126 | } | ||
| 1127 | if (not( -e $todo_flag)) { | ||
| 1128 | &B_log("DEBUG","Initializing TODO Flag file: $todo_flag"); | ||
| 1129 | &B_create_file($todo_flag); # Make sure it exists | ||
| 1130 | } | ||
| 1131 | &B_blank_file($todo_flag, | ||
| 1132 | "This will not appear in the file; ensures blanking"); | ||
| 1133 | return &B_append_line($todo_flag, "", "$flagData"); #return success of save | ||
| 1134 | } elsif (($action eq "isSet") and ($module ne "")) { | ||
| 1135 | if ($GLOBAL_CONFIG{"$module"}{"TODOFlag"} eq "yes") { | ||
| 1136 | return 1; #TRUE | ||
| 1137 | } else { | ||
| 1138 | return 0; #FALSE | ||
| 1139 | } | ||
| 1140 | } elsif (($action eq "set") and ($module ne "")) { | ||
| 1141 | $GLOBAL_CONFIG{"$module"}{"TODOFlag"} = "yes"; | ||
| 1142 | } elsif (($action eq "clear") and ($module ne "")) { | ||
| 1143 | $GLOBAL_CONFIG{"$module"}{"TODOFlag"} = ""; | ||
| 1144 | } else { | ||
| 1145 | &B_log("ERROR","TODO_Flag Called with invalid parameters: $action , $module". | ||
| 1146 | "audit report may be incorrect."); | ||
| 1147 | return 0; #FALSE | ||
| 1148 | } | ||
| 1149 | } | ||
| 1150 | |||
| 1151 | 1; | ||
| 1152 | |||
| 1153 | |||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/HPSpecific.pm b/dynamic-layers/meta-perl/recipes-security/bastille/files/HPSpecific.pm new file mode 100644 index 0000000..7e7d709 --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/HPSpecific.pm | |||
| @@ -0,0 +1,1983 @@ | |||
| 1 | package Bastille::API::HPSpecific; | ||
| 2 | |||
| 3 | use strict; | ||
| 4 | use Bastille::API; | ||
| 5 | use Bastille::API::FileContent; | ||
| 6 | |||
| 7 | require Exporter; | ||
| 8 | our @ISA = qw(Exporter); | ||
| 9 | our @EXPORT_OK = qw( | ||
| 10 | getIPFLocation | ||
| 11 | getGlobalSwlist | ||
| 12 | B_check_system | ||
| 13 | B_swmodify | ||
| 14 | B_load_ipf_rules | ||
| 15 | B_Schedule | ||
| 16 | B_ch_rc | ||
| 17 | B_set_value | ||
| 18 | B_chperm | ||
| 19 | B_install_jail | ||
| 20 | B_list_processes | ||
| 21 | B_list_full_processes | ||
| 22 | B_deactivate_inetd_service | ||
| 23 | B_get_rc | ||
| 24 | B_set_rc | ||
| 25 | B_chrootHPapache | ||
| 26 | isSystemTrusted | ||
| 27 | isTrustedMigrationAvailable | ||
| 28 | checkServiceOnHPUX | ||
| 29 | B_get_path | ||
| 30 | convertToTrusted | ||
| 31 | isOKtoConvert | ||
| 32 | convertToShadow | ||
| 33 | getSupportedSettings | ||
| 34 | B_get_sec_value | ||
| 35 | secureIfNoNameService | ||
| 36 | isUsingRemoteNameService | ||
| 37 | remoteServiceCheck | ||
| 38 | remoteNISPlusServiceCheck | ||
| 39 | B_create_nsswitch_file | ||
| 40 | B_combine_service_results | ||
| 41 | |||
| 42 | %priorBastilleNDD | ||
| 43 | %newNDD | ||
| 44 | ); | ||
| 45 | our @EXPORT = @EXPORT_OK; | ||
| 46 | |||
| 47 | |||
| 48 | |||
| 49 | # "Constants" for use both in testing and in lock-down | ||
| 50 | our %priorBastilleNDD = ( | ||
| 51 | "ip_forward_directed_broadcasts" =>["ip", "0"], | ||
| 52 | "ip_forward_src_routed" =>["ip", "0"], | ||
| 53 | "ip_forwarding" =>["ip", "0"], | ||
| 54 | "ip_ire_gw_probe" =>["ip", "0"], | ||
| 55 | "ip_pmtu_strategy" =>["ip", "1"], | ||
| 56 | "ip_respond_to_echo_broadcast" =>["ip", "0"], | ||
| 57 | "ip_send_redirects" =>["ip", "0"], | ||
| 58 | "ip_send_source_quench" =>["ip", "0"], | ||
| 59 | "tcp_syn_rcvd_max" =>["tcp","1000"], | ||
| 60 | "tcp_conn_request_max" =>["tcp","4096"] ); | ||
| 61 | |||
| 62 | our %newNDD = ( | ||
| 63 | "ip_forward_directed_broadcasts" =>["ip", "0"], | ||
| 64 | "ip_forward_src_routed" =>["ip", "0"], | ||
| 65 | "ip_forwarding" =>["ip", "0"], | ||
| 66 | "ip_ire_gw_probe" =>["ip", "0"], | ||
| 67 | "ip_pmtu_strategy" =>["ip", "1"], | ||
| 68 | "ip_respond_to_echo_broadcast" =>["ip", "0"], | ||
| 69 | "ip_send_redirects" =>["ip", "0"], | ||
| 70 | "ip_send_source_quench" =>["ip", "0"], | ||
| 71 | "tcp_syn_rcvd_max" =>["tcp","4096"], | ||
| 72 | "tcp_conn_request_max" =>["tcp","4096"], | ||
| 73 | "arp_cleanup_interval" =>["arp","60000"], | ||
| 74 | "ip_respond_to_timestamp" =>["ip", "0"], | ||
| 75 | "ip_respond_to_timestamp_broadcast" => ["ip","0"] ); | ||
| 76 | |||
| 77 | |||
| 78 | #################################################################### | ||
| 79 | # | ||
| 80 | # This module makes up the HP-UX specific API routines. | ||
| 81 | # | ||
| 82 | #################################################################### | ||
| 83 | # | ||
| 84 | # Subroutine Listing: | ||
| 85 | # &HP_ConfigureForDistro: adds all used file names to global | ||
| 86 | # hashes and generates a global IPD | ||
| 87 | # hash for SD modification lookup. | ||
| 88 | # | ||
| 89 | # &getGlobalSwlist($): Takes a fully qualified file name | ||
| 90 | # and returns product:filset info | ||
| 91 | # for that file. returns undef if | ||
| 92 | # the file is not present in the IPD | ||
| 93 | # | ||
| 94 | # &B_check_system: Runs a series of system queries to | ||
| 95 | # determine if Bastille can be safely | ||
| 96 | # ran on the current system. | ||
| 97 | # | ||
| 98 | # &B_swmodify($): Takes a file name and runs the | ||
| 99 | # swmodify command on it so that the | ||
| 100 | # IPD is updated after changes | ||
| 101 | # | ||
| 102 | # &B_System($$): Takes a system command and the system | ||
| 103 | # command that should be used to revert | ||
| 104 | # whatever was done. Returns 1 on | ||
| 105 | # success and 0 on failure | ||
| 106 | # | ||
| 107 | # &B_Backtick($) Takes a command to run and returns its stdout | ||
| 108 | # to be used in place of the prior prevelent use | ||
| 109 | # of un-error-handled backticks | ||
| 110 | # | ||
| 111 | # &B_load_ipf_rules($): Loads a set of ipfrules into ipf, storing | ||
| 112 | # current rules for later reversion. | ||
| 113 | # | ||
| 114 | # &B_Schedule($$): Takes a pattern and a crontab line. | ||
| 115 | # Adds or replaces the crontab line to | ||
| 116 | # the crontab file, depending on if a | ||
| 117 | # line matches the pattern | ||
| 118 | # | ||
| 119 | # &B_ch_rc($$): Takes a the rc.config.d flag name and | ||
| 120 | # new value as well as the init script | ||
| 121 | # location. This will stop a services | ||
| 122 | # and set the service so that it will | ||
| 123 | # not be restarted. | ||
| 124 | # | ||
| 125 | # &B_set_value($$$): Takes a param, value, and a filename | ||
| 126 | # and sets the given value in the file. | ||
| 127 | # Uses ch_rc, but could be rewritten using | ||
| 128 | # Bastille API calls to make it work on Linux | ||
| 129 | # | ||
| 130 | # &B_TODO($): Appends the give string to the TODO.txt | ||
| 131 | # file. | ||
| 132 | # | ||
| 133 | # &B_chperm($$$$): Takes new perm owner and group of given | ||
| 134 | # file. TO BE DEPRECATED!!! | ||
| 135 | # | ||
| 136 | # &B_install_jail($$): Takes the jail name and the jail config | ||
| 137 | # script location for a give jail... | ||
| 138 | # These scripts can be found in the main | ||
| 139 | # directory e.g. jail.bind.hpux | ||
| 140 | # | ||
| 141 | ##################################################################### | ||
| 142 | |||
| 143 | ############################################################################## | ||
| 144 | # | ||
| 145 | # HP-UX Bastille directory structure | ||
| 146 | # | ||
| 147 | ############################################################################## | ||
| 148 | # | ||
| 149 | # /opt/sec_mgmt/bastille/bin/ -- location of Bastille binaries | ||
| 150 | # /opt/sec_mgmt/bastille/lib/ -- location of Bastille modules | ||
| 151 | # /opt/sec_mgmt/bastille/doc/ -- location of Bastille doc files | ||
| 152 | # | ||
| 153 | # /etc/opt/sec_mgmt/bastille/ -- location of Bastille config files | ||
| 154 | # | ||
| 155 | # /var/opt/sec_mgmt/bastille/log -- location of Bastille log files | ||
| 156 | # /var/opt/sec_mgmt/bastille/revert -- directory holding all Bastille- | ||
| 157 | # created revert scripts | ||
| 158 | # /var/opt/sec_mgmt/bastille/revert/backup -- directory holding the original | ||
| 159 | # files that Bastille modifies, | ||
| 160 | # with permissions intact | ||
| 161 | # | ||
| 162 | ############################################################################## | ||
| 163 | |||
| 164 | sub getIPFLocation () { # Temporary until we get defined search space support | ||
| 165 | my $ipf=&getGlobal('BIN','ipf_new'); | ||
| 166 | my $ipfstat=&getGlobal('BIN','ipfstat_new'); | ||
| 167 | if (not(-e $ipf)) { # Detect if the binaries moved | ||
| 168 | $ipf = &getGlobal('BIN','ipf'); | ||
| 169 | $ipfstat=&getGlobal('BIN','ipfstat'); | ||
| 170 | } | ||
| 171 | return ($ipf, $ipfstat); | ||
| 172 | } | ||
| 173 | |||
| 174 | ############################################## | ||
| 175 | # Given a combination of service results, provided | ||
| 176 | # in an array, this function combines the result into | ||
| 177 | # a reasonable aggregate result | ||
| 178 | ############################################## | ||
| 179 | |||
| 180 | sub B_combine_service_results(@){ | ||
| 181 | my @results = @_; | ||
| 182 | |||
| 183 | #TODO: Consider greater sophistication wrt inconsistent, or not installed. | ||
| 184 | |||
| 185 | foreach my $result (@results) { | ||
| 186 | if (not(($result == SECURE_CAN_CHANGE) or | ||
| 187 | ($result == SECURE_CANT_CHANGE) or | ||
| 188 | ($result == NOT_INSTALLED()))) { | ||
| 189 | return NOTSECURE_CAN_CHANGE(); | ||
| 190 | } | ||
| 191 | } | ||
| 192 | return SECURE_CANT_CHANGE(); | ||
| 193 | } | ||
| 194 | |||
| 195 | #################################################################### | ||
| 196 | # &getGlobalSwlist ($file); | ||
| 197 | # This function returns the product and fileset information for | ||
| 198 | # a given file or directory if it exists in the IPD otherwise | ||
| 199 | # it returns undefined "undef" | ||
| 200 | # | ||
| 201 | # uses $GLOBAL_SWLIST{"$FILE"} | ||
| 202 | #################################################################### | ||
| 203 | sub getGlobalSwlist($){ | ||
| 204 | no strict; | ||
| 205 | my $file = $_[0]; | ||
| 206 | |||
| 207 | |||
| 208 | if(! %GLOBAL_SWLIST) { | ||
| 209 | # Generating swlist database for swmodify changes that will be required | ||
| 210 | # The database will be a hash of fully qualified file names that reference | ||
| 211 | # the files product name and fileset. These values are required to use | ||
| 212 | # swmodify... | ||
| 213 | |||
| 214 | # Files tagged 'is_volatile' in the IPD are not entered in the swlist database | ||
| 215 | # in order to avoid invoking swmodify if the file is changed later. Attempting to | ||
| 216 | # swmodify 'volatile' files is both unneccessary and complicated since swverify will | ||
| 217 | # not evaluate volatile files anyway, and adding another value to the swlist database | ||
| 218 | # would require complex code changes. | ||
| 219 | |||
| 220 | # temp variable to keep swlist command /usr/sbin/swlist | ||
| 221 | my $swlist = &getGlobal('BIN',"swlist"); | ||
| 222 | |||
| 223 | # listing of each directory and file that was installed by SD on the target machine | ||
| 224 | my @fileList = `$swlist -a is_volatile -l file`; | ||
| 225 | |||
| 226 | # listing of each patch and the patches that supersede each. | ||
| 227 | # hash which is indexed by patch.fileset on the system | ||
| 228 | my %patchSuperseded; | ||
| 229 | |||
| 230 | my @patchList = `${swlist} -l fileset -a superseded_by *.*,c=patch 2>&1`; | ||
| 231 | # check to see if any patches are present on the system | ||
| 232 | if(($? >> 8) == 0) { | ||
| 233 | |||
| 234 | # determining patch suppression for swmodify. | ||
| 235 | foreach my $patchState (@patchList) { | ||
| 236 | # removing empty lines and commented lines. | ||
| 237 | if($patchState !~ /^\s*\#/ && $patchState !~ /^\s*$/) { | ||
| 238 | |||
| 239 | # removing leading white space | ||
| 240 | $patchState =~ s/^\s+//; | ||
| 241 | my @patches = split /\s+/, $patchState; | ||
| 242 | if($#patches == 0){ | ||
| 243 | # patch is not superseded | ||
| 244 | $patchSuperseded{$patches[0]} = 0; | ||
| 245 | } | ||
| 246 | else { | ||
| 247 | # patch is superseded | ||
| 248 | $patchSuperseded{$patches[0]} = 1; | ||
| 249 | } | ||
| 250 | } | ||
| 251 | } | ||
| 252 | } | ||
| 253 | else { | ||
| 254 | &B_log("DEBUG","No patches found on the system.\n"); | ||
| 255 | } | ||
| 256 | |||
| 257 | if($#fileList >= 0){ | ||
| 258 | # foreach line of swlist output | ||
| 259 | foreach my $fileEntry ( @fileList ){ | ||
| 260 | #filter out commented portions | ||
| 261 | if( $fileEntry !~ /^\s*\#/ ){ | ||
| 262 | chomp $fileEntry; | ||
| 263 | # split the output into three fields: product.fileset, filename, flag_isvolatile | ||
| 264 | my( $productInfo, $file, $is_volatile ) = $fileEntry =~ /^\s*(\S+): (\S+)\t(\S+)/ ; | ||
| 265 | # do not register volatile files | ||
| 266 | next if ($is_volatile =~ /true/); # skip to next file entry | ||
| 267 | $productInfo =~ s/\s+//; | ||
| 268 | $file =~ s/\s+//; | ||
| 269 | # if the product is a patch | ||
| 270 | if($productInfo =~ /PH(CO|KL|NE|SS)/){ | ||
| 271 | # if the patch is not superseded by another patch | ||
| 272 | if($patchSuperseded{$productInfo} == 0){ | ||
| 273 | # add the patch to the list of owner for this file | ||
| 274 | push @{$GLOBAL_SWLIST{"$file"}}, $productInfo; | ||
| 275 | } | ||
| 276 | } | ||
| 277 | # not a patch. | ||
| 278 | else { | ||
| 279 | # add the product to the list of owners for this file | ||
| 280 | push @{$GLOBAL_SWLIST{"$file"}}, $productInfo; | ||
| 281 | } | ||
| 282 | |||
| 283 | } | ||
| 284 | } | ||
| 285 | } | ||
| 286 | else{ | ||
| 287 | # defining GLOBAL_SWLIST in error state. | ||
| 288 | $GLOBAL_SWLIST{"ERROR"} = "ERROR"; | ||
| 289 | &B_log("ERROR","Could not execute swlist. Swmodifys will not be attempted"); | ||
| 290 | } | ||
| 291 | } | ||
| 292 | |||
| 293 | if(exists $GLOBAL_SWLIST{"$file"}){ | ||
| 294 | return $GLOBAL_SWLIST{"$file"}; | ||
| 295 | } | ||
| 296 | else { | ||
| 297 | return undef; | ||
| 298 | } | ||
| 299 | } | ||
| 300 | |||
| 301 | ################################################################### | ||
| 302 | # &B_check_system; | ||
| 303 | # This subroutine is called to validate that bastille may be | ||
| 304 | # safely run on the current system. It will check to insure | ||
| 305 | # that there is enough file system space, mounts are rw, nfs | ||
| 306 | # mounts are not mounted noroot, and swinstall, swremove and | ||
| 307 | # swmodify are not running | ||
| 308 | # | ||
| 309 | # uses ErrorLog | ||
| 310 | # | ||
| 311 | ################################################################## | ||
| 312 | sub B_check_system { | ||
| 313 | # exitFlag is one if a conflict with the successful execution | ||
| 314 | # of bastille is found. | ||
| 315 | my $exitFlag = 0; | ||
| 316 | |||
| 317 | my $ignoreCheck = &getGlobal("BDIR","config") . "/.no_system_check"; | ||
| 318 | if( -e $ignoreCheck ) { | ||
| 319 | return $exitFlag; | ||
| 320 | } | ||
| 321 | |||
| 322 | # first check for swinstall, swmodify, or swremove processes | ||
| 323 | my $ps = &getGlobal('BIN',"ps") . " -el"; | ||
| 324 | my @processTable = `$ps`; | ||
| 325 | foreach my $process (@processTable) { | ||
| 326 | if($process =~ /swinstall/ ) { | ||
| 327 | &B_log("ERROR","Bastille cannot run while a swinstall is in progress.\n" . | ||
| 328 | "Complete the swinstall operation and then run Bastille.\n\n"); | ||
| 329 | $exitFlag = 1; | ||
| 330 | } | ||
| 331 | |||
| 332 | if($process =~ /swremove/ ) { | ||
| 333 | &B_log("ERROR","Bastille cannot run while a swremove is in progress.\n" . | ||
| 334 | "Complete the swremove operation and then run Bastille.\n\n"); | ||
| 335 | $exitFlag = 1; | ||
| 336 | } | ||
| 337 | |||
| 338 | if($process =~ /swmodify/ ) { | ||
| 339 | &B_log("ERROR","Bastille cannot run while a swmodify is in progress.\n" . | ||
| 340 | "Complete the swmodify operation and then run Bastille.\n\n"); | ||
| 341 | $exitFlag = 1; | ||
| 342 | } | ||
| 343 | |||
| 344 | } | ||
| 345 | |||
| 346 | # check for root read only mounts for /var /etc /stand / | ||
| 347 | # Bastille is required to make changes to these file systems. | ||
| 348 | my $mount = &getGlobal('BIN',"mount"); | ||
| 349 | my $rm = &getGlobal('BIN',"rm"); | ||
| 350 | my $touch = &getGlobal('BIN',"touch"); | ||
| 351 | |||
| 352 | my @mnttab = `$mount`; | ||
| 353 | |||
| 354 | if(($? >> 8) != 0) { | ||
| 355 | &B_log("WARNING","Unable to use $mount to determine if needed partitions\n" . | ||
| 356 | "are root writable, based on disk mount options.\n" . | ||
| 357 | "Bastille will continue but note that disk\n" . | ||
| 358 | "mount checks were skipped.\n\n"); | ||
| 359 | } | ||
| 360 | else { | ||
| 361 | foreach my $record (@mnttab) { | ||
| 362 | my @fields = split /\s+/, $record; | ||
| 363 | if ((defined $fields[0]) && (defined $fields[2]) && (defined $fields[3])) { | ||
| 364 | my $mountPoint = $fields[0]; | ||
| 365 | my $mountType = $fields[2]; | ||
| 366 | my $mountOptions = $fields[3]; | ||
| 367 | |||
| 368 | # checks for /stand and /var/* removed | ||
| 369 | if($mountPoint =~ /^\/$|^\/etc|^\/var$/) { | ||
| 370 | |||
| 371 | if($mountOptions =~ /^ro,|,ro,|,ro$/) { | ||
| 372 | &B_log("ERROR","$mountPoint is mounted read-only. Bastille needs to make\n" . | ||
| 373 | "modifications to this file system. Please remount\n" . | ||
| 374 | "$mountPoint read-write and then run Bastille again.\n\n"); | ||
| 375 | $exitFlag = 1; | ||
| 376 | } | ||
| 377 | # looking for an nfs mounted file system | ||
| 378 | if($mountType =~/.+:\//){ | ||
| 379 | my $fileExisted=0; | ||
| 380 | if(-e "$mountPoint/.bastille") { | ||
| 381 | $fileExisted=1; | ||
| 382 | } | ||
| 383 | |||
| 384 | `$touch $mountPoint/.bastille 1>/dev/null 2>&1`; | ||
| 385 | |||
| 386 | if( (! -e "$mountPoint/.bastille") || (($? >> 8) != 0) ) { | ||
| 387 | &B_log("ERROR","$mountPoint is an nfs mounted file system that does\n" . | ||
| 388 | "not allow root to write to. Bastille needs to make\n" . | ||
| 389 | "modifications to this file system. Please remount\n" . | ||
| 390 | "$mountPoint giving root access and then run Bastille\n" . | ||
| 391 | "again.\n\n"); | ||
| 392 | |||
| 393 | $exitFlag = 1; | ||
| 394 | } | ||
| 395 | # if the file did not exist befor the touch then remove the generated file | ||
| 396 | if(! $fileExisted) { | ||
| 397 | `$rm -f $mountPoint/.bastille 1>/dev/null 2>&1`; | ||
| 398 | } | ||
| 399 | } | ||
| 400 | } | ||
| 401 | } | ||
| 402 | else { | ||
| 403 | &B_log("WARNING","Unable to use $mount to determine if needed partitions\n" . | ||
| 404 | "are root writable, based on disk mount options.\n" . | ||
| 405 | "Bastille will continue but note that disk\n" . | ||
| 406 | "mount checks were skipped.\n\n"); | ||
| 407 | } | ||
| 408 | } | ||
| 409 | |||
| 410 | } | ||
| 411 | |||
| 412 | # checks for enough disk space in directories that Bastille writes to. | ||
| 413 | my $bdf = &getGlobal('BIN',"bdf"); | ||
| 414 | #directories that Bastille writes to => required space in kilobytes. | ||
| 415 | my %bastilleDirs = ( "/etc/opt/sec_mgmt/bastille" => "4", "/var/opt/sec_mgmt/bastille"=> "1000"); | ||
| 416 | for my $directory (sort keys %bastilleDirs) { | ||
| 417 | my @diskUsage = `$bdf $directory`; | ||
| 418 | |||
| 419 | if(($? >> 8) != 0) { | ||
| 420 | &B_log("WARNING","Unable to use $bdf to determine disk usage for\n" . | ||
| 421 | "$directory\n" . | ||
| 422 | "Bastille will continue but note that disk\n" . | ||
| 423 | "usage checks were skipped.\n\n"); | ||
| 424 | |||
| 425 | } | ||
| 426 | else { | ||
| 427 | # removing bdf header line from usage information. | ||
| 428 | shift @diskUsage; | ||
| 429 | my $usageString= ""; | ||
| 430 | |||
| 431 | foreach my $usageRecord (@diskUsage) { | ||
| 432 | chomp $usageRecord; | ||
| 433 | $usageString .= $usageRecord; | ||
| 434 | } | ||
| 435 | |||
| 436 | $usageString =~ s/^\s+//; | ||
| 437 | |||
| 438 | my @fields = split /\s+/, $usageString; | ||
| 439 | if($#fields != 5) { | ||
| 440 | &B_log("WARNING","Unable to use $bdf to determine disk usage for\n" . | ||
| 441 | "$directory\n" . | ||
| 442 | "Bastille will continue but note that disk\n" . | ||
| 443 | "usage checks were skipped.\n\n"); | ||
| 444 | } | ||
| 445 | else { | ||
| 446 | |||
| 447 | my $mountPoint = $fields[5]; | ||
| 448 | my $diskAvail = $fields[3]; | ||
| 449 | |||
| 450 | if($diskAvail <= $bastilleDirs{"$directory"}) { | ||
| 451 | &B_log("ERROR","$mountPoint does not contain enough available space\n" . | ||
| 452 | "for Bastille to run properly. $directory needs\n" . | ||
| 453 | "at least $bastilleDirs{$directory} kilobytes of space.\n" . | ||
| 454 | "Please clear at least that amount of space from\n" . | ||
| 455 | "$mountPoint and run Bastille again.\n" . | ||
| 456 | "Current Free Space available = ${diskAvail} k\n\n"); | ||
| 457 | $exitFlag = 1; | ||
| 458 | } | ||
| 459 | } | ||
| 460 | } | ||
| 461 | } | ||
| 462 | |||
| 463 | # check to make sure that we are in at least run level 2 before we attempt to run | ||
| 464 | my $who = &getGlobal('BIN', "who") . " -r"; | ||
| 465 | my $levelInfo = `$who`; | ||
| 466 | if(($? >> 8) != 0 ) { | ||
| 467 | &B_log("WARNING","Unable to use \"$who\" to determine system run.\n" . | ||
| 468 | "level Bastille will continue but note that the run\n" . | ||
| 469 | "level check was skipped.\n\n"); | ||
| 470 | } | ||
| 471 | else { | ||
| 472 | chomp $levelInfo; | ||
| 473 | my @runlevel = split /\s+/, $levelInfo; | ||
| 474 | if ((! defined $runlevel[3]) or ($runlevel[3] < 2)) { | ||
| 475 | &B_log("WARNING","Bastille requires a run-level of 2 or more to run properly.\n" . | ||
| 476 | "Please move your system to a higher run level and then\n" . | ||
| 477 | "run 'bastille -b'.\n\n"); | ||
| 478 | if(defined $runlevel[3]) { | ||
| 479 | &B_log("ERROR","Current run-level is '$runlevel[3]'.\n\n"); | ||
| 480 | $exitFlag=1; | ||
| 481 | } | ||
| 482 | else { | ||
| 483 | &B_log("WARNING","Unable to use \"$who\" to determine system run.\n" . | ||
| 484 | "level Bastille will continue but note that the run\n" . | ||
| 485 | "level check was skipped.\n\n"); | ||
| 486 | } | ||
| 487 | } | ||
| 488 | else { | ||
| 489 | &B_log("DEBUG","System run-level is $runlevel[3]\n"); | ||
| 490 | } | ||
| 491 | } | ||
| 492 | |||
| 493 | if($exitFlag) { | ||
| 494 | exit(1); | ||
| 495 | } | ||
| 496 | |||
| 497 | } | ||
| 498 | |||
| 499 | ################################################################### | ||
| 500 | # &B_swmodify($file); | ||
| 501 | # This subroutine is called after a file is modified. It will | ||
| 502 | # redefine the file in the IPD with it's new properties. If | ||
| 503 | # the file is not in the IPD it does nothing. | ||
| 504 | # | ||
| 505 | # uses B_System to make the swmodifications. | ||
| 506 | ################################################################## | ||
| 507 | sub B_swmodify($){ | ||
| 508 | my $file = $_[0]; | ||
| 509 | if(defined &getGlobalSwlist($file)){ | ||
| 510 | my $swmodify = &getGlobal('BIN',"swmodify"); | ||
| 511 | my @productsInfo = @{&getGlobalSwlist($file)}; | ||
| 512 | # running swmodify on files that were altered by this function but | ||
| 513 | # were created and maintained by SD | ||
| 514 | foreach my $productInfo (@productsInfo) { | ||
| 515 | &B_System("$swmodify -x files='$file' $productInfo", | ||
| 516 | "$swmodify -x files='$file' $productInfo"); | ||
| 517 | } | ||
| 518 | } | ||
| 519 | } | ||
| 520 | |||
| 521 | #################################################################### | ||
| 522 | # &B_load_ipf_rules($ipfruleset); | ||
| 523 | # This function enables an ipfruleset. It's a little more | ||
| 524 | # specific than most API functions, but necessary because | ||
| 525 | # ipf doesn't return correct exit codes (syntax error results | ||
| 526 | # in a 0 exit code) | ||
| 527 | # | ||
| 528 | # uses ActionLog and ErrorLog to log | ||
| 529 | # calls crontab directly (to list and to read in new jobs) | ||
| 530 | ################################################################### | ||
| 531 | sub B_load_ipf_rules ($) { | ||
| 532 | my $ipfruleset=$_[0]; | ||
| 533 | |||
| 534 | &B_log("DEBUG","# sub B_load_ipf_rules"); | ||
| 535 | |||
| 536 | # TODO: grab ipf.conf dynamically from the rc.config.d files | ||
| 537 | my $ipfconf = &getGlobal('FILE','ipf.conf'); | ||
| 538 | |||
| 539 | # file system changes - these are straightforward, and the API | ||
| 540 | # will take care of the revert | ||
| 541 | &B_create_file($ipfconf); | ||
| 542 | &B_blank_file($ipfconf, 'a$b'); | ||
| 543 | &B_append_line($ipfconf, 'a$b', $ipfruleset); | ||
| 544 | |||
| 545 | # runtime changes | ||
| 546 | |||
| 547 | # define binaries | ||
| 548 | my $grep = &getGlobal('BIN', 'grep'); | ||
| 549 | my ($ipf, $ipfstat) = &getIPFLocation; | ||
| 550 | # create backup rules | ||
| 551 | # This will exit with a non-zero exit code because of the grep | ||
| 552 | my @oldrules = `$ipfstat -io 2>&1 | $grep -v empty`; | ||
| 553 | |||
| 554 | my @errors=`$ipf -I -Fa -f $ipfconf 2>&1`; | ||
| 555 | |||
| 556 | if(($? >> 8) == 0) { | ||
| 557 | |||
| 558 | &B_set_rc("IPF_START","1"); | ||
| 559 | &B_set_rc("IPF_CONF","$ipfconf"); | ||
| 560 | |||
| 561 | # swap the rules in | ||
| 562 | &B_System("$ipf -s","$ipf -s"); | ||
| 563 | |||
| 564 | # now create a "here" document with the previous version of | ||
| 565 | # the rules and put it into the revert-actions script | ||
| 566 | &B_revert_log("$ipf -I -Fa -f - <<EOF\n@{oldrules}EOF"); | ||
| 567 | |||
| 568 | if (@errors) { | ||
| 569 | &B_log("ERROR","ipfilter produced the following errors when\n" . | ||
| 570 | " loading $ipfconf. You probably had an invalid\n" . | ||
| 571 | " rule in ". &getGlobal('FILE','customipfrules') ."\n". | ||
| 572 | "@errors\n"); | ||
| 573 | } | ||
| 574 | |||
| 575 | } else { | ||
| 576 | &B_log("ERROR","Unable to run $ipf\n"); | ||
| 577 | } | ||
| 578 | |||
| 579 | } | ||
| 580 | |||
| 581 | |||
| 582 | |||
| 583 | #################################################################### | ||
| 584 | # &B_Schedule($pattern,$cronjob); | ||
| 585 | # This function schedules a cronjob. If $pattern exists in the | ||
| 586 | # crontab file, that job will be replaced. Otherwise, the job | ||
| 587 | # will be appended. | ||
| 588 | # | ||
| 589 | # uses ActionLog and ErrorLog to log | ||
| 590 | # calls crontab directly (to list and to read in new jobs) | ||
| 591 | ################################################################### | ||
| 592 | sub B_Schedule ($$) { | ||
| 593 | my ($pattern,$cronjob)=@_; | ||
| 594 | $cronjob .= "\n"; | ||
| 595 | |||
| 596 | &B_log("DEBUG","# sub B_Schedule"); | ||
| 597 | my $crontab = &getGlobal('BIN','crontab'); | ||
| 598 | |||
| 599 | my @oldjobs = `$crontab -l 2>/dev/null`; | ||
| 600 | my @newjobs; | ||
| 601 | my $patternfound=0; | ||
| 602 | |||
| 603 | foreach my $oldjob (@oldjobs) { | ||
| 604 | if (($oldjob =~ m/$pattern/ ) and (not($patternfound))) { | ||
| 605 | push @newjobs, $cronjob; | ||
| 606 | $patternfound=1; | ||
| 607 | &B_log("ACTION","changing existing cron job which matches $pattern with\n" . | ||
| 608 | "$cronjob"); | ||
| 609 | } elsif ($oldjob !~ m/$pattern/ ) { | ||
| 610 | &B_log("ACTION","keeping existing cron job $oldjob"); | ||
| 611 | push @newjobs, $oldjob; | ||
| 612 | } #implied: else if pattern matches, but we've | ||
| 613 | #already replaced one, then toss the others. | ||
| 614 | } | ||
| 615 | |||
| 616 | unless ($patternfound) { | ||
| 617 | &B_log("ACTION","adding cron job\n$cronjob\n"); | ||
| 618 | push @newjobs, $cronjob; | ||
| 619 | } | ||
| 620 | |||
| 621 | if(open(CRONTAB, "|$crontab - 2> /dev/null")) { | ||
| 622 | print CRONTAB @newjobs; | ||
| 623 | |||
| 624 | # now create a "here" document with the previous version of | ||
| 625 | # the crontab file and put it into the revert-actions script | ||
| 626 | &B_revert_log("$crontab <<EOF\n" . "@oldjobs" . "EOF"); | ||
| 627 | close CRONTAB; | ||
| 628 | } | ||
| 629 | |||
| 630 | # Now check to make sure it happened, since cron will exit happily | ||
| 631 | # (retval 0) with no changes if there are any syntax errors | ||
| 632 | my @editedjobs = `$crontab -l 2>/dev/null`; | ||
| 633 | |||
| 634 | if (@editedjobs ne @newjobs) { | ||
| 635 | &B_log("ERROR","failed to add cron job:\n$cronjob\n" . | ||
| 636 | " You probably had an invalid crontab file to start with."); | ||
| 637 | } | ||
| 638 | |||
| 639 | } | ||
| 640 | |||
| 641 | |||
| 642 | #This function turns off a service, given a service name defined in HP-UX.service | ||
| 643 | |||
| 644 | sub B_ch_rc($) { | ||
| 645 | |||
| 646 | my ($service_name)=@_; | ||
| 647 | |||
| 648 | if (&GetDistro != "^HP-UX") { | ||
| 649 | &B_log("ERROR","Tried to call ch_rc $service_name on a non-HP-UX\n". | ||
| 650 | " system! Internal Bastille error."); | ||
| 651 | return undef; | ||
| 652 | } | ||
| 653 | my $configfile=""; | ||
| 654 | my $command = &getGlobal('BIN', 'ch_rc'); | ||
| 655 | |||
| 656 | my $startup_script=&getGlobal('DIR','initd') . "/". $service_name; | ||
| 657 | my @rc_parameters= @{ &getGlobal('SERVICE',$service_name) }; | ||
| 658 | my @rcFiles=@{ &getGlobal('RCCONFIG',$service_name) }; | ||
| 659 | my $rcFile=''; | ||
| 660 | if (@rcFiles == 1){ | ||
| 661 | $rcFile=$rcFiles[0]; | ||
| 662 | } else { | ||
| 663 | &B_log("FATAL","Multiple RC Files not yet supported... internal error."); | ||
| 664 | } | ||
| 665 | |||
| 666 | # if the service-related process is not run, and the control variable is stilll 1 | ||
| 667 | # there is a inconsistency. in this case we only need to change the control variable | ||
| 668 | my @psnames=@{ &getGlobal('PROCESS',$service_name)}; | ||
| 669 | my @processes; | ||
| 670 | foreach my $psname (@psnames) { | ||
| 671 | $psname .= '\b'; # avoid embedded match; anchor search pattern to trailing word boundry | ||
| 672 | my @procList = &isProcessRunning($psname); | ||
| 673 | if(@procList >= 0){ | ||
| 674 | splice @processes,$#processes+1,0,@procList; | ||
| 675 | } | ||
| 676 | } | ||
| 677 | #Actually set the rc variable | ||
| 678 | foreach my $rcVariable (@rc_parameters){ | ||
| 679 | my $orig_value = &B_get_rc($rcVariable); | ||
| 680 | if ($orig_value eq "" ) { #If variable not set, used the defined file | ||
| 681 | $configfile=&getGlobal("DIR","rc.config.d") . "/" . $rcFile; | ||
| 682 | if (not( -f $configfile )) { | ||
| 683 | &B_create_file($configfile); | ||
| 684 | } | ||
| 685 | } | ||
| 686 | &B_log("DEBUG","In B_ch_rc (no procs), setting $rcVariable to 0 in $configfile" . | ||
| 687 | ", with an original value of $orig_value with rcfile: $rcFile"); | ||
| 688 | if ( ! @processes) { # IF there are no processes we don't neet to perform a "stop" | ||
| 689 | &B_set_rc($rcVariable, "0", $configfile); | ||
| 690 | } else { | ||
| 691 | if ( $orig_value !~ "1" ) { #If param is not already 1, the "stop" script won't work | ||
| 692 | &B_set_rc($rcVariable, "1",$configfile); | ||
| 693 | } | ||
| 694 | &B_System ($startup_script . " stop", #stop service, then restart if the user runs bastille -r | ||
| 695 | $startup_script . " start"); | ||
| 696 | # set parameter, so that service will stay off after reboots | ||
| 697 | &B_set_rc($rcVariable, "0", $configfile); | ||
| 698 | } | ||
| 699 | } | ||
| 700 | } | ||
| 701 | |||
| 702 | |||
| 703 | # This routine sets a value in a given file | ||
| 704 | sub B_set_value($$$) { | ||
| 705 | my ($param, $value, $file)=@_; | ||
| 706 | |||
| 707 | &B_log("DEBUG","B_set_value: $param, $value, $file"); | ||
| 708 | if (! -e $file ) { | ||
| 709 | &B_create_file("$file"); | ||
| 710 | } | ||
| 711 | |||
| 712 | # If a value is already set to something other than $value then reset it. | ||
| 713 | #Note that though this tests for "$value ="the whole line gets replaced, so | ||
| 714 | #any pre-existing values are also replaced. | ||
| 715 | &B_replace_line($file,"^$param\\s*=\\s*","$param=$value\n"); | ||
| 716 | # If the value is not already set to something then set it. | ||
| 717 | &B_append_line($file,"^$param\\s*=\\s*$value","$param=$value\n"); | ||
| 718 | |||
| 719 | } | ||
| 720 | |||
| 721 | |||
| 722 | ################################################################################## | ||
| 723 | # &B_chperm($owner,$group,$mode,$filename(s)) | ||
| 724 | # This function changes ownership and mode of a list of files. Takes four | ||
| 725 | # arguments first the owner next the group and third the new mode in oct and | ||
| 726 | # last a list of files that the permissions changes should take affect on. | ||
| 727 | # | ||
| 728 | # uses: &swmodify and &B_revert_log | ||
| 729 | ################################################################################## | ||
| 730 | sub B_chperm($$$$) { | ||
| 731 | my ($newown, $newgrp, $newmode, $file_expr) = @_; | ||
| 732 | my @files = glob($file_expr); | ||
| 733 | |||
| 734 | my $return = 1; | ||
| 735 | |||
| 736 | foreach my $file (@files){ | ||
| 737 | my @filestat = stat $file; | ||
| 738 | my $oldmode = (($filestat[2]/512) % 8) . | ||
| 739 | (($filestat[2]/64) % 8) . | ||
| 740 | (($filestat[2]/8) % 8) . | ||
| 741 | (($filestat[2]) % 8); | ||
| 742 | |||
| 743 | if((chown $newown, $newgrp, $file) != 1 ){ | ||
| 744 | &B_log("ERROR","Could not change ownership of $file to $newown:$newgrp\n"); | ||
| 745 | $return = 0; | ||
| 746 | } | ||
| 747 | else{ | ||
| 748 | &B_log("ACTION","Changed ownership of $file to $newown:$newgrp\n"); | ||
| 749 | # swmodifying file if possible... | ||
| 750 | &B_swmodify($file); | ||
| 751 | &B_revert_log(&getGlobal('BIN',"chown") . " $filestat[4]:$filestat[5] $file\n"); | ||
| 752 | } | ||
| 753 | |||
| 754 | my $newmode_formatted=sprintf "%5lo",$newmode; | ||
| 755 | |||
| 756 | if((chmod $newmode, $file) != 1){ | ||
| 757 | &B_log("ERROR","Could not change mode of $file to $newmode_formatted\n"); | ||
| 758 | $return = 0; | ||
| 759 | } | ||
| 760 | else{ | ||
| 761 | &B_log("ACTION","Changed mode of $file to $newmode_formatted\n"); | ||
| 762 | &B_revert_log(&getGlobal('BIN',"chmod") . " $oldmode $file\n"); | ||
| 763 | } | ||
| 764 | |||
| 765 | |||
| 766 | } | ||
| 767 | return $return; | ||
| 768 | } | ||
| 769 | |||
| 770 | ############################################################################ | ||
| 771 | # &B_install_jail($jailname, $jailconfigfile); | ||
| 772 | # This function takes two arguments ( jail_name, jail_config ) | ||
| 773 | # It's purpose is to take read in config files that define a | ||
| 774 | # chroot jail and then generate it bases on that specification | ||
| 775 | ############################################################################ | ||
| 776 | sub B_install_jail($$) { | ||
| 777 | |||
| 778 | my $jailName = $_[0]; # Name of the jail e.g bind | ||
| 779 | my $jailConfig = $_[1]; # Name of the jails configuration file | ||
| 780 | # create the root directory of the jail if it does not exist | ||
| 781 | &B_create_dir( &getGlobal('BDIR','jail')); | ||
| 782 | &B_chperm(0,0,0555,&getGlobal('BDIR','jail')); | ||
| 783 | |||
| 784 | # create the Jail dir if it does not exist | ||
| 785 | &B_create_dir( &getGlobal('BDIR','jail') . "/" . $jailName); | ||
| 786 | &B_chperm(0,0,0555,&getGlobal('BDIR','jail') . "/". $jailName); | ||
| 787 | |||
| 788 | |||
| 789 | my $jailPath = &getGlobal('BDIR','jail') . "/" . $jailName; | ||
| 790 | my @lines; # used to store no commented no empty config file lines | ||
| 791 | # open configuration file for desired jail and parse in commands | ||
| 792 | if(open(JAILCONFIG,"< $jailConfig")) { | ||
| 793 | while(my $line=<JAILCONFIG>){ | ||
| 794 | if($line !~ /^\s*\#|^\s*$/){ | ||
| 795 | chomp $line; | ||
| 796 | push(@lines,$line); | ||
| 797 | } | ||
| 798 | } | ||
| 799 | close JAILCONFIG; | ||
| 800 | } | ||
| 801 | else{ | ||
| 802 | &B_log("ERROR","Open Failed on filename: $jailConfig\n"); | ||
| 803 | return 0; | ||
| 804 | } | ||
| 805 | # read through commands and execute | ||
| 806 | foreach my $line (@lines){ | ||
| 807 | &B_log("ACTION","Install jail: $line\n"); | ||
| 808 | my @confCmd = split /\s+/,$line; | ||
| 809 | if($confCmd[0] =~ /dir/){ # if the command say to add a directory | ||
| 810 | if($#confCmd == 4) { # checking dir Cmd form | ||
| 811 | if(! (-d $jailPath . "/" . $confCmd[1])){ | ||
| 812 | #add a directory and change its permissions according | ||
| 813 | #to the conf file | ||
| 814 | &B_create_dir( $jailPath . "/" . $confCmd[1]); | ||
| 815 | &B_chperm((getpwnam($confCmd[3]))[2], | ||
| 816 | (getgrnam($confCmd[4]))[2], | ||
| 817 | oct($confCmd[2]), | ||
| 818 | $jailPath . "/" . $confCmd[1]); | ||
| 819 | } | ||
| 820 | } | ||
| 821 | else { | ||
| 822 | &B_log("ERROR","Badly Formed Configuration Line:\n$line\n\n"); | ||
| 823 | } | ||
| 824 | } | ||
| 825 | elsif($confCmd[0] =~ /file/) { | ||
| 826 | if($#confCmd == 5) { # checking file cmd form | ||
| 827 | if(&B_cp($confCmd[1],$jailPath . "/" . $confCmd[2])){ | ||
| 828 | # for copy command cp file and change perms | ||
| 829 | &B_chperm($confCmd[4],$confCmd[5],oct($confCmd[3]),$jailPath . "/" . $confCmd[2]); | ||
| 830 | } | ||
| 831 | else { | ||
| 832 | &B_log("ERROR","Could not complete copy on specified files:\n" . | ||
| 833 | "$line\n"); | ||
| 834 | } | ||
| 835 | } | ||
| 836 | else { | ||
| 837 | &B_log("ERROR","Badly Formed Configuration Line:\n" . | ||
| 838 | "$line\n\n"); | ||
| 839 | } | ||
| 840 | } | ||
| 841 | elsif($confCmd[0] =~ /slink/) { | ||
| 842 | if($#confCmd == 2) { # checking file cmd form | ||
| 843 | if(!(-e $jailPath . "/" . $confCmd[2])){ | ||
| 844 | #for symlink command create the symlink | ||
| 845 | &B_symlink($jailPath . "/" . $confCmd[1], $confCmd[2]); | ||
| 846 | } | ||
| 847 | } | ||
| 848 | else { | ||
| 849 | &B_log("ERROR","Badly Formed Configuration Line:\n" . | ||
| 850 | "$line\n\n"); | ||
| 851 | } | ||
| 852 | } | ||
| 853 | else { | ||
| 854 | &B_log("ERROR","Unrecognized Configuration Line:\n" . | ||
| 855 | "$line\n\n"); | ||
| 856 | } | ||
| 857 | } | ||
| 858 | return 1; | ||
| 859 | } | ||
| 860 | |||
| 861 | |||
| 862 | |||
| 863 | ########################################################################### | ||
| 864 | # &B_list_processes($service) # | ||
| 865 | # # | ||
| 866 | # This subroutine uses the GLOBAL_PROCESS hash to determine if a # | ||
| 867 | # service's corresponding processes are running on the system. # | ||
| 868 | # If any of the processes are found to be running then the process # | ||
| 869 | # name(s) is/are returned by this subroutine in the form of an list # | ||
| 870 | # If none of the processes that correspond to the service are running # | ||
| 871 | # then an empty list is returned. # | ||
| 872 | ########################################################################### | ||
| 873 | sub B_list_processes($) { | ||
| 874 | |||
| 875 | # service name | ||
| 876 | my $service = $_[0]; | ||
| 877 | # list of processes related to the service | ||
| 878 | my @processes=@{ &getGlobal('PROCESS',$service)}; | ||
| 879 | |||
| 880 | # current systems process information | ||
| 881 | my $ps = &getGlobal('BIN',"ps"); | ||
| 882 | my $psTable = `$ps -elf`; | ||
| 883 | |||
| 884 | # the list to be returned from the function | ||
| 885 | my @running_processes; | ||
| 886 | |||
| 887 | # for every process associated with the service | ||
| 888 | foreach my $process (@processes) { | ||
| 889 | # if the process is in the process table then | ||
| 890 | if($psTable =~ m/$process/) { | ||
| 891 | # add the process to the list, which will be returned | ||
| 892 | push @running_processes, $process; | ||
| 893 | } | ||
| 894 | |||
| 895 | } | ||
| 896 | |||
| 897 | # return the list of running processes | ||
| 898 | return @running_processes; | ||
| 899 | |||
| 900 | } | ||
| 901 | |||
| 902 | ############################################################################# | ||
| 903 | # &B_list_full_processes($service) # | ||
| 904 | # # | ||
| 905 | # This subroutine simply grep through the process table for those matching # | ||
| 906 | # the input argument TODO: Allow B_list process to levereage this code # | ||
| 907 | # ... Not done this cycle to avoid release risk (late in cycle) # | ||
| 908 | ############################################################################# | ||
| 909 | sub B_list_full_processes($) { | ||
| 910 | |||
| 911 | # service name | ||
| 912 | my $procName = $_[0]; | ||
| 913 | my $ps = &getGlobal('BIN',"ps"); | ||
| 914 | my @psTable = split(/\n/,`$ps -elf`); | ||
| 915 | |||
| 916 | # for every process associated with the service | ||
| 917 | my @runningProcessLines = grep(/$procName/ , @psTable); | ||
| 918 | # return the list of running processes | ||
| 919 | return @runningProcessLines; | ||
| 920 | } | ||
| 921 | |||
| 922 | ################################################################################ | ||
| 923 | # &B_deactivate_inetd_service($service); # | ||
| 924 | # # | ||
| 925 | # This subroutine will disable all inetd services associated with the input # | ||
| 926 | # service name. Service name must be a reference to the following hashes # | ||
| 927 | # GLOBAL_SERVICE GLOBAL_SERVTYPE and GLOBAL_PROCESSES. If processes are left # | ||
| 928 | # running it will note these services in the TODO list as well as instruct the# | ||
| 929 | # user in how they remaining processes can be disabled. # | ||
| 930 | ################################################################################ | ||
| 931 | sub B_deactivate_inetd_service($) { | ||
| 932 | my $service = $_[0]; | ||
| 933 | my $servtype = &getGlobal('SERVTYPE',"$service"); | ||
| 934 | my $inetd_conf = &getGlobal('FILE',"inetd.conf"); | ||
| 935 | |||
| 936 | # check the service type to ensure that it can be configured by this subroutine. | ||
| 937 | if($servtype ne 'inet') { | ||
| 938 | &B_log("ACTION","The service \"$service\" is not an inet service so it cannot be\n" . | ||
| 939 | "configured by this subroutine\n"); | ||
| 940 | return 0; | ||
| 941 | } | ||
| 942 | |||
| 943 | # check for the inetd configuration files existence so it may be configured by | ||
| 944 | # this subroutine. | ||
| 945 | if(! -e $inetd_conf ) { | ||
| 946 | &B_log("ACTION","The file \"$inetd_conf\" cannot be located.\n" . | ||
| 947 | "Unable to configure inetd\n"); | ||
| 948 | return 0; | ||
| 949 | } | ||
| 950 | |||
| 951 | # list of service identifiers present in inetd.conf file. | ||
| 952 | my @inetd_entries = @{ &getGlobal('SERVICE',"$service") }; | ||
| 953 | |||
| 954 | foreach my $inetd_entry (@inetd_entries) { | ||
| 955 | &B_hash_comment_line($inetd_conf, "^\\s*$inetd_entry"); | ||
| 956 | } | ||
| 957 | |||
| 958 | # list of processes associated with this service which are still running | ||
| 959 | # on the system | ||
| 960 | my @running_processes = &B_list_processes($service); | ||
| 961 | |||
| 962 | if($#running_processes >= 0) { | ||
| 963 | my $todoString = "\n" . | ||
| 964 | "---------------------------------------\n" . | ||
| 965 | "Deactivating Inetd Service: $service\n" . | ||
| 966 | "---------------------------------------\n" . | ||
| 967 | "The following process(es) are associated with the inetd service \"$service\".\n" . | ||
| 968 | "They are most likely associated with a session which was initiated prior to\n" . | ||
| 969 | "running Bastille. To disable a process see \"kill(1)\" man pages or reboot\n" . | ||
| 970 | "the system\n" . | ||
| 971 | "Active Processes:\n" . | ||
| 972 | "###################################\n"; | ||
| 973 | foreach my $running_process (@running_processes) { | ||
| 974 | $todoString .= "\t$running_process\n"; | ||
| 975 | } | ||
| 976 | $todoString .= "###################################\n"; | ||
| 977 | |||
| 978 | &B_TODO($todoString); | ||
| 979 | } | ||
| 980 | |||
| 981 | } | ||
| 982 | |||
| 983 | |||
| 984 | ################################################################################ | ||
| 985 | # B_get_rc($key); # | ||
| 986 | # # | ||
| 987 | # This subroutine will use the ch_rc binary to get rc.config.d variables # | ||
| 988 | # values properly escaped and quoted. # | ||
| 989 | ################################################################################ | ||
| 990 | sub B_get_rc($) { | ||
| 991 | |||
| 992 | my $key=$_[0]; | ||
| 993 | my $ch_rc = &getGlobal('BIN',"ch_rc"); | ||
| 994 | |||
| 995 | # get the current value of the given parameter. | ||
| 996 | my $currentValue=`$ch_rc -l -p $key`; | ||
| 997 | chomp $currentValue; | ||
| 998 | |||
| 999 | if(($? >> 8) == 0 ) { | ||
| 1000 | # escape all meta characters. | ||
| 1001 | # $currentValue =~ s/([\"\`\$\\])/\\$1/g; | ||
| 1002 | # $currentValue = '"' . $currentValue . '"'; | ||
| 1003 | } | ||
| 1004 | else { | ||
| 1005 | return undef; | ||
| 1006 | } | ||
| 1007 | |||
| 1008 | return $currentValue; | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | |||
| 1012 | |||
| 1013 | ################################################################################ | ||
| 1014 | # B_set_rc($key,$value); # | ||
| 1015 | # # | ||
| 1016 | # This subroutine will use the ch_rc binary to set rc.config.d variables. As # | ||
| 1017 | # well as setting the variable this subroutine will set revert strings. # | ||
| 1018 | # # | ||
| 1019 | ################################################################################ | ||
| 1020 | sub B_set_rc($$;$) { | ||
| 1021 | |||
| 1022 | my ($key,$value,$configfile)=@_; | ||
| 1023 | my $ch_rc = &getGlobal('BIN',"ch_rc"); | ||
| 1024 | |||
| 1025 | # get the current value of the given parameter. | ||
| 1026 | my $currentValue=&B_get_rc($key); | ||
| 1027 | if(defined $currentValue ) { | ||
| 1028 | if ($currentValue =~ /^\"(.*)\"$/ ) { | ||
| 1029 | $currentValue = '"\"' . $1 . '\""'; | ||
| 1030 | } | ||
| 1031 | if ($value =~ /^\"(.*)\"$/ ) { | ||
| 1032 | $value = '"\"' . $1 . '\""'; | ||
| 1033 | } | ||
| 1034 | if ( &B_System("$ch_rc -a -p $key=$value $configfile", | ||
| 1035 | "$ch_rc -a -p $key=$currentValue $configfile") ) { | ||
| 1036 | #ch_rc success | ||
| 1037 | return 1; | ||
| 1038 | } | ||
| 1039 | else { | ||
| 1040 | #ch_rc failure. | ||
| 1041 | return 0; | ||
| 1042 | } | ||
| 1043 | } | ||
| 1044 | else { | ||
| 1045 | &B_log("ERROR","ch_rc was unable to lookup $key\n"); | ||
| 1046 | return 0; | ||
| 1047 | } | ||
| 1048 | |||
| 1049 | } | ||
| 1050 | |||
| 1051 | |||
| 1052 | ################################################################################ | ||
| 1053 | # &ChrootHPApache($chrootScript,$httpd_conf,$httpd_bin, | ||
| 1054 | # $apachectl,$apacheJailDir,$serverString); | ||
| 1055 | # | ||
| 1056 | # This subroutine given an chroot script, supplied by the vendor, a | ||
| 1057 | # httpd.conf file, the binary location of httpd, the control script, | ||
| 1058 | # the jail directory, and the servers identification string, descriptive | ||
| 1059 | # string for TODO etc. It makes modifications to httpd.conf so that when | ||
| 1060 | # Apache starts it will chroot itself into the jail that the above | ||
| 1061 | # mentions script creates. | ||
| 1062 | # | ||
| 1063 | # uses B_replace_line B_create_dir B_System B_TODO | ||
| 1064 | # | ||
| 1065 | ############################################################################### | ||
| 1066 | sub B_chrootHPapache($$$$$$) { | ||
| 1067 | |||
| 1068 | my ($chrootScript,$httpd_conf,$httpd_bin,$apachectl,$apacheJailDir,$serverString)= @_; | ||
| 1069 | |||
| 1070 | my $exportpath = "export PATH=/usr/bin;"; | ||
| 1071 | my $ps = &getGlobal('BIN',"ps"); | ||
| 1072 | my $isRunning = 0; | ||
| 1073 | my $todo_header = 0; | ||
| 1074 | |||
| 1075 | # checking for a 2.0 version of the apache chroot script. | ||
| 1076 | if(-e $chrootScript ) { | ||
| 1077 | |||
| 1078 | if(open HTTPD, $httpd_conf) { | ||
| 1079 | while (my $line = <HTTPD>){ | ||
| 1080 | if($line =~ /^\s*Chroot/) { | ||
| 1081 | &B_log("DEBUG","Apache is already running in a chroot as specified by the following line:\n$line\n" . | ||
| 1082 | "which appears in the httpd.conf file. No Apache Chroot action was taken.\n"); | ||
| 1083 | return; | ||
| 1084 | } | ||
| 1085 | } | ||
| 1086 | close(HTTPD); | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | if(`$ps -ef` =~ $httpd_bin ) { | ||
| 1090 | $isRunning=1; | ||
| 1091 | &B_System("$exportpath " . $apachectl . " stop","$exportpath " . $apachectl . " start"); | ||
| 1092 | } | ||
| 1093 | &B_replace_line($httpd_conf, '^\s*#\s*Chroot' , | ||
| 1094 | "Chroot " . $apacheJailDir); | ||
| 1095 | if(-d &getGlobal('BDIR',"jail")){ | ||
| 1096 | &B_log("DEBUG","Jail directory already exists. No action taken.\n"); | ||
| 1097 | } | ||
| 1098 | else{ | ||
| 1099 | &B_log("ACTION","Jail directory was created.\n"); | ||
| 1100 | &B_create_dir( &getGlobal('BDIR','jail')); | ||
| 1101 | } | ||
| 1102 | |||
| 1103 | if(-d $apacheJailDir){ | ||
| 1104 | &B_log("DEBUG","$serverString jail already exists. No action taken.\n"); | ||
| 1105 | } | ||
| 1106 | else{ | ||
| 1107 | &B_System(&getGlobal('BIN',"umask") . " 022; $exportpath " . $chrootScript, | ||
| 1108 | &getGlobal('BIN',"echo") . " \"Your $serverString is now running outside of it's\\n" . | ||
| 1109 | "chroot jail. You must manually migrate your web applications\\n" . | ||
| 1110 | "back to your Apache server's httpd.conf defined location(s).\\n". | ||
| 1111 | "After you have completed this, feel free to remove the jail directories\\n" . | ||
| 1112 | "from your machine. Your apache jail directory is located in\\n" . | ||
| 1113 | &getGlobal('BDIR',"jail") . "\\n\" >> " . &getGlobal('BFILE',"TOREVERT")); | ||
| 1114 | |||
| 1115 | } | ||
| 1116 | if($isRunning){ | ||
| 1117 | &B_System("$exportpath " . $apachectl . " start","$exportpath " . $apachectl . " stop"); | ||
| 1118 | &B_log("ACTION","$serverString is now running in an chroot jail.\n"); | ||
| 1119 | } | ||
| 1120 | |||
| 1121 | &B_log("ACTION","The jail is located in " . $apacheJailDir . "\n"); | ||
| 1122 | |||
| 1123 | if ($todo_header !=1){ | ||
| 1124 | &B_TODO("\n---------------------------------\nApache Chroot:\n" . | ||
| 1125 | "---------------------------------\n"); | ||
| 1126 | } | ||
| 1127 | &B_TODO("$serverString Chroot Jail:\n" . | ||
| 1128 | "httpd.conf contains the Apache dependencies. You should\n" . | ||
| 1129 | "review this file to ensure that the dependencies made it\n" . | ||
| 1130 | "into the jail. Otherwise, you run a risk of your Apache server\n" . | ||
| 1131 | "not having access to all its modules and functionality.\n"); | ||
| 1132 | |||
| 1133 | |||
| 1134 | } | ||
| 1135 | |||
| 1136 | } | ||
| 1137 | |||
| 1138 | |||
| 1139 | sub isSystemTrusted { | ||
| 1140 | my $getprdef = &getGlobal('BIN',"getprdef"); | ||
| 1141 | my $definition = &B_Backtick("$getprdef -t 2>&1"); | ||
| 1142 | if($definition =~ "System is not trusted.") { | ||
| 1143 | return 0; | ||
| 1144 | } else { | ||
| 1145 | return 1; | ||
| 1146 | } | ||
| 1147 | } | ||
| 1148 | |||
| 1149 | |||
| 1150 | sub isTrustedMigrationAvailable { | ||
| 1151 | my $distroVersion=''; | ||
| 1152 | |||
| 1153 | if (&GetDistro =~ '^HP-UX11.(\d*)') { | ||
| 1154 | $distroVersion=$1; | ||
| 1155 | if ($distroVersion < 23) { # Not available before 11.23 | ||
| 1156 | return 0; #FALSE | ||
| 1157 | } elsif ($distroVersion >= 31) { #Bundled with 11.31 and after | ||
| 1158 | &B_log('DEBUG','isTrustedMigrationAvailable: HP-UX 11.31 always has trusted mode extensions'); | ||
| 1159 | return 1; | ||
| 1160 | } elsif ($distroVersion == 23) { # Optional on 11.23 if filesets installed | ||
| 1161 | if ( -x &getGlobal('BIN',"userdbget") ) { | ||
| 1162 | &B_log('DEBUG','isTrustedMigrationAvailable: Trusted Extensions Installed'); | ||
| 1163 | return 1; | ||
| 1164 | } else { | ||
| 1165 | &B_log('DEBUG','isTrustedMigrationAvailable: Trusted Extensions Not Installed'); | ||
| 1166 | return 0; #FALSE | ||
| 1167 | } | ||
| 1168 | } else { | ||
| 1169 | &B_log('DEBUG','isTrustedMigrationAvailable: ' . &GetDistro . | ||
| 1170 | ' not currently supported for trusted extentions.'); | ||
| 1171 | return 0; #FALSE | ||
| 1172 | } | ||
| 1173 | } else { | ||
| 1174 | &B_log('WARNING','isTrustedMigrationAvailable: HP-UX routine called on Linux system'); | ||
| 1175 | return 0; #FALSE | ||
| 1176 | } | ||
| 1177 | } | ||
| 1178 | |||
| 1179 | |||
| 1180 | |||
| 1181 | ########################################################################### | ||
| 1182 | # &checkServiceOnHPUX($service); | ||
| 1183 | # | ||
| 1184 | # Checks if the given service is running on an HP/UX system. This is | ||
| 1185 | # called by B_is_Service_Off(), which is the function that Bastille | ||
| 1186 | # modules should call. | ||
| 1187 | # | ||
| 1188 | # Return values: | ||
| 1189 | # NOTSECURE_CAN_CHANGE() if the service is on | ||
| 1190 | # SECURE_CANT_CHANGE() if the service is off | ||
| 1191 | # INCONSISTENT() if the state of the service cannot be determined | ||
| 1192 | # NOT_INSTALLED() if the s/w isn't insalled | ||
| 1193 | # | ||
| 1194 | ########################################################################### | ||
| 1195 | sub checkServiceOnHPUX($) { | ||
| 1196 | my $service=$_[0]; | ||
| 1197 | |||
| 1198 | # get the list of parameters which could be used to initiate the service | ||
| 1199 | # (could be in /etc/rc.config.d, /etc/inetd.conf, or /etc/inittab, so we | ||
| 1200 | # check all of them) | ||
| 1201 | my @params= @{ &getGlobal('SERVICE',$service) }; | ||
| 1202 | my $grep =&getGlobal('BIN', 'grep'); | ||
| 1203 | my $inetd=&getGlobal('FILE', 'inetd.conf'); | ||
| 1204 | my $inittab=&getGlobal('FILE', 'inittab'); | ||
| 1205 | my $retVals; | ||
| 1206 | my $startup=&getGlobal('DIR','initd') ; | ||
| 1207 | my @inet_bins= @{ &getGlobal('PROCESS',$service) }; | ||
| 1208 | |||
| 1209 | my $entry_found = 0; | ||
| 1210 | |||
| 1211 | &B_log("DEBUG","CheckHPUXservice: $service"); | ||
| 1212 | my $full_initd_path = $startup . "/" . $service; | ||
| 1213 | if ($GLOBAL_SERVTYPE{$service} eq "rc") { # look for the init script in /sbin/init.d | ||
| 1214 | if (not(-e $full_initd_path )) { | ||
| 1215 | return NOT_INSTALLED(); | ||
| 1216 | } | ||
| 1217 | } else { #inet-based service, so look for inetd.conf entries. | ||
| 1218 | &B_log("DEBUG","Checking inet service $service"); | ||
| 1219 | my @inet_entries= @{ &getGlobal('SERVICE',$service) }; | ||
| 1220 | foreach my $service (@inet_entries) { | ||
| 1221 | &B_log('DEBUG',"Checking for inetd.conf entry of $service in checkService on HPUX"); | ||
| 1222 | my $service_regex = '^[#\s]*' . $service . '\s+'; | ||
| 1223 | if ( &B_match_line($inetd, $service_regex) ) { # inet entry search | ||
| 1224 | &B_log('DEBUG',"$service present, entry exists"); | ||
| 1225 | $entry_found = 1 ; | ||
| 1226 | } | ||
| 1227 | } | ||
| 1228 | if ($entry_found == 0 ) { | ||
| 1229 | return NOT_INSTALLED(); | ||
| 1230 | } | ||
| 1231 | } | ||
| 1232 | |||
| 1233 | foreach my $param (@params) { | ||
| 1234 | &B_log("DEBUG","Checking to see if service $service is off.\n"); | ||
| 1235 | if (&getGlobal('SERVTYPE', $service) =~ /rc/) { | ||
| 1236 | my $ch_rc=&getGlobal('BIN', 'ch_rc'); | ||
| 1237 | my $on=&B_Backtick("$ch_rc -l -p $param"); | ||
| 1238 | |||
| 1239 | $on =~ s/\s*\#.*$//; # remove end-of-line comments | ||
| 1240 | $on =~ s/^\s*\"(.+)\"\s*$/$1/; # remove surrounding double quotes | ||
| 1241 | $on =~ s/^\s*\'(.+)\'\s*$/$1/; # remove surrounding single quotes | ||
| 1242 | $on =~ s/^\s*\"(.+)\"\s*$/$1/; # just in case someone did '"blah blah"' | ||
| 1243 | |||
| 1244 | chomp $on; | ||
| 1245 | &B_log("DEBUG","ch_rc returned: $param=$on in checkServiceOnHPUX"); | ||
| 1246 | |||
| 1247 | if ($on =~ /^\d+$/ && $on != 0) { | ||
| 1248 | # service is on | ||
| 1249 | &B_log("DEBUG","CheckService found $param service is set to \'on\' in scripts."); | ||
| 1250 | return NOTSECURE_CAN_CHANGE(); | ||
| 1251 | } | ||
| 1252 | elsif($on =~ /^\s*$/) { | ||
| 1253 | # if the value returned is an empty string return | ||
| 1254 | # INCONSISTENT(), since we don't know what the hard-coded default is. | ||
| 1255 | return INCONSISTENT(); | ||
| 1256 | } | ||
| 1257 | } else { | ||
| 1258 | # those files which rely on comments to determine what gets | ||
| 1259 | # turned on, such as inetd.conf and inittab | ||
| 1260 | my $inettabs=&B_Backtick("$grep -e '^[[:space:]]*$param' $inetd $inittab"); | ||
| 1261 | if ($inettabs =~ /.+/) { # . matches anything except newlines | ||
| 1262 | # service is not off | ||
| 1263 | &B_log("DEBUG","Checking inetd.conf and inittab; found $inettabs"); | ||
| 1264 | ########################### BREAK out, don't skip question | ||
| 1265 | return NOTSECURE_CAN_CHANGE(); | ||
| 1266 | } | ||
| 1267 | } | ||
| 1268 | } # foreach $param | ||
| 1269 | |||
| 1270 | # boot-time parameters are not set; check processes | ||
| 1271 | # checkprocs for services returns INCONSISTENT() if a service is found | ||
| 1272 | # since a found-service is inconsistent with the above checks. | ||
| 1273 | B_log("DEBUG","Boot-Parameters not set, checking processes."); | ||
| 1274 | if (&runlevel < 2) { # Below runlevel 2, it is unlikely that | ||
| 1275 | #services will be running, so just check "on-disk" state | ||
| 1276 | &B_log("NOTE","Running during boot sequence, so skipping process checks"); | ||
| 1277 | return SECURE_CANT_CHANGE(); | ||
| 1278 | } else { | ||
| 1279 | return &checkProcsForService($service); | ||
| 1280 | } | ||
| 1281 | } | ||
| 1282 | |||
| 1283 | sub runlevel { | ||
| 1284 | my $who = &getGlobal("BIN", "who"); | ||
| 1285 | my $runlevel = &B_Backtick("$who -r"); | ||
| 1286 | if ($runlevel =~ s/.* run-level (\S).*/$1/) { | ||
| 1287 | &B_log("DEBUG","Runlevel is: $runlevel"); | ||
| 1288 | return $runlevel; | ||
| 1289 | } else { | ||
| 1290 | &B_log("WARNING","Can not determine runlevel, assuming runlevel 3"); | ||
| 1291 | &B_log("DEBUG","Runlevel command output: $runlevel"); | ||
| 1292 | return "3"; #safer since the who command didn't work, we'll assume | ||
| 1293 | # runlevel 3 since that provides more checks. | ||
| 1294 | } | ||
| 1295 | } | ||
| 1296 | |||
| 1297 | # | ||
| 1298 | # given a profile file, it will return a PATH array set by the file. | ||
| 1299 | # | ||
| 1300 | sub B_get_path($) { | ||
| 1301 | my $file = $_[0]; | ||
| 1302 | my $sh = &getGlobal("BIN", "sh"); | ||
| 1303 | # use (``)[0] is becuase, signal 0 maybe trapped which will produce some stdout | ||
| 1304 | my $path = (`$sh -c '. $file 1>/dev/null 2>&1 < /dev/null ; echo \$PATH'`)[0]; | ||
| 1305 | my @path_arr = split(":", $path); | ||
| 1306 | my %tmp_path; | ||
| 1307 | my %path; | ||
| 1308 | for my $tmpdir (@path_arr) { | ||
| 1309 | chomp $tmpdir; | ||
| 1310 | if ($tmpdir ne "" && ! $tmp_path{$tmpdir}) { | ||
| 1311 | $tmp_path{$tmpdir}++; | ||
| 1312 | } | ||
| 1313 | } | ||
| 1314 | return keys %tmp_path; | ||
| 1315 | } | ||
| 1316 | |||
| 1317 | # Convert to trusted mode if it's not already | ||
| 1318 | sub convertToTrusted { | ||
| 1319 | &B_log("DEBUG","# sub convertToTrusted \n"); | ||
| 1320 | if( ! &isSystemTrusted) { | ||
| 1321 | |||
| 1322 | my ($ok, $message) = &isOKtoConvert; | ||
| 1323 | |||
| 1324 | my $ts_header="\n---------------------------------\nTrusted Systems:\n" . | ||
| 1325 | "---------------------------------\n"; | ||
| 1326 | |||
| 1327 | if ($ok) { | ||
| 1328 | # actually do the conversion | ||
| 1329 | if(&B_System(&getGlobal('BIN','tsconvert'), &getGlobal('BIN','tsconvert') . " -r")){ | ||
| 1330 | # adjust change times for user passwords to keep them valid | ||
| 1331 | # default is to expire them when converting to a trusted system, | ||
| 1332 | # which can be problematic, especially since some older versions of | ||
| 1333 | # SecureShell do not allow the user to change the password | ||
| 1334 | &B_System(&getGlobal('BIN','modprpw') . " -V", ""); | ||
| 1335 | |||
| 1336 | my $getprdef = &getGlobal('BIN','getprdef'); | ||
| 1337 | my $oldsettings = &B_Backtick("$getprdef -m lftm,exptm,mintm,expwarn,umaxlntr"); | ||
| 1338 | $oldsettings =~ s/ //g; | ||
| 1339 | |||
| 1340 | # remove password lifetime and increasing login tries so they | ||
| 1341 | # don't lock themselves out of the system entirely. | ||
| 1342 | # set default expiration time and the like. | ||
| 1343 | my $newsettings="lftm=0,exptm=0,mintm=0,expwarn=0,umaxlntr=10"; | ||
| 1344 | |||
| 1345 | &B_System(&getGlobal('BIN','modprdef') . " -m $newsettings", | ||
| 1346 | &getGlobal('BIN','modprdef') . " -m $oldsettings"); | ||
| 1347 | |||
| 1348 | &B_TODO($ts_header . | ||
| 1349 | "Your system has been converted to a trusted system.\n" . | ||
| 1350 | "You should review the security settings available on a trusted system.\n". | ||
| 1351 | "$message"); | ||
| 1352 | |||
| 1353 | # to get rid of "Cron: Your job did not contain a valid audit ID." | ||
| 1354 | # error, we re-read the crontab file after converting to trusted mode | ||
| 1355 | # Nothing is necessary in "revert" since we won't be in trusted mode | ||
| 1356 | # at that time. | ||
| 1357 | # crontab's errors can be spurious, and this will report an 'error' | ||
| 1358 | # of the crontab file is missing, so we send stderr to the bit bucket | ||
| 1359 | my $crontab = &getGlobal('BIN',"crontab"); | ||
| 1360 | &B_System("$crontab -l 2>/dev/null | $crontab",""); | ||
| 1361 | } | ||
| 1362 | |||
| 1363 | } else { | ||
| 1364 | &B_TODO($ts_header . $message); | ||
| 1365 | return 0; # not ok to convert, so we didn't | ||
| 1366 | } | ||
| 1367 | } | ||
| 1368 | else { | ||
| 1369 | &B_log("DEBUG","System is already in trusted mode, no action taken.\n"); | ||
| 1370 | return 1; | ||
| 1371 | } | ||
| 1372 | |||
| 1373 | # just to make sure | ||
| 1374 | if( &isSystemTrusted ) { | ||
| 1375 | return 1; | ||
| 1376 | } else { | ||
| 1377 | &B_log("ERROR","Trusted system conversion was unsuccessful for an unknown reason.\n" . | ||
| 1378 | " You may try using SAM/SMH to do the conversion instead of Bastille.\n"); | ||
| 1379 | return 0; | ||
| 1380 | } | ||
| 1381 | } | ||
| 1382 | |||
| 1383 | # isOKtoConvert - check for conflicts between current system state and trusted | ||
| 1384 | # mode | ||
| 1385 | # | ||
| 1386 | # Return values | ||
| 1387 | # 0 - conflict found, see message for details | ||
| 1388 | # 1 - no conflicts, see message for further instructions | ||
| 1389 | # | ||
| 1390 | sub isOKtoConvert { | ||
| 1391 | &B_log("DEBUG","# sub isOKtoConvert \n"); | ||
| 1392 | # initialize text for TODO instructions | ||
| 1393 | my $specialinstructions=" - convert to trusted mode\n"; | ||
| 1394 | |||
| 1395 | # These are somewhat out-of-place, but only affect the text of the message. | ||
| 1396 | # Each of these messages is repeated in a separate TODO item in the | ||
| 1397 | # appropriate subroutine. | ||
| 1398 | if (&getGlobalConfig("AccountSecurity","single_user_password") eq "Y") { | ||
| 1399 | if (&GetDistro =~ "^HP-UX11.(.*)" and $1<23 ) { | ||
| 1400 | $specialinstructions .= " - set a single user password\n"; | ||
| 1401 | } | ||
| 1402 | } | ||
| 1403 | |||
| 1404 | if (&getGlobalConfig("AccountSecurity","passwordpolicies") eq "Y") { | ||
| 1405 | $specialinstructions .= " - set trusted mode password policies\n"; | ||
| 1406 | } | ||
| 1407 | |||
| 1408 | if (&getGlobalConfig("AccountSecurity", "PASSWORD_HISTORY_DEPTHyn") eq "Y") { | ||
| 1409 | $specialinstructions .= " - set a password history depth\n"; | ||
| 1410 | } | ||
| 1411 | |||
| 1412 | if (&getGlobalConfig("AccountSecurity","system_auditing") eq "Y") { | ||
| 1413 | $specialinstructions .= " - enable auditing\n"; | ||
| 1414 | } | ||
| 1415 | |||
| 1416 | my $saminstructions= | ||
| 1417 | "The security settings can be modified by running SAM as follows:\n" . | ||
| 1418 | "# sam\n" . | ||
| 1419 | "Next, go to the \"Auditing and Security Area\" and review\n" . | ||
| 1420 | "each sub-section. Make sure that you review all of your\n" . | ||
| 1421 | "settings, as some policies may seem restrictive.\n\n" . | ||
| 1422 | "On systems using the System Management Homepage, you can\n". | ||
| 1423 | "change your settings via the Tools:Security Attributes Configuration\n". | ||
| 1424 | "section. On some systems, you may also have the option of using SMH.\n\n"; | ||
| 1425 | |||
| 1426 | # First, check for possible conflicts and corner cases | ||
| 1427 | |||
| 1428 | # check nsswitch for possible conflicts | ||
| 1429 | my $nsswitch = &getGlobal('FILE', 'nsswitch.conf'); | ||
| 1430 | if ( -e $nsswitch) { | ||
| 1431 | open(FILE, $nsswitch); | ||
| 1432 | while (<FILE>) { | ||
| 1433 | if (/nis/ or /compat/ or /ldap/) { | ||
| 1434 | my $message = "Bastille found a possible conflict between trusted mode and\n" . | ||
| 1435 | "$nsswitch. Please remove all references to\n" . | ||
| 1436 | "\"compat\", \"nis\" and \"ldap\" in $nsswitch\n" . | ||
| 1437 | "and rerun Bastille, or use SAM/SMH to\n" . | ||
| 1438 | "$specialinstructions\n". | ||
| 1439 | "$saminstructions"; | ||
| 1440 | close(FILE); | ||
| 1441 | return (0,$message); | ||
| 1442 | } | ||
| 1443 | } | ||
| 1444 | close(FILE); | ||
| 1445 | } | ||
| 1446 | |||
| 1447 | # check the namesvrs config file for possible NIS conflicts | ||
| 1448 | #Changed to unless "Y AND Y" since question can be skipped when nis is off | ||
| 1449 | # but corner cases can still exist, so check then too. | ||
| 1450 | unless ( &getGlobalConfig('MiscellaneousDaemons','nis_client') eq "Y" and | ||
| 1451 | &getGlobalConfig('MiscellaneousDaemons','nis_server') eq "Y" ) { | ||
| 1452 | my $namesvrs = &getGlobal('FILE', 'namesvrs'); | ||
| 1453 | if (open(FILE, $namesvrs)) { | ||
| 1454 | while (<FILE>) { | ||
| 1455 | if (/^NIS.*=["]?1["]?$/) { | ||
| 1456 | my $message= "Possible conflict between trusted mode and NIS found.\n". | ||
| 1457 | "Please use SAM/SMH to\n" . | ||
| 1458 | " - turn off NIS\n" . | ||
| 1459 | "$specialinstructions\n". | ||
| 1460 | "$saminstructions"; | ||
| 1461 | close(FILE); | ||
| 1462 | return (0,$message); | ||
| 1463 | } | ||
| 1464 | } | ||
| 1465 | close(FILE); | ||
| 1466 | } else { | ||
| 1467 | &B_log("ERROR","Unable to open $namesvrs for reading."); | ||
| 1468 | my $message= "Possible conflict between trusted mode and NIS found.\n". | ||
| 1469 | "Please use SAM/SMH to\n" . | ||
| 1470 | " - turn off NIS\n" . | ||
| 1471 | "$specialinstructions\n". | ||
| 1472 | "$saminstructions"; | ||
| 1473 | return (0,$message); | ||
| 1474 | } | ||
| 1475 | if ( &B_match_line (&getGlobal("FILE","passwd"),"^\+:.*")) { | ||
| 1476 | my $message= '"+" entry found in passwd file. These are not\n' . | ||
| 1477 | "compatible with Trusted Mode. Either remove the entries\n" . | ||
| 1478 | "and re-run Bastille, or re-run Bastille, and direct it to\n" . | ||
| 1479 | "disable NIS client and server.\n"; | ||
| 1480 | return (0,$message); | ||
| 1481 | } | ||
| 1482 | |||
| 1483 | } | ||
| 1484 | |||
| 1485 | |||
| 1486 | # check for conflicts with DCE integrated login | ||
| 1487 | my $authcmd = &getGlobal('BIN','auth.adm'); | ||
| 1488 | if ( -e $authcmd ) { | ||
| 1489 | my $retval = system("PATH=/usr/bin $authcmd -q 1>/dev/null 2>&1"); | ||
| 1490 | if ($retval != 0 and $retval != 1) { | ||
| 1491 | my $message="It appears that DCE integrated login is configured on this system.\n" . | ||
| 1492 | "DCE integrated login is incompatible with trusted systems and\n" . | ||
| 1493 | "auditing. Bastille is unable to\n" . | ||
| 1494 | "$specialinstructions" . | ||
| 1495 | "You will need to configure auditing and password policies using DCE.\n\n"; | ||
| 1496 | return (0,$message); | ||
| 1497 | } | ||
| 1498 | } | ||
| 1499 | |||
| 1500 | if ( -e &getGlobal('FILE','shadow') ) { | ||
| 1501 | my $message="This system has already been converted to shadow passwords.\n" . | ||
| 1502 | "Shadow passwords are incompatible with trusted mode.\n" . | ||
| 1503 | "Bastille is unable to\n" . | ||
| 1504 | "$specialinstructions" . | ||
| 1505 | "If you desire these features, you should use\n". | ||
| 1506 | "\'pwunconv\' to change back to standard passwords,\n". | ||
| 1507 | "and then rerun Bastille.\n\n"; | ||
| 1508 | return (0,$message); | ||
| 1509 | } | ||
| 1510 | |||
| 1511 | return (1,$saminstructions); | ||
| 1512 | } | ||
| 1513 | |||
| 1514 | # This routine allows Bastille to determine trusted-mode extension availability | ||
| 1515 | |||
| 1516 | sub convertToShadow { | ||
| 1517 | |||
| 1518 | if (&isSystemTrusted) { | ||
| 1519 | # This is an internal error...Bastille should not call this routine | ||
| 1520 | # in this case. Error is here for robustness against future changes. | ||
| 1521 | &B_log("ERROR","This system is already converted to trusted mode.\n" . | ||
| 1522 | " Converting to shadow passwords will not be attempted.\n"); | ||
| 1523 | return 0; | ||
| 1524 | } | ||
| 1525 | |||
| 1526 | # configuration files on which shadowed passwords depend | ||
| 1527 | my $nsswitch_conf = &getGlobal('FILE',"nsswitch.conf"); | ||
| 1528 | |||
| 1529 | # binaries used to convert to a shadowed password | ||
| 1530 | my $pwconv = &getGlobal('BIN',"pwconv"); | ||
| 1531 | my $echo = &getGlobal('BIN','echo'); # the echo is used to pipe a yes into the pwconv program as | ||
| 1532 | # pwconv requires user interaction. | ||
| 1533 | |||
| 1534 | # the binary used in a system revert. | ||
| 1535 | my $pwunconv = &getGlobal('BIN',"pwunconv"); | ||
| 1536 | #check the password file for nis usage and if the nis client | ||
| 1537 | #or server is running. | ||
| 1538 | if(-e $nsswitch_conf) { | ||
| 1539 | # check the file for nis, nis+, compat, or dce usage. | ||
| 1540 | if(&B_match_line($nsswitch_conf, '^\s*passwd:.+(nis|nisplus|dce|compat)')) { | ||
| 1541 | my $shadowTODO = "\n---------------------------------\nHide encrypted passwords:\n" . | ||
| 1542 | "---------------------------------\n" . | ||
| 1543 | "This version of password shadowing does not support any repository other\n" . | ||
| 1544 | "than files. In order to convert your password database to shadowed passwords\n" . | ||
| 1545 | "there can be no mention of nis, nisplus, compat, or dce in the passwd\n" . | ||
| 1546 | "field of the \"$nsswitch_conf\" file. Please make the necessary edits to\n" . | ||
| 1547 | "the $nsswitch_conf file and run Bastille again using the command:\n" . | ||
| 1548 | "\"bastille -b\"\n"; | ||
| 1549 | # Adding the shadowTODO comment to the TODO list. | ||
| 1550 | &B_TODO("$shadowTODO"); | ||
| 1551 | # Notifing the user that the shadowed password coversion has failed. | ||
| 1552 | &B_log("ERROR","Password Shadowing Conversion Failed\n" . | ||
| 1553 | "$shadowTODO"); | ||
| 1554 | # exiting the subroutine. | ||
| 1555 | return 0; | ||
| 1556 | } | ||
| 1557 | |||
| 1558 | } | ||
| 1559 | |||
| 1560 | # convert the password file to a shadowed repository. | ||
| 1561 | if (( -e $pwconv ) and ( -e $pwunconv ) and | ||
| 1562 | ( &B_System("$echo \"yes\" | $pwconv","$pwunconv") ) ){ | ||
| 1563 | &B_TODO( "\n---------------------------------\nShadowing Password File:\n" . | ||
| 1564 | "---------------------------------\n" . | ||
| 1565 | "Your password file has been converted to use password shadowing.\n" . | ||
| 1566 | "This version of password shadowing does not support any repository other\n" . | ||
| 1567 | "than files. There can be no mention of nis, nisplus, compat, or dce\n" . | ||
| 1568 | "in the passwd field of the \"$nsswitch_conf\" file.\n\n" ); | ||
| 1569 | } else { | ||
| 1570 | &B_log("ERROR","Conversion to shadow mode failed. The system may require ". | ||
| 1571 | "a patch to be capable of switching to shadow mode, or the ". | ||
| 1572 | "system my be in a state where conversion is not possible."); | ||
| 1573 | } | ||
| 1574 | } | ||
| 1575 | |||
| 1576 | |||
| 1577 | |||
| 1578 | ########################################################################## | ||
| 1579 | # &getSupportedSettings(); | ||
| 1580 | # Manipulates %trustedParameter and %isSupportedSetting, file-scoped variables | ||
| 1581 | # | ||
| 1582 | # Reads the password policy support matrix, which in-turn gives Bastille the | ||
| 1583 | # places it should look for a given password policy setting. | ||
| 1584 | |||
| 1585 | # Note the file was created like this so if could be maintained in an Excel(tm) | ||
| 1586 | # spreadsheet, to optimize reviewability. TODO: consider other formats | ||
| 1587 | |||
| 1588 | # File Format: | ||
| 1589 | # HEADERS:<comment>,[<OS Version> <Mode> <Extensions>,]... | ||
| 1590 | # [ | ||
| 1591 | # :<label>:<trusted equivalent>,,,,,,,,,,,,<comment> | ||
| 1592 | # <action> (comment), [<test value>,]... | ||
| 1593 | # ] ... | ||
| 1594 | # Example; | ||
| 1595 | # 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 | ||
| 1596 | #:ABORT_LOGIN_ON_MISSING_HOMEDIR,,,,,,,,,,,,,root | ||
| 1597 | #/etc/security.dsc (search),x,,xx,x,x,x,!,!,!,!,!,!, | ||
| 1598 | #/etc/default/security(search),y,y,y,y,y,y,y,y,y,y,y,y, | ||
| 1599 | #getprdef (execute with <Trusted Equiv> argument),x,x,x,x,x,x,x,x,x,x,x,x, | ||
| 1600 | |||
| 1601 | ########################################################################### | ||
| 1602 | our %trustedParameter = (); | ||
| 1603 | our %isSupportedSetting = (); | ||
| 1604 | |||
| 1605 | sub getSupportedSettings() { | ||
| 1606 | |||
| 1607 | my $line; # For a config file line | ||
| 1608 | my $linecount = 0; | ||
| 1609 | my $currentsetting = ""; | ||
| 1610 | my @fields; # Fields in a given line | ||
| 1611 | my @columns; #Column Definitions | ||
| 1612 | |||
| 1613 | |||
| 1614 | &B_open(*SETTINGSFILE,&getGlobal('BFILE','AccountSecSupport')); | ||
| 1615 | my @settingLines=<SETTINGSFILE>; | ||
| 1616 | &B_close(*SETTINGSFILE); | ||
| 1617 | |||
| 1618 | #Remove blank-lines and comments | ||
| 1619 | @settingLines = grep(!/^#/,@settingLines); | ||
| 1620 | @settingLines = grep(!/^(\s*,+)*$/,@settingLines); | ||
| 1621 | |||
| 1622 | foreach $line (@settingLines) { | ||
| 1623 | ++$linecount; | ||
| 1624 | @fields = split(/,/,$line); | ||
| 1625 | if ($line =~ /^Information Source:/) { #Sets up colums | ||
| 1626 | my $fieldcount = 1; #Skipping first field | ||
| 1627 | while ((defined($fields[$fieldcount])) and | ||
| 1628 | ($fields[$fieldcount] =~ /\d+\.\d+/)){ | ||
| 1629 | my @subfields = split(/ /,$fields[$fieldcount]); | ||
| 1630 | my $fieldsCount = @subfields; | ||
| 1631 | if ($fieldsCount != 3){ | ||
| 1632 | &B_log("ERROR","Invalid subfield count: $fieldsCount in:". | ||
| 1633 | &getGlobal('BFILE','AccountSecSupport') . | ||
| 1634 | " line: $linecount and field: $fieldcount"); | ||
| 1635 | } | ||
| 1636 | $columns[$fieldcount] = {OSVersion => $subfields[0], | ||
| 1637 | Mode => $subfields[1], | ||
| 1638 | Extension => $subfields[2] }; | ||
| 1639 | &B_log("DEBUG","Found Header Column, $columns[$fieldcount]{'OSVersion'}, ". | ||
| 1640 | $columns[$fieldcount]{'Mode'} ." , " . | ||
| 1641 | $columns[$fieldcount]{'Extension'}); | ||
| 1642 | ++$fieldcount; | ||
| 1643 | } # New Account Seting ex: | ||
| 1644 | } elsif ($line =~ /^:([^,:]+)(?::([^,]+))?/) { # :PASSWORD_WARNDAYS:expwarn,,,,,,,,,,,, | ||
| 1645 | $currentsetting = $1; | ||
| 1646 | if (defined($2)) { | ||
| 1647 | $trustedParameter{"$currentsetting"}=$2; | ||
| 1648 | } | ||
| 1649 | &B_log("DEBUG","Found Current Setting: ". $currentsetting . | ||
| 1650 | "/" . $trustedParameter{"$currentsetting"}); | ||
| 1651 | } elsif (($line =~ /(^[^, :\)\(]+)[^,]*,((?:(?:[!y?nx]|!!),)+)/) and #normal line w/ in setting ex: | ||
| 1652 | ($currentsetting ne "")){ # security.dsc (search),x,x,x,x,x,!,!!,!,!,!,!, | ||
| 1653 | my $placeToLook = $1; | ||
| 1654 | my $fieldcount = 1; #Skip the first one, which we used in last line | ||
| 1655 | while (defined($fields[$fieldcount])) { | ||
| 1656 | &B_log("DEBUG","Setting $currentsetting : $columns[$fieldcount]{OSVersion} , ". | ||
| 1657 | "$columns[$fieldcount]{Mode} , ". | ||
| 1658 | "$columns[$fieldcount]{Extension} , ". | ||
| 1659 | "$placeToLook, to $fields[$fieldcount]"); | ||
| 1660 | $isSupportedSetting{"$currentsetting"} | ||
| 1661 | {"$columns[$fieldcount]{OSVersion}"} | ||
| 1662 | {"$columns[$fieldcount]{Mode}"} | ||
| 1663 | {"$columns[$fieldcount]{Extension}"} | ||
| 1664 | {"$placeToLook"} = | ||
| 1665 | $fields[$fieldcount]; | ||
| 1666 | ++$fieldcount; | ||
| 1667 | } | ||
| 1668 | } else { | ||
| 1669 | if ($line !~ /^,*/) { | ||
| 1670 | &B_log("ERROR","Incorrectly Formatted Line at ". | ||
| 1671 | &getGlobal('BFILE','AccountSecSupport') . ": $linecount"); | ||
| 1672 | } | ||
| 1673 | } | ||
| 1674 | } | ||
| 1675 | } | ||
| 1676 | |||
| 1677 | ########################################################################## | ||
| 1678 | # &B_get_sec_value($param); | ||
| 1679 | # This subroutine finds the value for a given user policy parameter. | ||
| 1680 | # Specifically, it supports the parameters listed in the internal data structure | ||
| 1681 | |||
| 1682 | # Return values: | ||
| 1683 | # 'Not Defined' if the value is not present or not uniquely defined. | ||
| 1684 | # $value if the value is present and unique | ||
| 1685 | # | ||
| 1686 | ########################################################################### | ||
| 1687 | sub B_get_sec_value($) { | ||
| 1688 | my $param=$_[0]; | ||
| 1689 | |||
| 1690 | my $os_version; | ||
| 1691 | if (&GetDistro =~ /^HP-UX\D*(\d+\.\d+)/ ){ | ||
| 1692 | $os_version=$1; | ||
| 1693 | } else { | ||
| 1694 | &B_log("ERROR","B_get_sec_value only supported on HP-UX"); | ||
| 1695 | return undef; | ||
| 1696 | } | ||
| 1697 | # my $sec_dsc = &getGlobal('FILE', 'security.dsc'); | ||
| 1698 | my $sec_file = &getGlobal('FILE', 'security'); | ||
| 1699 | my $getprdef = &getGlobal('BIN','getprdef'); | ||
| 1700 | my $getprpw = &getGlobal('BIN','getprpw'); | ||
| 1701 | my $userdbget = &getGlobal('BIN','userdbget'); | ||
| 1702 | my $passwd = &getGlobal('BIN','passwd'); | ||
| 1703 | |||
| 1704 | my $sec_flags = ""; | ||
| 1705 | my @sec_settings=(); | ||
| 1706 | my $user_sec_setting=""; | ||
| 1707 | |||
| 1708 | my $security_mode="Standard"; | ||
| 1709 | my $security_extension="no-SMSE"; | ||
| 1710 | |||
| 1711 | &B_log("DEBUG","Entering get_sec_value for: $param"); | ||
| 1712 | |||
| 1713 | sub isok ($) { # Locally-scoped subroutine, takes supported-matrix entry as argument | ||
| 1714 | my $supportedMatrixEntry = $_[0]; | ||
| 1715 | |||
| 1716 | if ($supportedMatrixEntry =~ /!/) { #Matrix Entry for "Documented and/or tested" | ||
| 1717 | &B_log("DEBUG","isOk TRUE: $supportedMatrixEntry"); | ||
| 1718 | return 1; | ||
| 1719 | } else { | ||
| 1720 | &B_log("DEBUG","isOk FALSE: $supportedMatrixEntry"); | ||
| 1721 | return 0; #FALSE | ||
| 1722 | } | ||
| 1723 | } #end local subroutine | ||
| 1724 | |||
| 1725 | #Get Top Array item non-destructively | ||
| 1726 | sub getTop (@) { | ||
| 1727 | my @incomingArray = @_; | ||
| 1728 | my $topval = pop(@incomingArray); | ||
| 1729 | push(@incomingArray,$topval); #Probably redundant, but left in just in case. | ||
| 1730 | return $topval; | ||
| 1731 | } | ||
| 1732 | |||
| 1733 | sub ifExistsPushOnSecSettings($$) { | ||
| 1734 | my $sec_settings = $_[0]; | ||
| 1735 | my $pushval = $_[1]; | ||
| 1736 | |||
| 1737 | if ($pushval ne ""){ | ||
| 1738 | push (@$sec_settings, $pushval); | ||
| 1739 | } | ||
| 1740 | } | ||
| 1741 | |||
| 1742 | #prpw and prdef both use "YES" instead of "1" like the other settings. | ||
| 1743 | sub normalizePolicy($){ | ||
| 1744 | my $setting = $_[0]; | ||
| 1745 | |||
| 1746 | $setting =~ s/YES/1/; | ||
| 1747 | $setting =~ s/NO/1/; | ||
| 1748 | |||
| 1749 | return $setting; | ||
| 1750 | } | ||
| 1751 | |||
| 1752 | |||
| 1753 | |||
| 1754 | if ((%trustedParameter == ()) or (%isSupportedSetting == ())) { | ||
| 1755 | # Manipulates %trustedParameter and %isSupportedSetting | ||
| 1756 | &getSupportedSettings; | ||
| 1757 | } | ||
| 1758 | |||
| 1759 | #First determine the security mode | ||
| 1760 | my $shadowFile = &getGlobal("FILE","shadow"); | ||
| 1761 | my $passwdFile = &getGlobal("FILE","passwd"); | ||
| 1762 | |||
| 1763 | if (&isSystemTrusted) { | ||
| 1764 | $security_mode = 'Trusted'; | ||
| 1765 | } elsif ((-e $shadowFile) and #check file exist, and that passwd has no non-"locked" accounts | ||
| 1766 | (not(&B_match_line($passwdFile,'^[^\:]+:[^:]*[^:*x]')))) { | ||
| 1767 | $security_mode = 'Shadow'; | ||
| 1768 | } else { | ||
| 1769 | $security_mode = 'Standard'; | ||
| 1770 | } | ||
| 1771 | if (&isTrustedMigrationAvailable) { | ||
| 1772 | $security_extension = 'SMSE'; | ||
| 1773 | } else { | ||
| 1774 | $security_extension = 'no-SMSE'; | ||
| 1775 | } | ||
| 1776 | &B_log("DEBUG","Security mode: $security_mode extension: $security_extension"); | ||
| 1777 | # Now look up the value from each applicable database, from highest precedence | ||
| 1778 | # to lowest: | ||
| 1779 | &B_log("DEBUG","Checking $param in userdbget"); | ||
| 1780 | if (&isok($isSupportedSetting{$param}{$os_version}{$security_mode} | ||
| 1781 | {$security_extension}{"userdbget_-a"})) { | ||
| 1782 | &ifExistsPushOnSecSettings(\@sec_settings, | ||
| 1783 | &B_getValueFromString('\w+\s+\w+=(\S+)', | ||
| 1784 | &B_Backtick("$userdbget -a $param"))); | ||
| 1785 | &B_log("DEBUG", $param . ":userdbget setting: ". &getTop(@sec_settings)); | ||
| 1786 | } | ||
| 1787 | &B_log("DEBUG","Checking $param in passwd"); | ||
| 1788 | if (&isok($isSupportedSetting{$param}{$os_version}{$security_mode} | ||
| 1789 | {$security_extension}{"passwd_-sa"})) { | ||
| 1790 | if ($param eq "PASSWORD_MINDAYS") { | ||
| 1791 | &ifExistsPushOnSecSettings(\@sec_settings, | ||
| 1792 | &B_getValueFromString('(?:\w+\s+){2}[\d\/]+\s+(\d+)\s+\d+', | ||
| 1793 | &B_Backtick("$passwd -s -a"))); | ||
| 1794 | } elsif ($param eq "PASSWORD_MAXDAYS") { | ||
| 1795 | &ifExistsPushOnSecSettings(\@sec_settings, | ||
| 1796 | &B_getValueFromString('(?:\w+\s+){2}[\d\/]+\s+\d+\s+(\d+)', | ||
| 1797 | &B_Backtick("$passwd -s -a"))); | ||
| 1798 | } elsif ($param eq "PASSWORD_WARNDAYS") { | ||
| 1799 | &ifExistsPushOnSecSettings(\@sec_settings, | ||
| 1800 | &B_getValueFromString('(?:\w+\s+){2}[\d\/]+(?:\s+\d+){2}\s+(\d+)', | ||
| 1801 | &B_Backtick("$passwd -s -a"))); | ||
| 1802 | } | ||
| 1803 | &B_log("DEBUG", $param . ":passwd -sa setting: ". &getTop(@sec_settings)); | ||
| 1804 | } | ||
| 1805 | &B_log("DEBUG","Checking $param in get prpw"); | ||
| 1806 | if (&isok($isSupportedSetting{$param}{$os_version}{$security_mode} | ||
| 1807 | {$security_extension}{"getprpw"})) { | ||
| 1808 | my $logins = &getGlobal("BIN","logins"); | ||
| 1809 | my @userArray = split(/\n/,`$logins`); | ||
| 1810 | my $userParamVals = ''; | ||
| 1811 | foreach my $rawuser (@userArray) { | ||
| 1812 | $rawuser =~ /^(\S+)/; | ||
| 1813 | my $user = $1; | ||
| 1814 | my $nextParamVal=&B_Backtick("$getprpw -l -m $trustedParameter{$param} $user"); | ||
| 1815 | $nextParamVal =~ s/\w*=(-*[\w\d]*)/$1/; | ||
| 1816 | if ($nextParamVal != -1) { #Don't count users for which the local DB is undefined | ||
| 1817 | $userParamVals .= $user . "::::" . $nextParamVal ."\n"; | ||
| 1818 | } | ||
| 1819 | } #Note getValueFromStrings deals with duplicates, returning "Not Unigue" | ||
| 1820 | my $policySetting = &B_getValueFromString('::::(\S+)',"$userParamVals"); | ||
| 1821 | &ifExistsPushOnSecSettings (\@sec_settings, &normalizePolicy($policySetting)); | ||
| 1822 | &B_log("DEBUG", $param . ":prpw setting: ". &getTop(@sec_settings)); | ||
| 1823 | } | ||
| 1824 | &B_log("DEBUG","Checking $param in get prdef"); | ||
| 1825 | if (&isok($isSupportedSetting{$param}{$os_version}{$security_mode} | ||
| 1826 | {$security_extension}{"getprdef"})) { | ||
| 1827 | $_ = &B_Backtick ("$getprdef -m " . $trustedParameter{$param}); | ||
| 1828 | /\S+=(\S+)/; | ||
| 1829 | my $policySetting = $1; | ||
| 1830 | &ifExistsPushOnSecSettings(\@sec_settings, &normalizePolicy($policySetting)); | ||
| 1831 | &B_log("DEBUG", $param . ":prdef setting: ". &getTop(@sec_settings)); | ||
| 1832 | |||
| 1833 | } | ||
| 1834 | &B_log("DEBUG","Checking $param in default security"); | ||
| 1835 | if (&isok($isSupportedSetting{$param}{$os_version}{$security_mode} | ||
| 1836 | {$security_extension}{"/etc/default/security"})) { | ||
| 1837 | &ifExistsPushOnSecSettings(\@sec_settings,&B_getValueFromFile('^\s*'. $param . | ||
| 1838 | '\s*=\s*([^\s#]+)\s*$', $sec_file)); | ||
| 1839 | &B_log("DEBUG", $param . ":default setting: ". &getTop(@sec_settings)); | ||
| 1840 | } | ||
| 1841 | #Commented below code in 3.0 release to avoid implication that bastille | ||
| 1842 | #had ever set these values explicitly, and the implications to runnable | ||
| 1843 | #config files where Bastille would then apply the defaults as actual policy | ||
| 1844 | #with possible conversion to shadow or similar side-effect. | ||
| 1845 | |||
| 1846 | # &B_log("DEBUG","Checking $param in security.dsc"); | ||
| 1847 | #security.dsc, only added in if valid for OS/mode/Extension, and nothing else | ||
| 1848 | #is defined (ie: @sec_settings=0) | ||
| 1849 | # if ((&isok($isSupportedSetting{$param}{$os_version}{$security_mode} | ||
| 1850 | # {$security_extension}{"/etc/security.dsc"})) and (@sec_settings == 0)) { | ||
| 1851 | # &ifExistsPushOnSecSettings(\@sec_settings, &B_getValueFromFile('^' . $param . | ||
| 1852 | # ';(?:[-\w/]*;){2}([-\w/]+);', $sec_dsc)); | ||
| 1853 | # &B_log("DEBUG", $param . ":security.dsc: ". &getTop(@sec_settings)); | ||
| 1854 | # } | ||
| 1855 | |||
| 1856 | # Return what we found | ||
| 1857 | my $last_setting=undef; | ||
| 1858 | my $current_setting=undef; | ||
| 1859 | while (@sec_settings > 0) { | ||
| 1860 | $current_setting = pop(@sec_settings); | ||
| 1861 | &B_log("DEBUG","Comparing $param configuration for identity: " . | ||
| 1862 | $current_setting); | ||
| 1863 | if ((defined($current_setting)) and ($current_setting ne '')) { | ||
| 1864 | if (not(defined($last_setting))){ | ||
| 1865 | $last_setting=$current_setting; | ||
| 1866 | } elsif (($last_setting ne $current_setting) or | ||
| 1867 | ($current_setting eq 'Not Unique')){ | ||
| 1868 | &B_log("DEBUG","$param setting not unique."); | ||
| 1869 | return 'Not Unique'; # Inconsistent state found, return 'Not Unique' | ||
| 1870 | } | ||
| 1871 | } | ||
| 1872 | } | ||
| 1873 | if ((not(defined($last_setting))) or ($last_setting eq '')) { | ||
| 1874 | return undef; | ||
| 1875 | } else { | ||
| 1876 | return $last_setting; | ||
| 1877 | } | ||
| 1878 | |||
| 1879 | } #End B_get_sec_value | ||
| 1880 | |||
| 1881 | sub secureIfNoNameService($){ | ||
| 1882 | my $retval = $_[0]; | ||
| 1883 | |||
| 1884 | if (&isUsingRemoteNameService) { | ||
| 1885 | return MANUAL(); | ||
| 1886 | } else { | ||
| 1887 | return $retval; | ||
| 1888 | } | ||
| 1889 | } | ||
| 1890 | |||
| 1891 | #Specifically for cleartext protocols like NIS, which are not "secure" | ||
| 1892 | sub isUsingRemoteNameService(){ | ||
| 1893 | |||
| 1894 | if (&remoteServiceCheck('nis|nisplus|dce') == SECURE_CAN_CHANGE()){ | ||
| 1895 | return 0; #false | ||
| 1896 | } else { | ||
| 1897 | return 1; | ||
| 1898 | } | ||
| 1899 | } | ||
| 1900 | |||
| 1901 | |||
| 1902 | |||
| 1903 | ########################################### | ||
| 1904 | ## This is a wrapper for two functions that | ||
| 1905 | ## test the existence of nis-like configurations | ||
| 1906 | ## It is used by both the front end test and the back-end run | ||
| 1907 | ############################################## | ||
| 1908 | sub remoteServiceCheck($){ | ||
| 1909 | my $regex = $_[0]; | ||
| 1910 | |||
| 1911 | my $nsswitch_conf = &getGlobal('FILE',"nsswitch.conf"); | ||
| 1912 | my $passwd = &getGlobal('FILE',"passwd"); | ||
| 1913 | |||
| 1914 | # check the file for nis usage. | ||
| 1915 | if (-e $nsswitch_conf) { | ||
| 1916 | if (&B_match_line($nsswitch_conf, '^\s*passwd:.*('. $regex . ')')) { | ||
| 1917 | return NOTSECURE_CAN_CHANGE(); | ||
| 1918 | } elsif ((&B_match_line($nsswitch_conf, '^\s*passwd:.*(compat)')) and | ||
| 1919 | (&B_match_line($passwd, '^\s*\+'))) { | ||
| 1920 | return NOTSECURE_CAN_CHANGE(); # true | ||
| 1921 | } | ||
| 1922 | } elsif ((&B_match_line($passwd, '^\s*\+'))) { | ||
| 1923 | return NOTSECURE_CAN_CHANGE(); | ||
| 1924 | } | ||
| 1925 | |||
| 1926 | my $oldnisdomain=&B_get_rc("NIS_DOMAIN"); | ||
| 1927 | if ((($oldnisdomain eq "") or ($oldnisdomain eq '""')) and (&checkServiceOnHPUX('nis.client'))){ | ||
| 1928 | return SECURE_CAN_CHANGE(); | ||
| 1929 | } | ||
| 1930 | return NOTSECURE_CAN_CHANGE(); | ||
| 1931 | } | ||
| 1932 | |||
| 1933 | ############################################# | ||
| 1934 | # remoteNISPlusServiceCheck | ||
| 1935 | # test the existence of nis+ configuration | ||
| 1936 | ############################################# | ||
| 1937 | sub remoteNISPlusServiceCheck () { | ||
| 1938 | |||
| 1939 | my $nsswitch_conf = &getGlobal('FILE',"nsswitch.conf"); | ||
| 1940 | |||
| 1941 | # check the file for nis+ usage. | ||
| 1942 | if (-e $nsswitch_conf) { | ||
| 1943 | if (&B_match_line($nsswitch_conf, 'nisplus')) { | ||
| 1944 | return NOTSECURE_CAN_CHANGE(); | ||
| 1945 | } | ||
| 1946 | } | ||
| 1947 | |||
| 1948 | return &checkServiceOnHPUX('nisp.client'); | ||
| 1949 | } | ||
| 1950 | |||
| 1951 | |||
| 1952 | ########################################################################## | ||
| 1953 | # This subroutine creates nsswitch.conf file if the file not exists, | ||
| 1954 | # and then append serveral services into the file if the service not | ||
| 1955 | # exists in the file. | ||
| 1956 | ########################################################################## | ||
| 1957 | sub B_create_nsswitch_file ($) { | ||
| 1958 | my $regex = $_[0]; | ||
| 1959 | |||
| 1960 | my $nsswitch = &getGlobal('FILE',"nsswitch.conf"); | ||
| 1961 | |||
| 1962 | if( ! -f $nsswitch ) { | ||
| 1963 | &B_create_file($nsswitch); | ||
| 1964 | # we don't need to revert the permissions change because we just | ||
| 1965 | # created the file | ||
| 1966 | chmod(0444, $nsswitch); | ||
| 1967 | |||
| 1968 | &B_append_line($nsswitch,'\s*passwd:', "passwd: $regex\n"); | ||
| 1969 | &B_append_line($nsswitch,'\s*group:', "group: $regex\n"); | ||
| 1970 | &B_append_line($nsswitch,'\s*hosts:', "hosts: $regex\n"); | ||
| 1971 | &B_append_line($nsswitch,'\s*networks:', "networks: $regex\n"); | ||
| 1972 | &B_append_line($nsswitch,'\s*protocols:', "protocols: $regex\n"); | ||
| 1973 | &B_append_line($nsswitch,'\s*rpc:', "rpc: $regex\n"); | ||
| 1974 | &B_append_line($nsswitch,'\s*publickey:', "publickey: $regex\n"); | ||
| 1975 | &B_append_line($nsswitch,'\s*netgroup:', "netgroup: $regex\n"); | ||
| 1976 | &B_append_line($nsswitch,'\s*automount:', "automount: $regex\n"); | ||
| 1977 | &B_append_line($nsswitch,'\s*aliases:', "aliases: $regex\n"); | ||
| 1978 | &B_append_line($nsswitch,'\s*services:', "services: $regex\n"); | ||
| 1979 | } | ||
| 1980 | } | ||
| 1981 | |||
| 1982 | 1; | ||
| 1983 | |||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/Miscellaneous.pm b/dynamic-layers/meta-perl/recipes-security/bastille/files/Miscellaneous.pm new file mode 100644 index 0000000..b3bdf10 --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/Miscellaneous.pm | |||
| @@ -0,0 +1,166 @@ | |||
| 1 | package Bastille::API::Miscellaneous; | ||
| 2 | use strict; | ||
| 3 | |||
| 4 | use File::Path; | ||
| 5 | use Bastille::API; | ||
| 6 | use Bastille::API::HPSpecific; | ||
| 7 | use Bastille::API::FileContent; | ||
| 8 | |||
| 9 | require Exporter; | ||
| 10 | our @ISA = qw(Exporter); | ||
| 11 | our @EXPORT_OK = qw( | ||
| 12 | PrepareToRun | ||
| 13 | B_is_package_installed | ||
| 14 | ); | ||
| 15 | our @EXPORT = @EXPORT_OK; | ||
| 16 | |||
| 17 | |||
| 18 | ########################################################################### | ||
| 19 | # | ||
| 20 | # PrepareToRun sets up Bastille to run. It checks the ARGV array for | ||
| 21 | # special options and runs ConfigureForDistro to set necessary file | ||
| 22 | # locations and other global variables. | ||
| 23 | # | ||
| 24 | ########################################################################### | ||
| 25 | |||
| 26 | sub PrepareToRun { | ||
| 27 | |||
| 28 | # Make sure we're root! | ||
| 29 | if ( $> != 0 ) { | ||
| 30 | &B_log("ERROR","Bastille must run as root!\n"); | ||
| 31 | exit(1); | ||
| 32 | } | ||
| 33 | |||
| 34 | |||
| 35 | # Make any directories that don't exist... | ||
| 36 | foreach my $dir (keys %GLOBAL_BDIR) { | ||
| 37 | my $BdirPath = $GLOBAL_BDIR{$dir}; | ||
| 38 | if ( $BdirPath =~ /^\s*\// ) { #Don't make relative directories | ||
| 39 | mkpath ($BdirPath,0,0700); | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | if(&GetDistro =~ "^HP-UX") { | ||
| 44 | &B_check_system; | ||
| 45 | } | ||
| 46 | |||
| 47 | &B_log("ACTION","\n########################################################\n" . | ||
| 48 | "# Begin Bastille Run #\n" . | ||
| 49 | "########################################################\n\n"); | ||
| 50 | |||
| 51 | #read sum file if it exists. | ||
| 52 | &B_read_sums; | ||
| 53 | |||
| 54 | |||
| 55 | # No longer necessary as flags are no longer in sum file, and sums are | ||
| 56 | # are now checked "real time" | ||
| 57 | |||
| 58 | # check the integrity of the files listed | ||
| 59 | # for my $file (sort keys %GLOBAL_SUM) { | ||
| 60 | # &B_check_sum($file); | ||
| 61 | # } | ||
| 62 | # write out the newly flagged sums | ||
| 63 | # &B_write_sums; | ||
| 64 | |||
| 65 | |||
| 66 | } | ||
| 67 | |||
| 68 | |||
| 69 | |||
| 70 | ########################################################################### | ||
| 71 | # &B_is_package_installed($package); | ||
| 72 | # | ||
| 73 | # This function checks for the existence of the package named. | ||
| 74 | # | ||
| 75 | # TODO: Allow $package to be an expression. | ||
| 76 | # TODO: Allow optional $version, $release, $epoch arguments so we can | ||
| 77 | # make sure that the given package is at least as recent as some | ||
| 78 | # given version number. | ||
| 79 | # | ||
| 80 | # scalar return values: | ||
| 81 | # 0: $package is not installed | ||
| 82 | # 1: $package is installed | ||
| 83 | ########################################################################### | ||
| 84 | |||
| 85 | sub B_is_package_installed($) { | ||
| 86 | no strict; | ||
| 87 | my $package = $_[0]; | ||
| 88 | # Create a "global" variable with values scoped to this function | ||
| 89 | # We do this to avoid having to repeatedly swlist/rpm | ||
| 90 | # when we run B_is_package_installed | ||
| 91 | local %INSTALLED_PACKAGE_LIST; | ||
| 92 | |||
| 93 | my $distro = &GetDistro; | ||
| 94 | if ($distro =~ /^HP-UX/) { | ||
| 95 | if (&checkProcsForService('swagent','ignore_warning') == SECURE_CANT_CHANGE()) { | ||
| 96 | &B_log("WARNING","Software Distributor Agent(swagent) is not running. Can not tell ". | ||
| 97 | "if package: $package is installed or not. Bastille will assume not. ". | ||
| 98 | "If the package is actually installed, Bastille may report or configure incorrectly.". | ||
| 99 | "To use Bastille-results as-is, please check to ensure $package is not installed, ". | ||
| 100 | "or re-run with the swagent running to get correct results."); | ||
| 101 | return 0; #FALSE | ||
| 102 | } | ||
| 103 | my $swlist=&getGlobal('BIN','swlist'); | ||
| 104 | if (%INSTALLED_PACKAGE_LIST == () ) { # re-use prior results | ||
| 105 | if (open(SWLIST, "$swlist -a state -l fileset |")) { | ||
| 106 | while (my $line = <SWLIST>){ | ||
| 107 | if ($line =~ /^ {2}\S+\.(\S+)\s*(\w+)/) { | ||
| 108 | $INSTALLED_PACKAGE_LIST{$1} = $2; | ||
| 109 | } | ||
| 110 | } | ||
| 111 | close SWLIST; | ||
| 112 | } else { | ||
| 113 | &B_log("ERROR","B_is_package_installed was unable to run the swlist command: $swlist,\n"); | ||
| 114 | return FALSE; | ||
| 115 | } | ||
| 116 | } | ||
| 117 | # Now find the entry | ||
| 118 | if ($INSTALLED_PACKAGE_LIST{$package} == 'configured') { | ||
| 119 | return TRUE; | ||
| 120 | } else { | ||
| 121 | return FALSE; | ||
| 122 | } | ||
| 123 | } #End HP-UX Section | ||
| 124 | # This routine only works on RPM-based distros: Red Hat, Fedora, Mandrake and SuSE | ||
| 125 | elsif ( ($distro !~ /^RH/) and ($distro !~ /^MN/) and($distro !~ /^SE/) ) { | ||
| 126 | return 0; | ||
| 127 | } else { #This is a RPM-based distro | ||
| 128 | # Run an rpm command -- librpm is extremely messy, dynamic and not | ||
| 129 | # so much a perl thing. It's actually barely a C/C++ thing... | ||
| 130 | if (open RPM,"rpm -q $package") { | ||
| 131 | # We should get only one line back, but let's parse a few | ||
| 132 | # just in case. | ||
| 133 | my @lines = <RPM>; | ||
| 134 | close RPM; | ||
| 135 | # | ||
| 136 | # This is what we're trying to parse: | ||
| 137 | # $ rpm -q jay | ||
| 138 | # package jay is not installed | ||
| 139 | # $ rpm -q bash | ||
| 140 | # bash-2.05b-305.1 | ||
| 141 | # | ||
| 142 | |||
| 143 | foreach $line (@lines) { | ||
| 144 | if ($line =~ /^package\s$package\sis\snot\sinstalled/) { | ||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | elsif ($line =~ /^$package\-/) { | ||
| 148 | return 1; | ||
| 149 | } | ||
| 150 | } | ||
| 151 | |||
| 152 | # If we've read every line without finding one of these, then | ||
| 153 | # our parsing is broken | ||
| 154 | &B_log("ERROR","B_is_package_installed was unable to find a definitive RPM present or not present line.\n"); | ||
| 155 | return 0; | ||
| 156 | } else { | ||
| 157 | &B_log("ERROR","B_is_package_installed was unable to run the RPM command,\n"); | ||
| 158 | return 0; | ||
| 159 | } | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | |||
| 164 | |||
| 165 | 1; | ||
| 166 | |||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/ServiceAdmin.pm b/dynamic-layers/meta-perl/recipes-security/bastille/files/ServiceAdmin.pm new file mode 100644 index 0000000..879223a --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/ServiceAdmin.pm | |||
| @@ -0,0 +1,690 @@ | |||
| 1 | package Bastille::API::ServiceAdmin; | ||
| 2 | use strict; | ||
| 3 | |||
| 4 | use Bastille::API; | ||
| 5 | |||
| 6 | use Bastille::API::HPSpecific; | ||
| 7 | use Bastille::API::FileContent; | ||
| 8 | |||
| 9 | require Exporter; | ||
| 10 | our @ISA = qw(Exporter); | ||
| 11 | our @EXPORT_OK = qw( | ||
| 12 | B_chkconfig_on | ||
| 13 | B_chkconfig_off | ||
| 14 | B_service_start | ||
| 15 | B_service_stop | ||
| 16 | B_service_restart | ||
| 17 | B_is_service_off | ||
| 18 | checkServiceOnLinux | ||
| 19 | remoteServiceCheck | ||
| 20 | remoteNISPlusServiceCheck | ||
| 21 | B_create_nsswitch_file | ||
| 22 | ); | ||
| 23 | our @EXPORT = @EXPORT_OK; | ||
| 24 | |||
| 25 | |||
| 26 | ####### | ||
| 27 | # &B_chkconfig_on and &B_chkconfig_off() are great for systems that didn't use | ||
| 28 | # a more modern init system. This is a bit of a problem on Fedora, though, | ||
| 29 | # which used upstart from Fedora 9 to Fedora 14, then switched to a new | ||
| 30 | # Red Hat-created system called systemd for Fedora 15 and 16 (so far). | ||
| 31 | # OpenSUSE also moved to systemd, starting with 12.1. Version 11.4 did not | ||
| 32 | # use systemd. | ||
| 33 | # It is also a problem on Ubuntu, starting at version 6.10, where they also | ||
| 34 | # used upstart. | ||
| 35 | ##### | ||
| 36 | |||
| 37 | |||
| 38 | |||
| 39 | |||
| 40 | ########################################################################### | ||
| 41 | # &B_chkconfig_on ($daemon_name) creates the symbolic links that are | ||
| 42 | # named in the "# chkconfig: ___ _ _ " portion of the init.d files. We | ||
| 43 | # need this utility, in place of the distro's chkconfig, because of both | ||
| 44 | # our need to add revert functionality and our need to harden distros that | ||
| 45 | # are not mounted on /. | ||
| 46 | # | ||
| 47 | # It uses the following global variables to find the links and the init | ||
| 48 | # scripts, respectively: | ||
| 49 | # | ||
| 50 | # &getGlobal('DIR', "rcd") -- directory where the rc_.d subdirs can be found | ||
| 51 | # &getGlobal('DIR', "initd") -- directory the rc_.d directories link to | ||
| 52 | # | ||
| 53 | # Here an example of where you might use this: | ||
| 54 | # | ||
| 55 | # You'd like to tell the system to run the firewall at boot: | ||
| 56 | # B_chkconfig_on("bastille-firewall") | ||
| 57 | # | ||
| 58 | ########################################################################### | ||
| 59 | |||
| 60 | # PW: Blech. Copied B_chkconfig_off() and changed a few things, | ||
| 61 | # then changed a few more things.... | ||
| 62 | |||
| 63 | sub B_chkconfig_on { | ||
| 64 | |||
| 65 | my $startup_script=$_[0]; | ||
| 66 | my $retval=1; | ||
| 67 | |||
| 68 | my $chkconfig_line; | ||
| 69 | my ($runlevelinfo,@runlevels); | ||
| 70 | my ($start_order,$stop_order,$filetolink); | ||
| 71 | |||
| 72 | &B_log("ACTION","# chkconfig_on enabling $startup_script\n"); | ||
| 73 | |||
| 74 | # In Debian system there is no chkconfig script, run levels are checked | ||
| 75 | # one by one (jfs) | ||
| 76 | if (&GetDistro =~/^DB.*/) { | ||
| 77 | $filetolink = &getGlobal('DIR', "initd") . "/$startup_script"; | ||
| 78 | if (-x $filetolink) | ||
| 79 | { | ||
| 80 | foreach my $level ("0","1","2","3","4","5","6" ) { | ||
| 81 | my $link = ''; | ||
| 82 | $link = &getGlobal('DIR', "rcd") . "/rc" . "$level" . ".d/K50" . "$startup_script"; | ||
| 83 | $retval=symlink($filetolink,$link); | ||
| 84 | } | ||
| 85 | } | ||
| 86 | return $retval; | ||
| 87 | } | ||
| 88 | # | ||
| 89 | # On SUSE, chkconfig-based rc scripts have been replaced with a whole different | ||
| 90 | # system. chkconfig on SUSE is actually a shell script that does some stuff and then | ||
| 91 | # calls insserv, their replacement. | ||
| 92 | # | ||
| 93 | |||
| 94 | if (&GetDistro =~ /^SE/) { | ||
| 95 | # only try to chkconfig on if init script is found | ||
| 96 | if ( -e (&getGlobal('DIR', "initd") . "/$startup_script") ) { | ||
| 97 | $chkconfig_line=&getGlobal('BIN','chkconfig'); | ||
| 98 | &B_System("$chkconfig_line $startup_script on", "$chkconfig_line $startup_script off"); | ||
| 99 | # chkconfig doesn't take affect until reboot, need to restart service also | ||
| 100 | B_service_restart("$startup_script"); | ||
| 101 | return 1; #success | ||
| 102 | } | ||
| 103 | return 0; #failure | ||
| 104 | } | ||
| 105 | |||
| 106 | # | ||
| 107 | # Run through the init script looking for the chkconfig line... | ||
| 108 | # | ||
| 109 | $retval = open CHKCONFIG,&getGlobal('DIR', "initd") . "/$startup_script"; | ||
| 110 | unless ($retval) { | ||
| 111 | &B_log("ACTION","# Didn't chkconfig_on $startup_script because we couldn't open " . &getGlobal('DIR', "initd") . "/$startup_script\n"); | ||
| 112 | } | ||
| 113 | else { | ||
| 114 | |||
| 115 | READ_LOOP: | ||
| 116 | while (my $line=<CHKCONFIG>) { | ||
| 117 | |||
| 118 | # We're looking for lines like this one: | ||
| 119 | # # chkconfig: 2345 10 90 | ||
| 120 | # OR this | ||
| 121 | # # chkconfig: - 10 90 | ||
| 122 | |||
| 123 | if ($line =~ /^#\s*chkconfig:\s*([-\d]+)\s*(\d+)\s*(\d+)/ ) { | ||
| 124 | $runlevelinfo = $1; | ||
| 125 | $start_order = $2; | ||
| 126 | $stop_order = $3; | ||
| 127 | # handle a run levels arg of '-' | ||
| 128 | if ( $runlevelinfo eq '-' ) { | ||
| 129 | &B_log("ACTION","chkconfig_on saw '-' for run levels for \"$startup_script\", is defaulting to levels 3,4,5\n"); | ||
| 130 | $runlevelinfo = '345'; | ||
| 131 | } | ||
| 132 | @runlevels = split(//,$runlevelinfo); | ||
| 133 | # make sure the orders have 2 digits | ||
| 134 | $start_order =~ s/^(\d)$/0$1/; | ||
| 135 | $stop_order =~ s/^(\d)$/0$1/; | ||
| 136 | last READ_LOOP; | ||
| 137 | } | ||
| 138 | } | ||
| 139 | close CHKCONFIG; | ||
| 140 | |||
| 141 | # Do we have what we need? | ||
| 142 | if ( (scalar(@runlevels) < 1) || (! $start_order =~ /^\d{2}$/) || (! $stop_order =~ /^\d{2}$/) ) { | ||
| 143 | # problem | ||
| 144 | &B_log("ERROR","# B_chkconfig_on $startup_script failed -- no valid run level/start/stop info found\n"); | ||
| 145 | return(-1); | ||
| 146 | } | ||
| 147 | |||
| 148 | # Now, run through creating symlinks... | ||
| 149 | &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"); | ||
| 150 | |||
| 151 | $retval=0; | ||
| 152 | # BUG: we really ought to readdir() on &getGlobal('DIR', "rcd") to get all levels | ||
| 153 | foreach my $level ( "0","1","2","3","4","5","6" ) { | ||
| 154 | my $link = ''; | ||
| 155 | # we make K links in run levels not specified in the chkconfig line | ||
| 156 | $link = &getGlobal('DIR', "rcd") . "/rc" . $level . ".d/K$stop_order" . $startup_script; | ||
| 157 | my $klink = $link; | ||
| 158 | # now we see if this is a specified run level; if so, make an S link | ||
| 159 | foreach my $markedlevel ( @runlevels ) { | ||
| 160 | if ( $level == $markedlevel) { | ||
| 161 | $link = &getGlobal('DIR', "rcd") . "/rc" . $level . ".d/S$start_order" . $startup_script; | ||
| 162 | } | ||
| 163 | } | ||
| 164 | my $target = &getGlobal('DIR', "initd") ."/" . $startup_script; | ||
| 165 | my $local_return; | ||
| 166 | |||
| 167 | if ( (-e "$klink") && ($klink ne $link) ) { | ||
| 168 | # there's a K link, but this level needs an S link | ||
| 169 | unless ($GLOBAL_LOGONLY) { | ||
| 170 | $local_return = unlink("$klink"); | ||
| 171 | if ( ! $local_return ) { | ||
| 172 | # unlinking old, bad $klink failed | ||
| 173 | &B_log("ERROR","Unlinking $klink failed\n"); | ||
| 174 | } else { | ||
| 175 | &B_log("ACTION","Removed link $klink\n"); | ||
| 176 | # If we removed the link, add a link command to the revert file | ||
| 177 | &B_revert_log (&getGlobal('BIN','ln') . " -s $target $klink\n"); | ||
| 178 | } # close what to do if unlink works | ||
| 179 | } # if not GLOBAL_LOGONLY | ||
| 180 | } # if $klink exists and ne $link | ||
| 181 | |||
| 182 | # OK, we've disposed of any old K links, make what we need | ||
| 183 | if ( (! ( -e "$link" )) && ($link ne '') ) { | ||
| 184 | # link doesn't exist and the start/stop number is OK; make it | ||
| 185 | unless ($GLOBAL_LOGONLY) { | ||
| 186 | # create the link | ||
| 187 | $local_return = &B_symlink($target,$link); | ||
| 188 | if ($local_return) { | ||
| 189 | $retval++; | ||
| 190 | &B_log("ACTION","Created link $link\n"); | ||
| 191 | } else { | ||
| 192 | &B_log("ERROR","Couldn't create $link when trying to chkconfig on $startup_script\n"); | ||
| 193 | } | ||
| 194 | } | ||
| 195 | |||
| 196 | } # link doesn't exist | ||
| 197 | } # foreach level | ||
| 198 | |||
| 199 | } | ||
| 200 | |||
| 201 | if ($retval < @runlevels) { | ||
| 202 | $retval=0; | ||
| 203 | } | ||
| 204 | |||
| 205 | $retval; | ||
| 206 | |||
| 207 | } | ||
| 208 | |||
| 209 | |||
| 210 | ########################################################################### | ||
| 211 | # &B_chkconfig_off ($daemon_name) deletes the symbolic links that are | ||
| 212 | # named in the "# chkconfig: ___ _ _ " portion of the init.d files. We | ||
| 213 | # need this utility, in place of the distro's chkconfig, because of both | ||
| 214 | # our need to add revert functionality and our need to harden distros that | ||
| 215 | # are not mounted on /. | ||
| 216 | # | ||
| 217 | # chkconfig allows for a REVERT of its work by writing to an executable | ||
| 218 | # file &getGlobal('BFILE', "removed-symlinks"). | ||
| 219 | # | ||
| 220 | # It uses the following global variables to find the links and the init | ||
| 221 | # scripts, respectively: | ||
| 222 | # | ||
| 223 | # &getGlobal('DIR', "rcd") -- directory where the rc_.d subdirs can be found | ||
| 224 | # &getGlobal('DIR', "initd") -- directory the rc_.d directories link to | ||
| 225 | # | ||
| 226 | # Here an example of where you might use this: | ||
| 227 | # | ||
| 228 | # You'd like to tell stop running sendmail in daemon mode on boot: | ||
| 229 | # B_chkconfig_off("sendmail") | ||
| 230 | # | ||
| 231 | ########################################################################### | ||
| 232 | |||
| 233 | |||
| 234 | |||
| 235 | sub B_chkconfig_off { | ||
| 236 | |||
| 237 | my $startup_script=$_[0]; | ||
| 238 | my $retval=1; | ||
| 239 | |||
| 240 | my $chkconfig_line; | ||
| 241 | my @runlevels; | ||
| 242 | my ($start_order,$stop_order,$filetolink); | ||
| 243 | |||
| 244 | if (&GetDistro =~/^DB.*/) { | ||
| 245 | $filetolink = &getGlobal('DIR', "initd") . "/$startup_script"; | ||
| 246 | if (-x $filetolink) | ||
| 247 | { | ||
| 248 | # Three ways to do this in Debian: | ||
| 249 | # 1.- have the initd script set to 600 mode | ||
| 250 | # 2.- Remove the links in rcd (re-installing the package | ||
| 251 | # will break it) | ||
| 252 | # 3.- Use update-rc.d --remove (same as 2.) | ||
| 253 | # (jfs) | ||
| 254 | &B_chmod(0600,$filetolink); | ||
| 255 | $retval=6; | ||
| 256 | |||
| 257 | # The second option | ||
| 258 | #foreach my $level ("0","1","2","3","4","5","6" ) { | ||
| 259 | #my $link = ''; | ||
| 260 | #$link = &getGlobal('DIR', "rcd") . "/rc" . "$level" . ".d/K50" . "$startup_script"; | ||
| 261 | #unlink($link); | ||
| 262 | #} | ||
| 263 | } | ||
| 264 | } | ||
| 265 | |||
| 266 | # | ||
| 267 | # On SUSE, chkconfig-based rc scripts have been replaced with a whole different | ||
| 268 | # system. chkconfig on SUSE is actually a shell script that does some stuff and then | ||
| 269 | # calls insserv, their replacement. | ||
| 270 | # | ||
| 271 | elsif (&GetDistro =~ /^SE/) { | ||
| 272 | # only try to chkconfig off if init script is found | ||
| 273 | if ( -e (&getGlobal('DIR', "initd") . "/$startup_script") ) { | ||
| 274 | $chkconfig_line=&getGlobal('BIN','chkconfig'); | ||
| 275 | &B_System("$chkconfig_line $startup_script on", "$chkconfig_line $startup_script off"); | ||
| 276 | # chkconfig doesn't take affect until reboot, need to stop service | ||
| 277 | # since expectation is that the daemons are disabled even without a reboot | ||
| 278 | B_service_stop("$startup_script"); | ||
| 279 | return 1; #success | ||
| 280 | } | ||
| 281 | return 0; #failure | ||
| 282 | } | ||
| 283 | else { | ||
| 284 | |||
| 285 | # Run through the init script looking for the chkconfig line... | ||
| 286 | |||
| 287 | |||
| 288 | $retval = open CHKCONFIG,&getGlobal('DIR', "initd") . "/$startup_script"; | ||
| 289 | unless ($retval) { | ||
| 290 | &B_log("ACTION","Didn't chkconfig_off $startup_script because we couldn't open " . &getGlobal('DIR', "initd") . "/$startup_script\n"); | ||
| 291 | } | ||
| 292 | else { | ||
| 293 | |||
| 294 | READ_LOOP: | ||
| 295 | while (my $line=<CHKCONFIG>) { | ||
| 296 | |||
| 297 | # We're looking for lines like this one: | ||
| 298 | # # chkconfig: 2345 10 90 | ||
| 299 | |||
| 300 | if ($line =~ /^#\s*chkconfig:\s*([-\d]+)\s*(\d+)\s*(\d+)/ ) { | ||
| 301 | @runlevels=split //,$1; | ||
| 302 | $start_order=$2; | ||
| 303 | $stop_order=$3; | ||
| 304 | |||
| 305 | |||
| 306 | # Change single digit run levels to double digit -- otherwise, | ||
| 307 | # the alphabetic ordering chkconfig depends on fails. | ||
| 308 | if ($start_order =~ /^\d$/ ) { | ||
| 309 | $start_order = "0" . $start_order; | ||
| 310 | &B_log("ACTION","chkconfig_off converted start order to $start_order\n"); | ||
| 311 | } | ||
| 312 | if ($stop_order =~ /^\d$/ ) { | ||
| 313 | $stop_order = "0" . $stop_order; | ||
| 314 | &B_log("ACTION","chkconfig_off converted stop order to $stop_order\n"); | ||
| 315 | } | ||
| 316 | |||
| 317 | last READ_LOOP; | ||
| 318 | } | ||
| 319 | } | ||
| 320 | close CHKCONFIG; | ||
| 321 | |||
| 322 | # If we never found a chkconfig line, can we just run through all 5 | ||
| 323 | # rcX.d dirs from 1 to 5...? | ||
| 324 | |||
| 325 | # unless ( $start_order and $stop_order ) { | ||
| 326 | # @runlevels=("1","2","3","4","5"); | ||
| 327 | # $start_order = "*"; $stop_order="*"; | ||
| 328 | # } | ||
| 329 | |||
| 330 | # Now, run through removing symlinks... | ||
| 331 | |||
| 332 | |||
| 333 | |||
| 334 | $retval=0; | ||
| 335 | |||
| 336 | # Handle the special case that the run level specified is solely "-" | ||
| 337 | if ($runlevels[0] =~ /-/) { | ||
| 338 | @runlevels = ( "0","1","2","3","4","5","6" ); | ||
| 339 | } | ||
| 340 | |||
| 341 | foreach my $level ( @runlevels ) { | ||
| 342 | my $link = &getGlobal('DIR', "rcd") . "/rc" . $level . ".d/S$start_order" . $startup_script; | ||
| 343 | my $new_link = &getGlobal('DIR', "rcd") . "/rc" . $level . ".d/K$stop_order" . $startup_script; | ||
| 344 | my $target = &getGlobal('DIR', "initd") ."/" . $startup_script; | ||
| 345 | my $local_return; | ||
| 346 | |||
| 347 | |||
| 348 | # Replace the S__ link in this level with a K__ link. | ||
| 349 | if ( -e $link ) { | ||
| 350 | unless ($GLOBAL_LOGONLY) { | ||
| 351 | $local_return=unlink $link; | ||
| 352 | if ($local_return) { | ||
| 353 | $local_return=symlink $target,$new_link; | ||
| 354 | unless ($local_return) { | ||
| 355 | &B_log("ERROR","Linking $target to $new_link failed.\n"); | ||
| 356 | } | ||
| 357 | } | ||
| 358 | else { # unlinking failed | ||
| 359 | &B_log("ERROR","Unlinking $link failed\n"); | ||
| 360 | } | ||
| 361 | |||
| 362 | } | ||
| 363 | if ($local_return) { | ||
| 364 | $retval++; | ||
| 365 | &B_log("ACTION","Removed link $link\n"); | ||
| 366 | |||
| 367 | # | ||
| 368 | # If we removed the link, add a link command to the revert file | ||
| 369 | # Write out the revert information for recreating the S__ | ||
| 370 | # symlink and deleting the K__ symlink. | ||
| 371 | &B_revert_log(&getGlobal('BIN',"ln") . " -s $target $link\n"); | ||
| 372 | &B_revert_log(&getGlobal('BIN',"rm") . " -f $new_link\n"); | ||
| 373 | } | ||
| 374 | else { | ||
| 375 | &B_log("ERROR","B_chkconfig_off $startup_script failed\n"); | ||
| 376 | } | ||
| 377 | |||
| 378 | } | ||
| 379 | } # foreach | ||
| 380 | |||
| 381 | } # else-unless | ||
| 382 | |||
| 383 | } # else-DB | ||
| 384 | if ($retval < @runlevels) { | ||
| 385 | $retval=0; | ||
| 386 | } | ||
| 387 | |||
| 388 | $retval; | ||
| 389 | |||
| 390 | } | ||
| 391 | |||
| 392 | |||
| 393 | ########################################################################### | ||
| 394 | # &B_service_start ($daemon_name) | ||
| 395 | # Starts service on RedHat/SUSE-based Linux distributions which have the | ||
| 396 | # service command: | ||
| 397 | # | ||
| 398 | # service $daemon_name start | ||
| 399 | # | ||
| 400 | # Other Linux distros that also support this method of starting | ||
| 401 | # services can be added to use this function. | ||
| 402 | # | ||
| 403 | # Here an example of where you might use this: | ||
| 404 | # | ||
| 405 | # You'd like to tell the system to start the vsftpd daemon: | ||
| 406 | # &B_service_start("vsftpd") | ||
| 407 | # | ||
| 408 | # Uses &B_System in HP_API.pm | ||
| 409 | # To match how the &B_System command works this method: | ||
| 410 | # returns 1 on success | ||
| 411 | # returns 0 on failure | ||
| 412 | ########################################################################### | ||
| 413 | |||
| 414 | sub B_service_start { | ||
| 415 | |||
| 416 | my $daemon=$_[0]; | ||
| 417 | |||
| 418 | if ( (&GetDistro !~ /^SE/) and (&GetDistro !~ /^RH/) and | ||
| 419 | (&GetDistro !~ /^RHFC/) and (&GetDistro !~ /^MN/) ) { | ||
| 420 | &B_log("ERROR","Tried to call service_start on a system lacking a service command! Internal Bastille error."); | ||
| 421 | return undef; | ||
| 422 | } | ||
| 423 | |||
| 424 | # only start service if init script is found | ||
| 425 | if ( -e (&getGlobal('DIR', 'initd') . "/$daemon") ) { | ||
| 426 | &B_log("ACTION","# service_start enabling $daemon\n"); | ||
| 427 | |||
| 428 | my $service_cmd=&getGlobal('BIN', 'service'); | ||
| 429 | if ($service_cmd) { | ||
| 430 | # Start the service, | ||
| 431 | # Also provide &B_System revert command | ||
| 432 | |||
| 433 | return (&B_System("$service_cmd $daemon start", | ||
| 434 | "$service_cmd $daemon stop")); | ||
| 435 | } | ||
| 436 | } | ||
| 437 | |||
| 438 | # init script not found, do not try to start, return failure | ||
| 439 | return 0; | ||
| 440 | } | ||
| 441 | |||
| 442 | ########################################################################### | ||
| 443 | # &B_service_stop ($daemon_name) | ||
| 444 | # Stops service on RedHat/SUSE-based Linux distributions which have the | ||
| 445 | # service command: | ||
| 446 | # | ||
| 447 | # service $daemon_name stop | ||
| 448 | # | ||
| 449 | # Other Linux distros that also support this method of starting | ||
| 450 | # services can be added to use this function. | ||
| 451 | # Stops service. | ||
| 452 | # | ||
| 453 | # | ||
| 454 | # Here an example of where you might use this: | ||
| 455 | # | ||
| 456 | # You'd like to tell the system to stop the vsftpd daemon: | ||
| 457 | # &B_service_stop("vsftpd") | ||
| 458 | # | ||
| 459 | # Uses &B_System in HP_API.pm | ||
| 460 | # To match how the &B_System command works this method: | ||
| 461 | # returns 1 on success | ||
| 462 | # returns 0 on failure | ||
| 463 | ########################################################################### | ||
| 464 | |||
| 465 | sub B_service_stop { | ||
| 466 | |||
| 467 | my $daemon=$_[0]; | ||
| 468 | |||
| 469 | if ( (&GetDistro !~ /^SE/) and (&GetDistro !~ /^RH/) and | ||
| 470 | (&GetDistro !~ /^RHFC/) and (&GetDistro !~ /^MN/) ) { | ||
| 471 | &B_log("ERROR","Tried to call service_stop on a system lacking a service command! Internal Bastille error."); | ||
| 472 | return undef; | ||
| 473 | } | ||
| 474 | |||
| 475 | # only stop service if init script is found | ||
| 476 | if ( -e (&getGlobal('DIR', 'initd') . "/$daemon") ) { | ||
| 477 | &B_log("ACTION","# service_stop disabling $daemon\n"); | ||
| 478 | |||
| 479 | my $service_cmd=&getGlobal('BIN', 'service'); | ||
| 480 | if ($service_cmd) { | ||
| 481 | |||
| 482 | # Stop the service, | ||
| 483 | # Also provide &B_System revert command | ||
| 484 | |||
| 485 | return (&B_System("$service_cmd $daemon stop", | ||
| 486 | "$service_cmd $daemon start")); | ||
| 487 | } | ||
| 488 | } | ||
| 489 | |||
| 490 | # init script not found, do not try to stop, return failure | ||
| 491 | return 0; | ||
| 492 | } | ||
| 493 | |||
| 494 | |||
| 495 | ########################################################################### | ||
| 496 | # &B_service_restart ($daemon_name) | ||
| 497 | # Restarts service on RedHat/SUSE-based Linux distributions which have the | ||
| 498 | # service command: | ||
| 499 | # | ||
| 500 | # service $daemon_name restart | ||
| 501 | # | ||
| 502 | # Other Linux distros that also support this method of starting | ||
| 503 | # services can be added to use this function. | ||
| 504 | # | ||
| 505 | # Here an example of where you might use this: | ||
| 506 | # | ||
| 507 | # You'd like to tell the system to restart the vsftpd daemon: | ||
| 508 | # &B_service_restart("vsftpd") | ||
| 509 | # | ||
| 510 | # Uses &B_System in HP_API.pm | ||
| 511 | # To match how the &B_System command works this method: | ||
| 512 | # returns 1 on success | ||
| 513 | # returns 0 on failure | ||
| 514 | ########################################################################### | ||
| 515 | |||
| 516 | sub B_service_restart { | ||
| 517 | |||
| 518 | my $daemon=$_[0]; | ||
| 519 | |||
| 520 | if ( (&GetDistro !~ /^SE/) and (&GetDistro !~ /^RH/) and | ||
| 521 | (&GetDistro !~ /^RHFC/) and (&GetDistro !~ /^MN/) ) { | ||
| 522 | &B_log("ERROR","Tried to call service_restart on a system lacking a service command! Internal Bastille error."); | ||
| 523 | return undef; | ||
| 524 | } | ||
| 525 | |||
| 526 | # only restart service if init script is found | ||
| 527 | if ( -e (&getGlobal('DIR', 'initd') . "/$daemon") ) { | ||
| 528 | &B_log("ACTION","# service_restart re-enabling $daemon\n"); | ||
| 529 | |||
| 530 | my $service_cmd=&getGlobal('BIN', 'service'); | ||
| 531 | if ($service_cmd) { | ||
| 532 | |||
| 533 | # Restart the service | ||
| 534 | return (&B_System("$service_cmd $daemon restart", | ||
| 535 | "$service_cmd $daemon restart")); | ||
| 536 | } | ||
| 537 | } | ||
| 538 | |||
| 539 | # init script not found, do not try to restart, return failure | ||
| 540 | return 0; | ||
| 541 | } | ||
| 542 | |||
| 543 | ########################################################################### | ||
| 544 | # &B_is_service_off($;$) | ||
| 545 | # | ||
| 546 | # Runs the specified test to determine whether or not the question should | ||
| 547 | # be answered. | ||
| 548 | # | ||
| 549 | # return values: | ||
| 550 | # NOTSECURE_CAN_CHANGE()/0: service is on | ||
| 551 | # SECURE_CANT_CHANGE()/1: service is off | ||
| 552 | # undef: test is not defined | ||
| 553 | ########################################################################### | ||
| 554 | |||
| 555 | sub B_is_service_off ($){ | ||
| 556 | my $service=$_[0]; | ||
| 557 | |||
| 558 | if(&GetDistro =~ "^HP-UX"){ | ||
| 559 | #die "Why do I think I'm on HPUX?!\n"; | ||
| 560 | return &checkServiceOnHPUX($service); | ||
| 561 | } | ||
| 562 | elsif ( (&GetDistro =~ "^RH") || (&GetDistro =~ "^SE") ) { | ||
| 563 | return &checkServiceOnLinux($service); | ||
| 564 | } | ||
| 565 | else { | ||
| 566 | &B_log("DEBUG","B_is_service off called for unsupported OS"); | ||
| 567 | # not yet implemented for other distributions of Linux | ||
| 568 | # when GLOBAL_SERVICE, GLOBAL_SERVTYPE and GLOBAL_PROCESS are filled | ||
| 569 | # in for Linux, then | ||
| 570 | # at least inetd and inittab services should be similar to the above, | ||
| 571 | # whereas chkconfig would be used on some Linux distros to determine | ||
| 572 | # if non-inetd/inittab services are running at boot time. Looking at | ||
| 573 | # processes should be similar. | ||
| 574 | return undef; | ||
| 575 | } | ||
| 576 | } | ||
| 577 | |||
| 578 | ########################################################################### | ||
| 579 | # &checkServiceOnLinux($service); | ||
| 580 | # | ||
| 581 | # Checks if the given service is running on a Linux system. This is | ||
| 582 | # called by B_is_Service_Off(), which is the function that Bastille | ||
| 583 | # modules should call. | ||
| 584 | # | ||
| 585 | # Return values: | ||
| 586 | # NOTSECURE_CAN_CHANGE() if the service is on | ||
| 587 | # SECURE_CANT_CHANGE() if the service is off | ||
| 588 | # undef if the state of the service cannot be determined | ||
| 589 | # | ||
| 590 | ########################################################################### | ||
| 591 | sub checkServiceOnLinux($) { | ||
| 592 | my $service=$_[0]; | ||
| 593 | |||
| 594 | # get the list of parameters which could be used to initiate the service | ||
| 595 | # (could be in /etc/rc.d/rc?.d, /etc/inetd.conf, or /etc/inittab, so we | ||
| 596 | # check all of them) | ||
| 597 | |||
| 598 | my @params = @{ &getGlobal('SERVICE', $service) }; | ||
| 599 | my $chkconfig = &getGlobal('BIN', 'chkconfig'); | ||
| 600 | my $grep = &getGlobal('BIN', 'grep'); | ||
| 601 | my $inittab = &getGlobal('FILE', 'inittab'); | ||
| 602 | my $serviceType = &getGlobal('SERVTYPE', $service);; | ||
| 603 | |||
| 604 | # A kludge to get things running because &getGlobal('SERVICE' doesn't | ||
| 605 | # return the expected values. | ||
| 606 | @params = (); | ||
| 607 | push (@params, $service); | ||
| 608 | |||
| 609 | foreach my $param (@params) { | ||
| 610 | &B_log("DEBUG","Checking to see if service $service is off.\n"); | ||
| 611 | |||
| 612 | if ($serviceType =~ /rc/) { | ||
| 613 | my $on = &B_Backtick("$chkconfig --list $param 2>&1"); | ||
| 614 | if ($on =~ /^$param:\s+unknown/) { | ||
| 615 | # This service isn't installed on the system | ||
| 616 | return NOT_INSTALLED(); | ||
| 617 | } | ||
| 618 | if ($on =~ /^error reading information on service $param: No such file or directory/) { | ||
| 619 | # This service isn't installed on the system | ||
| 620 | return NOT_INSTALLED(); | ||
| 621 | } | ||
| 622 | if ($on =~ /^error/) { | ||
| 623 | # This probably | ||
| 624 | &B_log("DEBUG","chkconfig returned: $param=$on\n"); | ||
| 625 | return undef; | ||
| 626 | } | ||
| 627 | $on =~ s/^$param\s+//; # remove the service name and spaces | ||
| 628 | $on =~ s/[0-6]:off\s*//g; # remove any runlevel:off entries | ||
| 629 | $on =~ s/:on\s*//g; # remove the :on from the runlevels | ||
| 630 | # what remains is a list of runlevels in which the service is on, | ||
| 631 | # or a null string if it is never turned on | ||
| 632 | chomp $on; # newline should be gone already (\s) | ||
| 633 | &B_log("DEBUG","chkconfig returned: $param=$on\n"); | ||
| 634 | |||
| 635 | if ($on =~ /^\d+$/) { | ||
| 636 | # service is not off | ||
| 637 | ########################### BREAK out, don't skip question | ||
| 638 | return NOTSECURE_CAN_CHANGE(); | ||
| 639 | } | ||
| 640 | } | ||
| 641 | elsif ($serviceType =~ /inet/) { | ||
| 642 | my $on = &B_Backtick("$chkconfig --list $param 2>&1"); | ||
| 643 | if ($on =~ /^$param:\s+unknown/) { | ||
| 644 | # This service isn't installed on the system | ||
| 645 | return NOT_INSTALLED(); | ||
| 646 | } | ||
| 647 | if ($on =~ /^error reading information on service $param: No such file or directory/) { | ||
| 648 | # This service isn't installed on the system | ||
| 649 | return NOT_INSTALLED(); | ||
| 650 | } | ||
| 651 | if ($on =~ /^error/ ) { | ||
| 652 | # Something else is wrong? | ||
| 653 | # return undef | ||
| 654 | return undef; | ||
| 655 | } | ||
| 656 | if ($on =~ tr/\n// > 1) { | ||
| 657 | $on =~ s/^xinetd.+\n//; | ||
| 658 | } | ||
| 659 | $on =~ s/^\s*$param:?\s+//; # remove the service name and spaces | ||
| 660 | chomp $on; # newline should be gone already (\s) | ||
| 661 | &B_log("DEBUG","chkconfig returned: $param=$on\n"); | ||
| 662 | |||
| 663 | if ($on =~ /^on$/) { | ||
| 664 | # service is not off | ||
| 665 | ########################### BREAK out, don't skip question | ||
| 666 | return NOTSECURE_CAN_CHANGE(); | ||
| 667 | } | ||
| 668 | } | ||
| 669 | else { | ||
| 670 | # perhaps the service is started by inittab | ||
| 671 | my $inittabline = &B_Backtick("$grep -E '^[^#].{0,3}:.*:.+:.*$param' $inittab"); | ||
| 672 | if ($inittabline =~ /.+/) { # . matches anything except newlines | ||
| 673 | # service is not off | ||
| 674 | &B_log("DEBUG","Checking inittab; found $inittabline\n"); | ||
| 675 | ########################### BREAK out, don't skip question | ||
| 676 | return NOTSECURE_CAN_CHANGE(); | ||
| 677 | } | ||
| 678 | } | ||
| 679 | } # foreach my $param | ||
| 680 | |||
| 681 | |||
| 682 | # boot-time parameters are not set; check processes | ||
| 683 | # Note the checkProcsforService returns INCONSISTENT() if a process is found | ||
| 684 | # assuming the checks above | ||
| 685 | return &checkProcsForService($service); | ||
| 686 | } | ||
| 687 | |||
| 688 | 1; | ||
| 689 | |||
| 690 | |||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/accept_os_flag_in_backend.patch b/dynamic-layers/meta-perl/recipes-security/bastille/files/accept_os_flag_in_backend.patch new file mode 100644 index 0000000..4a438e4 --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/accept_os_flag_in_backend.patch | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | Upstream Status: Inappropriate [No upstream maintenance] | ||
| 2 | |||
| 3 | Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> | ||
| 4 | |||
| 5 | --- | ||
| 6 | |||
| 7 | Index: Bastille/BastilleBackEnd | ||
| 8 | =================================================================== | ||
| 9 | --- Bastille.orig/BastilleBackEnd 2013-08-21 12:40:54.000000000 -0400 | ||
| 10 | +++ Bastille/BastilleBackEnd 2013-08-21 12:43:21.895950001 -0400 | ||
| 11 | @@ -52,11 +52,13 @@ | ||
| 12 | my $force = 0; | ||
| 13 | my $debug = 0; | ||
| 14 | my $alternate_config=undef; | ||
| 15 | +my $os_version=undef; | ||
| 16 | |||
| 17 | if( Getopt::Long::GetOptions( "n" => \$nodisclaim, | ||
| 18 | "v" => \$verbose, | ||
| 19 | "force" => \$force, | ||
| 20 | "f=s" => \$alternate_config, | ||
| 21 | + "os=s" => \$os_version, | ||
| 22 | "debug" => \$debug) ) { | ||
| 23 | $error = 0; # no parse error | ||
| 24 | |||
| 25 | @@ -66,7 +68,8 @@ | ||
| 26 | |||
| 27 | &setOptions( | ||
| 28 | debug => $debug, | ||
| 29 | - verbose => $verbose); | ||
| 30 | + verbose => $verbose, | ||
| 31 | + os => $os_version); | ||
| 32 | &ConfigureForDistro; | ||
| 33 | |||
| 34 | if ( $error ) { # GetOptions couldn't parse all of the args | ||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/allow_os_with_assess.patch b/dynamic-layers/meta-perl/recipes-security/bastille/files/allow_os_with_assess.patch new file mode 100644 index 0000000..e112f90 --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/allow_os_with_assess.patch | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | Upstream Status: Inappropriate [No upstream maintenance] | ||
| 2 | |||
| 3 | Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> | ||
| 4 | |||
| 5 | --- | ||
| 6 | |||
| 7 | Index: Bastille/bin/bastille | ||
| 8 | =================================================================== | ||
| 9 | --- Bastille.orig/bin/bastille 2013-08-21 08:59:06.647950000 -0400 | ||
| 10 | +++ Bastille/bin/bastille 2013-08-21 15:55:53.193631711 -0400 | ||
| 11 | @@ -195,7 +195,6 @@ | ||
| 12 | systemFileLocations | ||
| 13 | |||
| 14 | isAssessing='no' | ||
| 15 | -nonXArg='no' | ||
| 16 | |||
| 17 | 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 | ||
| 18 | printErr | ||
| 19 | @@ -316,12 +315,10 @@ | ||
| 20 | '--os') | ||
| 21 | options_left="$options_left --os" | ||
| 22 | optarg='yes' | ||
| 23 | - nonXArg='yes' | ||
| 24 | ;; | ||
| 25 | '-f') | ||
| 26 | options_left="$options_left -f" | ||
| 27 | optarg='yes' | ||
| 28 | - nonXArg='yes' | ||
| 29 | ;; | ||
| 30 | # Non-exclusive (undocumented and unsupported) options follow: | ||
| 31 | # There is no validity/combination checking done with these. | ||
| 32 | @@ -345,11 +342,6 @@ | ||
| 33 | fi | ||
| 34 | done | ||
| 35 | |||
| 36 | -#Detect case where -f or --os attempted use with --assess | ||
| 37 | - if [ \( x$nonXArg = xyes \) -a \( x$isAssessing = xyes \) ]; then | ||
| 38 | - printUsage | ||
| 39 | - exit 2 | ||
| 40 | - fi | ||
| 41 | |||
| 42 | # We have a valid version of perl! Verify that all the required | ||
| 43 | # modules can be found. | ||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/call_output_config.patch b/dynamic-layers/meta-perl/recipes-security/bastille/files/call_output_config.patch new file mode 100644 index 0000000..1e898b1 --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/call_output_config.patch | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | Upstream Status: Inappropriate [No upstream maintenance] | ||
| 2 | |||
| 3 | Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> | ||
| 4 | |||
| 5 | --- | ||
| 6 | |||
| 7 | Index: Bastille/Bastille_Curses.pm | ||
| 8 | =================================================================== | ||
| 9 | --- Bastille.orig/Bastille_Curses.pm 2013-08-21 08:58:53.899950000 -0400 | ||
| 10 | +++ Bastille/Bastille_Curses.pm 2013-08-21 09:20:20.295950005 -0400 | ||
| 11 | @@ -84,7 +84,7 @@ | ||
| 12 | } | ||
| 13 | |||
| 14 | # Output answers to the script and display | ||
| 15 | - &checkAndSaveConfig(&getGlobal('BFILE', "config")); | ||
| 16 | + &outputConfig; | ||
| 17 | |||
| 18 | # Run Bastille | ||
| 19 | |||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/config b/dynamic-layers/meta-perl/recipes-security/bastille/files/config new file mode 100755 index 0000000..9e5e206 --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/config | |||
| @@ -0,0 +1,106 @@ | |||
| 1 | # Q: Would you like to enforce password aging? [Y] | ||
| 2 | AccountSecurity.passwdage="Y" | ||
| 3 | # Q: Should Bastille disable clear-text r-protocols that use IP-based authentication? [Y] | ||
| 4 | AccountSecurity.protectrhost="Y" | ||
| 5 | # Q: Should we disallow root login on tty's 1-6? [N] | ||
| 6 | AccountSecurity.rootttylogins="Y" | ||
| 7 | # Q: What umask would you like to set for users on the system? [077] | ||
| 8 | AccountSecurity.umask="077" | ||
| 9 | # Q: Do you want to set the default umask? [Y] | ||
| 10 | AccountSecurity.umaskyn="Y" | ||
| 11 | # Q: Would you like to deactivate the Apache web server? [Y] | ||
| 12 | Apache.apacheoff="Y" | ||
| 13 | # Q: Would you like to password protect single-user mode? [Y] | ||
| 14 | BootSecurity.passsum="Y" | ||
| 15 | # Q: Should we restrict console access to a small group of user accounts? [N] | ||
| 16 | ConfigureMiscPAM.consolelogin="Y" | ||
| 17 | # Q: Which accounts should be able to login at console? [root] | ||
| 18 | ConfigureMiscPAM.consolelogin_accounts="root" | ||
| 19 | # Q: Would you like to put limits on system resource usage? [N] | ||
| 20 | ConfigureMiscPAM.limitsconf="Y" | ||
| 21 | # Q: Would you like to set more restrictive permissions on the administration utilities? [N] | ||
| 22 | FilePermissions.generalperms_1_1="Y" | ||
| 23 | # Q: Would you like to disable SUID status for mount/umount? | ||
| 24 | FilePermissions.suidmount="Y" | ||
| 25 | # Q: Would you like to disable SUID status for ping? [Y] | ||
| 26 | FilePermissions.suidping="Y" | ||
| 27 | # Q: Would you like to disable SUID status for traceroute? [Y] | ||
| 28 | FilePermissions.suidtrace="Y" | ||
| 29 | # Q: Do you need the advanced networking options? | ||
| 30 | Firewall.ip_advnetwork="Y" | ||
| 31 | # Q: Should Bastille run the firewall and enable it at boot time? [N] | ||
| 32 | Firewall.ip_enable_firewall="Y" | ||
| 33 | # Q: Would you like to run the packet filtering script? [N] | ||
| 34 | Firewall.ip_intro="Y" | ||
| 35 | # Q: Interfaces for DHCP queries: [ ] | ||
| 36 | Firewall.ip_s_dhcpiface=" " | ||
| 37 | # Q: DNS servers: [0.0.0.0/0] | ||
| 38 | Firewall.ip_s_dns="10.184.9.1" | ||
| 39 | # Q: ICMP allowed types: [destination-unreachable echo-reply time-exceeded] | ||
| 40 | Firewall.ip_s_icmpallowed="destination-unreachable echo-reply time-exceeded" | ||
| 41 | # Q: ICMP services to audit: [ ] | ||
| 42 | Firewall.ip_s_icmpaudit=" " | ||
| 43 | # Q: ICMP types to disallow outbound: [destination-unreachable time-exceeded] | ||
| 44 | Firewall.ip_s_icmpout="destination-unreachable time-exceeded" | ||
| 45 | # Q: Internal interfaces: [ ] | ||
| 46 | Firewall.ip_s_internaliface=" " | ||
| 47 | # Q: TCP service names or port numbers to allow on private interfaces: [ ] | ||
| 48 | Firewall.ip_s_internaltcp=" " | ||
| 49 | # Q: UDP service names or port numbers to allow on private interfaces: [ ] | ||
| 50 | Firewall.ip_s_internaludp=" " | ||
| 51 | # Q: Masqueraded networks: [ ] | ||
| 52 | Firewall.ip_s_ipmasq=" " | ||
| 53 | # Q: Kernel modules to masquerade: [ftp raudio vdolive] | ||
| 54 | Firewall.ip_s_kernelmasq="ftp raudio vdolive" | ||
| 55 | # Q: NTP servers to query: [ ] | ||
| 56 | Firewall.ip_s_ntpsrv=" " | ||
| 57 | # Q: Force passive mode? [N] | ||
| 58 | Firewall.ip_s_passiveftp="N" | ||
| 59 | # Q: Public interfaces: [eth+ ppp+ slip+] | ||
| 60 | Firewall.ip_s_publiciface="eth+ ppp+ slip+" | ||
| 61 | # Q: TCP service names or port numbers to allow on public interfaces:[ ] | ||
| 62 | Firewall.ip_s_publictcp=" " | ||
| 63 | # Q: UDP service names or port numbers to allow on public interfaces:[ ] | ||
| 64 | Firewall.ip_s_publicudp=" " | ||
| 65 | # Q: Reject method: [DENY] | ||
| 66 | Firewall.ip_s_rejectmethod="DENY" | ||
| 67 | # Q: Enable source address verification? [Y] | ||
| 68 | Firewall.ip_s_srcaddr="Y" | ||
| 69 | # Q: TCP services to audit: [telnet ftp imap pop3 finger sunrpc exec login linuxconf ssh] | ||
| 70 | Firewall.ip_s_tcpaudit="telnet ftp imap pop3 finger sunrpc exec login linuxconf ssh" | ||
| 71 | # Q: TCP services to block: [2049 2065:2090 6000:6020 7100] | ||
| 72 | Firewall.ip_s_tcpblock="2049 2065:2090 6000:6020 7100" | ||
| 73 | # Q: Trusted interface names: [lo] | ||
| 74 | Firewall.ip_s_trustiface="lo" | ||
| 75 | # Q: UDP services to audit: [31337] | ||
| 76 | Firewall.ip_s_udpaudit="31337" | ||
| 77 | # Q: UDP services to block: [2049 6770] | ||
| 78 | Firewall.ip_s_udpblock="2049 6770" | ||
| 79 | # Q: Would you like to add additional logging? [Y] | ||
| 80 | Logging.morelogging="Y" | ||
| 81 | # Q: Would you like to set up process accounting? [N] | ||
| 82 | Logging.pacct="N" | ||
| 83 | # Q: Do you have a remote logging host? [N] | ||
| 84 | Logging.remotelog="N" | ||
| 85 | # Q: Would you like to disable acpid and/or apmd? [Y] | ||
| 86 | MiscellaneousDaemons.apmd="Y" | ||
| 87 | # Q: Would you like to deactivate NFS and Samba? [Y] | ||
| 88 | MiscellaneousDaemons.remotefs="Y" | ||
| 89 | # Q: Would you like to disable printing? [N] | ||
| 90 | Printing.printing="Y" | ||
| 91 | # Q: Would you like to disable printing? [N] | ||
| 92 | Printing.printing_cups="Y" | ||
| 93 | # Q: Would you like to display "Authorized Use" messages at log-in time? [Y] | ||
| 94 | SecureInetd.banners="Y" | ||
| 95 | # Q: Should Bastille ensure inetd's FTP service does not run on this system? [y] | ||
| 96 | SecureInetd.deactivate_ftp="Y" | ||
| 97 | # Q: Should Bastille ensure the telnet service does not run on this system? [y] | ||
| 98 | SecureInetd.deactivate_telnet="Y" | ||
| 99 | # Q: Who is responsible for granting authorization to use this machine? | ||
| 100 | SecureInetd.owner="its owner" | ||
| 101 | # Q: Would you like to set a default-deny on TCP Wrappers and xinetd? [N] | ||
| 102 | SecureInetd.tcpd_default_deny="Y" | ||
| 103 | # Q: Do you want to stop sendmail from running in daemon mode? [Y] | ||
| 104 | Sendmail.sendmaildaemon="Y" | ||
| 105 | # Q: Would you like to install TMPDIR/TMP scripts? [N] | ||
| 106 | TMPDIR.tmpdir="N" | ||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/do_not_apply_config.patch b/dynamic-layers/meta-perl/recipes-security/bastille/files/do_not_apply_config.patch new file mode 100644 index 0000000..574aa98 --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/do_not_apply_config.patch | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | Upstream Status: Inappropriate [No upstream maintenance] | ||
| 2 | |||
| 3 | Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> | ||
| 4 | |||
| 5 | --- | ||
| 6 | |||
| 7 | Index: Bastille/Bastille_Curses.pm | ||
| 8 | =================================================================== | ||
| 9 | --- Bastille.orig/Bastille_Curses.pm 2013-08-27 16:43:39.130959000 -0400 | ||
| 10 | +++ Bastille/Bastille_Curses.pm 2013-08-27 16:43:39.794959000 -0400 | ||
| 11 | @@ -83,11 +83,6 @@ | ||
| 12 | # Output answers to the script and display | ||
| 13 | &outputConfig; | ||
| 14 | |||
| 15 | - # Run Bastille | ||
| 16 | - | ||
| 17 | - &Run_Bastille_with_Config; | ||
| 18 | - | ||
| 19 | - | ||
| 20 | # Display Credits | ||
| 21 | |||
| 22 | open CREDITS,"/usr/share/Bastille/Credits"; | ||
| 23 | Index: Bastille/InteractiveBastille | ||
| 24 | =================================================================== | ||
| 25 | --- Bastille.orig/InteractiveBastille 2013-08-27 16:43:39.434959000 -0400 | ||
| 26 | +++ Bastille/InteractiveBastille 2013-08-27 17:18:55.758959000 -0400 | ||
| 27 | @@ -531,10 +531,10 @@ | ||
| 28 | " Please address bug reports and suggestions to jay\@bastille-linux.org\n" . | ||
| 29 | "\n"; | ||
| 30 | |||
| 31 | - $InterfaceEndScreenDescription = "We will now implement the choices you have made here.\n\n" . | ||
| 32 | + $InterfaceEndScreenDescription = "We will now record the choices you have made here.\n\n" . | ||
| 33 | "Answer NO if you want to go back and make changes!\n"; | ||
| 34 | - $InterfaceEndScreenQuestion = "Are you finished answering the questions, i.e. may we make the changes?"; | ||
| 35 | - $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"; | ||
| 36 | + $InterfaceEndScreenQuestion = "Are you finished answering the questions, i.e. may we record the answers and exit?"; | ||
| 37 | + $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"; | ||
| 38 | require Bastille_Curses; | ||
| 39 | } elsif ($GLOBAL_AUDITONLY) { | ||
| 40 | |||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/edit_usage_message.patch b/dynamic-layers/meta-perl/recipes-security/bastille/files/edit_usage_message.patch new file mode 100644 index 0000000..72cdc2f --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/edit_usage_message.patch | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | Upstream Status: Inappropriate [No upstream maintenance] | ||
| 2 | |||
| 3 | Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> | ||
| 4 | |||
| 5 | --- | ||
| 6 | |||
| 7 | Index: Bastille/bin/bastille | ||
| 8 | =================================================================== | ||
| 9 | --- Bastille.orig/bin/bastille 2013-08-25 14:16:35.614779001 -0400 | ||
| 10 | +++ Bastille/bin/bastille 2013-08-25 14:16:38.674779000 -0400 | ||
| 11 | @@ -60,7 +60,7 @@ | ||
| 12 | printUsage () { | ||
| 13 | cat >&2 << EOF | ||
| 14 | $ERRSPACES Usage: bastille [ -b | -c | -x ] [ --os <version>] [ -f <alternate config> ] | ||
| 15 | -$ERRSPACES bastille [-r | -l | -h | --assess | --assessnobrowser ] | ||
| 16 | +$ERRSPACES bastille [-r | -l | -h | --assess | --assessnobrowser ] [ --os <version> ] | ||
| 17 | $ERRSPACES -b : use a saved config file to apply changes | ||
| 18 | $ERRSPACES directly to system | ||
| 19 | $ERRSPACES -c : use the Curses (non-X11) GUI, not available on HP-UX | ||
| 20 | Index: Bastille/Bastille/API.pm | ||
| 21 | =================================================================== | ||
| 22 | --- Bastille.orig/Bastille/API.pm 2013-08-25 08:15:40.266779002 -0400 | ||
| 23 | +++ Bastille/Bastille/API.pm 2013-08-25 14:18:22.750778811 -0400 | ||
| 24 | @@ -206,7 +206,7 @@ | ||
| 25 | #options before interactive or Bastille runs, so this check is often redundant | ||
| 26 | $GLOBAL_ERROR{"usage"}="\n". | ||
| 27 | "$spc Usage: bastille [ -b | -c | -x ] [ --os <version> ] [ -f <alternate config> ]\n". | ||
| 28 | - "$spc bastille [ -r | --assess | --assessnobowser ]\n\n". | ||
| 29 | + "$spc bastille [ -r | --assess | --assessnobowser ] [ --os <version> ]\n\n". | ||
| 30 | "$spc --assess : check status of system and report in browser\n". | ||
| 31 | "$spc --assessnobrowser : check status of system and list report locations\n". | ||
| 32 | "$spc -b : use a saved config file to apply changes\n". | ||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/find_existing_config.patch b/dynamic-layers/meta-perl/recipes-security/bastille/files/find_existing_config.patch new file mode 100644 index 0000000..c075875 --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/find_existing_config.patch | |||
| @@ -0,0 +1,64 @@ | |||
| 1 | Upstream Status: Inappropriate [No upstream maintenance] | ||
| 2 | |||
| 3 | Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> | ||
| 4 | |||
| 5 | --- | ||
| 6 | |||
| 7 | Index: Bastille/bin/bastille | ||
| 8 | =================================================================== | ||
| 9 | --- Bastille.orig/bin/bastille 2013-06-20 14:58:01.065796000 -0400 | ||
| 10 | +++ Bastille/bin/bastille 2013-08-20 15:16:18.472378000 -0400 | ||
| 11 | @@ -102,8 +102,9 @@ | ||
| 12 | # defines OS specific file locations based on uname | ||
| 13 | systemFileLocations | ||
| 14 | |||
| 15 | + config_files=`find $config_repository -type f -name \*config 2>/dev/null` | ||
| 16 | + | ||
| 17 | if [ -f $last_config ]; then | ||
| 18 | - config_files=`find $config_repository -type f -name \*config 2>/dev/null` | ||
| 19 | for config_cursor in `echo $config_files` | ||
| 20 | do | ||
| 21 | if /usr/bin/diff $last_config $config_cursor >/dev/null 2>&1 | ||
| 22 | @@ -112,8 +113,8 @@ | ||
| 23 | fi | ||
| 24 | done | ||
| 25 | if [ -n "$match" ]; then | ||
| 26 | - echo "The last bastille run corresponds to the following profiles:" | ||
| 27 | - echo "$match" | ||
| 28 | + printf "The last Bastille run corresponds to the following profiles:\n" | ||
| 29 | + printf "$match" | ||
| 30 | else | ||
| 31 | cat >&2 << EOF | ||
| 32 | NOTE: The last config file applied, | ||
| 33 | @@ -122,18 +123,28 @@ | ||
| 34 | $ERRSPACES $config_repository. | ||
| 35 | $ERRSPACES This probably means that Bastille was last run interactively and | ||
| 36 | $ERRSPACES changes were made to the config file, but they have not yet been | ||
| 37 | -$ERRSPACES applied, or that the source config file was moved. If you do have pending | ||
| 38 | +$ERRSPACES applied, or that the source config file was moved. If you do have pending | ||
| 39 | $ERRSPACES changes in a config file, you can apply them by running | ||
| 40 | $ERRSPACES 'bastille -b -f <config file>.' | ||
| 41 | EOF | ||
| 42 | |||
| 43 | fi | ||
| 44 | else | ||
| 45 | - echo "NOTE: The system is in its pre-bastilled state.\n" | ||
| 46 | + for config_cursor in `echo $config_files` | ||
| 47 | + do | ||
| 48 | + match="$match $config_cursor\n" | ||
| 49 | + done | ||
| 50 | + if [ -n "$match" ]; then | ||
| 51 | + printf "The following Bastille profiles were located:\n" | ||
| 52 | + printf "$match" | ||
| 53 | + else | ||
| 54 | + printf "No Bastille profiles were located.\n" | ||
| 55 | + fi | ||
| 56 | + 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" | ||
| 57 | fi | ||
| 58 | - | ||
| 59 | } | ||
| 60 | |||
| 61 | + | ||
| 62 | # First, make sure we're root | ||
| 63 | if [ `PATH="/usr/bin:/bin"; id -u` -ne 0 ]; then | ||
| 64 | echo "ERROR: Bastille must be run as root user" >&2 | ||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/fix_missing_use_directives.patch b/dynamic-layers/meta-perl/recipes-security/bastille/files/fix_missing_use_directives.patch new file mode 100644 index 0000000..05f145a --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/fix_missing_use_directives.patch | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | Upstream Status: Inappropriate [No upstream maintenance] | ||
| 2 | |||
| 3 | Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> | ||
| 4 | |||
| 5 | --- | ||
| 6 | |||
| 7 | Index: Bastille/Bastille/Firewall.pm | ||
| 8 | =================================================================== | ||
| 9 | --- Bastille.orig/Bastille/Firewall.pm 2008-09-14 19:56:54.000000000 -0400 | ||
| 10 | +++ Bastille/Bastille/Firewall.pm 2013-08-20 16:28:44.588378000 -0400 | ||
| 11 | @@ -21,6 +21,7 @@ | ||
| 12 | package Bastille::Firewall; | ||
| 13 | |||
| 14 | use Bastille::API; | ||
| 15 | +use Bastille::API::AccountPermission; | ||
| 16 | use Bastille::API::FileContent; | ||
| 17 | use Bastille::API::ServiceAdmin; | ||
| 18 | |||
| 19 | Index: Bastille/Bastille/SecureInetd.pm | ||
| 20 | =================================================================== | ||
| 21 | --- Bastille.orig/Bastille/SecureInetd.pm 2008-09-14 19:56:58.000000000 -0400 | ||
| 22 | +++ Bastille/Bastille/SecureInetd.pm 2013-08-20 16:45:02.252378001 -0400 | ||
| 23 | @@ -12,6 +12,7 @@ | ||
| 24 | use lib "/usr/lib"; | ||
| 25 | |||
| 26 | use Bastille::API; | ||
| 27 | +use Bastille::API::AccountPermission; | ||
| 28 | use Bastille::API::HPSpecific; | ||
| 29 | use Bastille::API::ServiceAdmin; | ||
| 30 | use Bastille::API::FileContent; | ||
| 31 | Index: Bastille/Bastille/ConfigureMiscPAM.pm | ||
| 32 | =================================================================== | ||
| 33 | --- Bastille.orig/Bastille/ConfigureMiscPAM.pm 2005-09-12 23:47:28.000000000 -0400 | ||
| 34 | +++ Bastille/Bastille/ConfigureMiscPAM.pm 2013-08-20 18:36:07.340378001 -0400 | ||
| 35 | @@ -5,6 +5,7 @@ | ||
| 36 | use lib "/usr/lib"; | ||
| 37 | |||
| 38 | use Bastille::API; | ||
| 39 | +use Bastille::API::FileContent; | ||
| 40 | |||
| 41 | # To DO: | ||
| 42 | # | ||
| 43 | Index: Bastille/Bastille/Printing.pm | ||
| 44 | =================================================================== | ||
| 45 | --- Bastille.orig/Bastille/Printing.pm 2008-09-14 19:56:58.000000000 -0400 | ||
| 46 | +++ Bastille/Bastille/Printing.pm 2013-08-20 19:05:01.532378002 -0400 | ||
| 47 | @@ -5,6 +5,7 @@ | ||
| 48 | use lib "/usr/lib"; | ||
| 49 | |||
| 50 | use Bastille::API; | ||
| 51 | +use Bastille::API::AccountPermission; | ||
| 52 | use Bastille::API::HPSpecific; | ||
| 53 | use Bastille::API::ServiceAdmin; | ||
| 54 | use Bastille::API::FileContent; | ||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/fix_number_of_modules.patch b/dynamic-layers/meta-perl/recipes-security/bastille/files/fix_number_of_modules.patch new file mode 100644 index 0000000..743e549 --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/fix_number_of_modules.patch | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | Upstream Status: Inappropriate [No upstream maintenance] | ||
| 2 | |||
| 3 | Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> | ||
| 4 | |||
| 5 | --- | ||
| 6 | |||
| 7 | Index: Bastille/Bastille_Curses.pm | ||
| 8 | =================================================================== | ||
| 9 | --- Bastille.orig/Bastille_Curses.pm 2013-08-24 18:21:54.445288000 -0400 | ||
| 10 | +++ Bastille/Bastille_Curses.pm 2013-08-24 18:29:16.981288000 -0400 | ||
| 11 | @@ -36,9 +36,6 @@ | ||
| 12 | use Curses; | ||
| 13 | use Curses::Widgets; | ||
| 14 | |||
| 15 | - # Number_Modules is the number of modules loaded in by Load_Questions | ||
| 16 | - $Number_Modules=0; | ||
| 17 | - | ||
| 18 | # | ||
| 19 | # Highlighted button is the button currently chosen in the button bar | ||
| 20 | # We preserve this from question to question... | ||
| 21 | @@ -397,7 +394,7 @@ | ||
| 22 | my $title; | ||
| 23 | |||
| 24 | if ($module) { | ||
| 25 | - $title=$module . " of $Number_Modules"; | ||
| 26 | + $title=$module; | ||
| 27 | } | ||
| 28 | |||
| 29 | txt_field( 'window' => $window, | ||
| 30 | @@ -488,7 +485,7 @@ | ||
| 31 | my $title; | ||
| 32 | |||
| 33 | if ($module) { | ||
| 34 | - $title=$module . " of $Number_Modules"; | ||
| 35 | + $title=$module; | ||
| 36 | } | ||
| 37 | |||
| 38 | noecho; | ||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/fix_version_parse.patch b/dynamic-layers/meta-perl/recipes-security/bastille/files/fix_version_parse.patch new file mode 100644 index 0000000..5923c04 --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/fix_version_parse.patch | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | Upstream Status: Inappropriate [No upstream maintenance] | ||
| 2 | |||
| 3 | Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> | ||
| 4 | |||
| 5 | --- | ||
| 6 | |||
| 7 | Index: Bastille/bin/bastille | ||
| 8 | =================================================================== | ||
| 9 | --- Bastille.orig/bin/bastille | ||
| 10 | +++ Bastille/bin/bastille | ||
| 11 | @@ -162,11 +162,12 @@ fi | ||
| 12 | # We check that the version is at least the minimum | ||
| 13 | |||
| 14 | PERL_VERSION=`${CURRENT_PERL_PATH}/perl -version | | ||
| 15 | - head -2 | # the second line contains the version | ||
| 16 | + head -n 2 | # the second line contains the version | ||
| 17 | tr " " "\n" | # split words into separate lines | ||
| 18 | - sed -e "s/^v//" | # to get rid of the v in v5.6.0 | ||
| 19 | - grep "^[1-9]\." | # find a "word" that starts with number dot | ||
| 20 | - sed -e "s/_/./"` # substitute _patchlevel with .patchlevel | ||
| 21 | + grep "^(v" | # find a "word" that starts with '(v' | ||
| 22 | + sed -e "s/^(v//" -e "s/)//" -e "s/_/./"` | ||
| 23 | + # to get rid of the (v in v5.6.0 | ||
| 24 | + # substitute _patchlevel with .patchlevel | ||
| 25 | # (used in 5.005_03 and prior) | ||
| 26 | |||
| 27 | # everything before the first . | ||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/fixed_defined_warnings.patch b/dynamic-layers/meta-perl/recipes-security/bastille/files/fixed_defined_warnings.patch new file mode 100644 index 0000000..e7996e3 --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/fixed_defined_warnings.patch | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | From c59b84ca3bda8e4244d47901b6966f28dd675434 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Andrei Dinu <andrei.adrianx.dinu@intel.com> | ||
| 3 | Date: Thu, 23 May 2013 15:12:23 +0300 | ||
| 4 | Subject: [PATCH] added yocto-standard to bastille | ||
| 5 | |||
| 6 | In order to make Bastille functional and avoid errors | ||
| 7 | regarding distros, if not any given distro is identified, | ||
| 8 | yocto-standard distro is added to the distro variable | ||
| 9 | in Bastille. | ||
| 10 | |||
| 11 | Fixed also some warnings regarding defined statements | ||
| 12 | in API.pm. | ||
| 13 | |||
| 14 | Upstream Status: Inappropriate [No upstream maintenance] | ||
| 15 | |||
| 16 | Signed-off-by: Andrei Dinu <andrei.adrianx.dinu@intel.com> | ||
| 17 | |||
| 18 | Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> | ||
| 19 | |||
| 20 | --- | ||
| 21 | Bastille/API.pm | 12 ++++++------ | ||
| 22 | 1 file changed, 6 insertions(+), 6 deletions(-) | ||
| 23 | |||
| 24 | Index: Bastille/Bastille/API.pm | ||
| 25 | =================================================================== | ||
| 26 | --- Bastille.orig/Bastille/API.pm 2008-09-14 19:56:53.000000000 -0400 | ||
| 27 | +++ Bastille/Bastille/API.pm 2013-08-21 08:55:26.715950001 -0400 | ||
| 28 | @@ -445,8 +445,8 @@ | ||
| 29 | $release=`/usr/bin/uname -sr`; | ||
| 30 | } | ||
| 31 | else { | ||
| 32 | - print STDERR "$err Could not determine operating system version!\n"; | ||
| 33 | - $distro="unknown"; | ||
| 34 | + print STDERR "$err Could not determine operating system version!\n"; | ||
| 35 | + $distro="unknown" | ||
| 36 | } | ||
| 37 | |||
| 38 | # Figure out what kind of system we're on. | ||
| 39 | @@ -1284,7 +1284,7 @@ | ||
| 40 | |||
| 41 | my $sumFile = &getGlobal('BFILE',"sum.csv"); | ||
| 42 | |||
| 43 | - if ( defined %GLOBAL_SUM ) { | ||
| 44 | + if ( %GLOBAL_SUM ) { | ||
| 45 | |||
| 46 | open( SUM, "> $sumFile") or &B_log("ERROR","Unable to open $sumFile for write.\n$!\n"); | ||
| 47 | |||
| 48 | @@ -1318,7 +1318,7 @@ | ||
| 49 | my $file = $_[0]; | ||
| 50 | my $cksum = &getGlobal('BIN',"cksum"); | ||
| 51 | |||
| 52 | - if (not(defined(%GLOBAL_SUM))) { | ||
| 53 | + if (not(%GLOBAL_SUM)) { | ||
| 54 | &B_read_sums; | ||
| 55 | } | ||
| 56 | |||
| 57 | @@ -1375,7 +1375,7 @@ | ||
| 58 | sub B_isFileinSumDB($) { | ||
| 59 | my $file = $_[0]; | ||
| 60 | |||
| 61 | - if (not(defined(%GLOBAL_SUM))) { | ||
| 62 | + if (not(%GLOBAL_SUM)) { | ||
| 63 | &B_log("DEBUG","Reading in DB from B_isFileinSumDB"); | ||
| 64 | &B_read_sums; | ||
| 65 | } | ||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/organize_distro_discovery.patch b/dynamic-layers/meta-perl/recipes-security/bastille/files/organize_distro_discovery.patch new file mode 100644 index 0000000..d64d1e2 --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/organize_distro_discovery.patch | |||
| @@ -0,0 +1,476 @@ | |||
| 1 | Upstream Status: Inappropriate [No upstream maintenance] | ||
| 2 | |||
| 3 | Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> | ||
| 4 | |||
| 5 | --- | ||
| 6 | |||
| 7 | Index: Bastille/Bastille/API.pm | ||
| 8 | =================================================================== | ||
| 9 | --- Bastille.orig/Bastille/API.pm 2013-08-22 04:32:38.269968002 -0400 | ||
| 10 | +++ Bastille/Bastille/API.pm 2013-08-22 11:29:53.137968002 -0400 | ||
| 11 | @@ -141,7 +141,7 @@ | ||
| 12 | checkProcsForService | ||
| 13 | |||
| 14 | |||
| 15 | - $GLOBAL_OS $GLOBAL_ACTUAL_OS $CLI | ||
| 16 | + $CLI | ||
| 17 | $GLOBAL_LOGONLY $GLOBAL_VERBOSE $GLOBAL_DEBUG $GLOBAL_AUDITONLY $GLOBAL_AUDIT_NO_BROWSER $errorFlag | ||
| 18 | %GLOBAL_BIN %GLOBAL_DIR %GLOBAL_FILE | ||
| 19 | %GLOBAL_BDIR %GLOBAL_BFILE | ||
| 20 | @@ -198,7 +198,7 @@ | ||
| 21 | my $err ="ERROR: "; | ||
| 22 | my $spc =" "; | ||
| 23 | my $GLOBAL_OS="None"; | ||
| 24 | -my $GLOBAL_ACTUAL_OS="None"; | ||
| 25 | +my $GLOBAL_INFERRED_OS="None"; | ||
| 26 | my %GLOBAL_SUMS=(); | ||
| 27 | my $CLI=''; | ||
| 28 | |||
| 29 | @@ -306,7 +306,7 @@ | ||
| 30 | |||
| 31 | ########################################################################### | ||
| 32 | # | ||
| 33 | -# GetDistro checks to see if the target is a known distribution and reports | ||
| 34 | +# InferDistro checks to see if the target is a known distribution and reports | ||
| 35 | # said distribution. | ||
| 36 | # | ||
| 37 | # This is used throughout the script, but also by ConfigureForDistro. | ||
| 38 | @@ -314,205 +314,194 @@ | ||
| 39 | # | ||
| 40 | ########################################################################### | ||
| 41 | |||
| 42 | -sub GetDistro() { | ||
| 43 | +sub InferDistro() { | ||
| 44 | |||
| 45 | my ($release,$distro); | ||
| 46 | |||
| 47 | - # Only read files for the distro once. | ||
| 48 | - # if the --os option was used then | ||
| 49 | - if ($GLOBAL_OS eq "None") { | ||
| 50 | - if ( -e "/etc/mandrake-release" ) { | ||
| 51 | - open(MANDRAKE_RELEASE,"/etc/mandrake-release"); | ||
| 52 | - $release=<MANDRAKE_RELEASE>; | ||
| 53 | - | ||
| 54 | - if ( ($release =~ /^Mandrake Linux release (\d+\.\d+\w*)/) or ($release =~ /^Linux Mandrake release (\d+\.\d+\w*)/) ) { | ||
| 55 | - $distro="MN$1"; | ||
| 56 | - } | ||
| 57 | - elsif ( $release =~ /^Mandrakelinux release (\d+\.\d+)\b/ ) { | ||
| 58 | - $distro="MN$1"; | ||
| 59 | - } | ||
| 60 | - else { | ||
| 61 | - print STDERR "$err Couldn't determine Mandrake/Mandriva version! Setting to 10.1!\n"; | ||
| 62 | - $distro="MN10.1"; | ||
| 63 | - } | ||
| 64 | - | ||
| 65 | - close(MANDRAKE_RELEASE); | ||
| 66 | - } | ||
| 67 | - elsif ( -e "/etc/immunix-release" ) { | ||
| 68 | - open(IMMUNIX_RELEASE,"/etc/immunix-release"); | ||
| 69 | - $release=<IMMUNIX_RELEASE>; | ||
| 70 | - unless ($release =~ /^Immunix Linux release (\d+\.\d+\w*)/) { | ||
| 71 | - print STDERR "$err Couldn't determine Immunix version! Setting to 6.2!\n"; | ||
| 72 | - $distro="RH6.2"; | ||
| 73 | - } | ||
| 74 | - else { | ||
| 75 | - $distro="RH$1"; | ||
| 76 | - } | ||
| 77 | - close(*IMMUNIX_RELEASE); | ||
| 78 | - } | ||
| 79 | - elsif ( -e '/etc/fedora-release' ) { | ||
| 80 | - open(FEDORA_RELEASE,'/etc/fedora-release'); | ||
| 81 | - $release=<FEDORA_RELEASE>; | ||
| 82 | - close FEDORA_RELEASE; | ||
| 83 | - if ($release =~ /^Fedora Core release (\d+\.?\d*)/) { | ||
| 84 | - $distro = "RHFC$1"; | ||
| 85 | - } | ||
| 86 | - elsif ($release =~ /^Fedora release (\d+\.?\d*)/) { | ||
| 87 | - $distro = "RHFC$1"; | ||
| 88 | - } | ||
| 89 | - else { | ||
| 90 | - print STDERR "$err Could not determine Fedora version! Setting to Fedora Core 8\n"; | ||
| 91 | - $distro='RHFC8'; | ||
| 92 | - } | ||
| 93 | + if ( -e "/etc/mandrake-release" ) { | ||
| 94 | + open(MANDRAKE_RELEASE,"/etc/mandrake-release"); | ||
| 95 | + $release=<MANDRAKE_RELEASE>; | ||
| 96 | + | ||
| 97 | + if ( ($release =~ /^Mandrake Linux release (\d+\.\d+\w*)/) or ($release =~ /^Linux Mandrake release (\d+\.\d+\w*)/) ) { | ||
| 98 | + $distro="MN$1"; | ||
| 99 | + } | ||
| 100 | + elsif ( $release =~ /^Mandrakelinux release (\d+\.\d+)\b/ ) { | ||
| 101 | + $distro="MN$1"; | ||
| 102 | + } | ||
| 103 | + else { | ||
| 104 | + print STDERR "$err Could not infer Mandrake/Mandriva version! Setting to 10.1!\n"; | ||
| 105 | + $distro="MN10.1"; | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + close(MANDRAKE_RELEASE); | ||
| 109 | + } | ||
| 110 | + elsif ( -e "/etc/immunix-release" ) { | ||
| 111 | + open(IMMUNIX_RELEASE,"/etc/immunix-release"); | ||
| 112 | + $release=<IMMUNIX_RELEASE>; | ||
| 113 | + unless ($release =~ /^Immunix Linux release (\d+\.\d+\w*)/) { | ||
| 114 | + print STDERR "$err Could not infer Immunix version! Setting to 6.2!\n"; | ||
| 115 | + $distro="RH6.2"; | ||
| 116 | + } | ||
| 117 | + else { | ||
| 118 | + $distro="RH$1"; | ||
| 119 | } | ||
| 120 | - elsif ( -e "/etc/redhat-release" ) { | ||
| 121 | - open(*REDHAT_RELEASE,"/etc/redhat-release"); | ||
| 122 | - $release=<REDHAT_RELEASE>; | ||
| 123 | - if ($release =~ /^Red Hat Linux release (\d+\.?\d*\w*)/) { | ||
| 124 | - $distro="RH$1"; | ||
| 125 | - } | ||
| 126 | - elsif ($release =~ /^Red Hat Linux .+ release (\d+)\.?\d*([AEW]S)/) { | ||
| 127 | - $distro="RHEL$1$2"; | ||
| 128 | - } | ||
| 129 | - elsif ($release =~ /^Red Hat Enterprise Linux ([AEW]S) release (\d+)/) { | ||
| 130 | - $distro="RHEL$2$1"; | ||
| 131 | + close(*IMMUNIX_RELEASE); | ||
| 132 | + } | ||
| 133 | + elsif ( -e '/etc/fedora-release' ) { | ||
| 134 | + open(FEDORA_RELEASE,'/etc/fedora-release'); | ||
| 135 | + $release=<FEDORA_RELEASE>; | ||
| 136 | + close FEDORA_RELEASE; | ||
| 137 | + if ($release =~ /^Fedora Core release (\d+\.?\d*)/) { | ||
| 138 | + $distro = "RHFC$1"; | ||
| 139 | + } | ||
| 140 | + elsif ($release =~ /^Fedora release (\d+\.?\d*)/) { | ||
| 141 | + $distro = "RHFC$1"; | ||
| 142 | + } | ||
| 143 | + else { | ||
| 144 | + print STDERR "$err Could not infer Fedora version! Setting to Fedora Core 8\n"; | ||
| 145 | + $distro='RHFC8'; | ||
| 146 | + } | ||
| 147 | + } | ||
| 148 | + elsif ( -e "/etc/redhat-release" ) { | ||
| 149 | + open(*REDHAT_RELEASE,"/etc/redhat-release"); | ||
| 150 | + $release=<REDHAT_RELEASE>; | ||
| 151 | + if ($release =~ /^Red Hat Linux release (\d+\.?\d*\w*)/) { | ||
| 152 | + $distro="RH$1"; | ||
| 153 | + } | ||
| 154 | + elsif ($release =~ /^Red Hat Linux .+ release (\d+)\.?\d*([AEW]S)/) { | ||
| 155 | + $distro="RHEL$1$2"; | ||
| 156 | + } | ||
| 157 | + elsif ($release =~ /^Red Hat Enterprise Linux ([AEW]S) release (\d+)/) { | ||
| 158 | + $distro="RHEL$2$1"; | ||
| 159 | + } | ||
| 160 | + elsif ($release =~ /^CentOS release (\d+\.\d+)/) { | ||
| 161 | + my $version = $1; | ||
| 162 | + if ($version =~ /^4\./) { | ||
| 163 | + $distro='RHEL4AS'; | ||
| 164 | } | ||
| 165 | - elsif ($release =~ /^CentOS release (\d+\.\d+)/) { | ||
| 166 | - my $version = $1; | ||
| 167 | - if ($version =~ /^4\./) { | ||
| 168 | - $distro='RHEL4AS'; | ||
| 169 | - } | ||
| 170 | - elsif ($version =~ /^3\./) { | ||
| 171 | - $distro='RHEL3AS'; | ||
| 172 | - } | ||
| 173 | - else { | ||
| 174 | - print STDERR "$err Could not determine CentOS version! Setting to Red Hat Enterprise 4 AS.\n"; | ||
| 175 | - $distro='RHEL4AS'; | ||
| 176 | - } | ||
| 177 | - } | ||
| 178 | - else { | ||
| 179 | - # JJB/HP - Should this be B_log? | ||
| 180 | - print STDERR "$err Couldn't determine Red Hat version! Setting to 9!\n"; | ||
| 181 | - $distro="RH9"; | ||
| 182 | - } | ||
| 183 | - close(REDHAT_RELEASE); | ||
| 184 | - | ||
| 185 | - } | ||
| 186 | - elsif ( -e "/etc/debian_version" ) { | ||
| 187 | - $stable="3.1"; #Change this when Debian stable changes | ||
| 188 | - open(*DEBIAN_RELEASE,"/etc/debian_version"); | ||
| 189 | - $release=<DEBIAN_RELEASE>; | ||
| 190 | - unless ($release =~ /^(\d+\.\d+\w*)/) { | ||
| 191 | - print STDERR "$err System is not running a stable Debian GNU/Linux version. Setting to $stable.\n"; | ||
| 192 | - $distro="DB$stable"; | ||
| 193 | + elsif ($version =~ /^3\./) { | ||
| 194 | + $distro='RHEL3AS'; | ||
| 195 | } | ||
| 196 | else { | ||
| 197 | - $distro="DB$1"; | ||
| 198 | - } | ||
| 199 | - close(DEBIAN_RELEASE); | ||
| 200 | - } | ||
| 201 | - elsif ( -e "/etc/SuSE-release" ) { | ||
| 202 | - open(*SUSE_RELEASE,"/etc/SuSE-release"); | ||
| 203 | - $release=<SUSE_RELEASE>; | ||
| 204 | - if ($release =~ /^SuSE Linux (\d+\.\d+\w*)/i) { | ||
| 205 | - $distro="SE$1"; | ||
| 206 | - } | ||
| 207 | - elsif ($release =~ /^SUSE LINUX Enterprise Server (\d+\.?\d?\w*)/i) { | ||
| 208 | - $distro="SESLES$1"; | ||
| 209 | - } | ||
| 210 | - elsif ($release =~ /^SUSE Linux Enterprise Server (\d+\.?\d?\w*)/i) { | ||
| 211 | - $distro="SESLES$1"; | ||
| 212 | - } | ||
| 213 | - elsif ($release =~ /^openSuSE (\d+\.\d+\w*)/i) { | ||
| 214 | - $distro="SE$1"; | ||
| 215 | + print STDERR "$err Could not infer CentOS version! Setting to Red Hat Enterprise 4 AS.\n"; | ||
| 216 | + $distro='RHEL4AS'; | ||
| 217 | } | ||
| 218 | - else { | ||
| 219 | - print STDERR "$err Couldn't determine SuSE version! Setting to 10.3!\n"; | ||
| 220 | - $distro="SE10.3"; | ||
| 221 | - } | ||
| 222 | - close(SUSE_RELEASE); | ||
| 223 | - } | ||
| 224 | - elsif ( -e "/etc/turbolinux-release") { | ||
| 225 | - open(*TURBOLINUX_RELEASE,"/etc/turbolinux-release"); | ||
| 226 | - $release=<TURBOLINUX_RELEASE>; | ||
| 227 | - unless ($release =~ /^Turbolinux Workstation (\d+\.\d+\w*)/) { | ||
| 228 | - print STDERR "$err Couldn't determine TurboLinux version! Setting to 7.0!\n"; | ||
| 229 | - $distro="TB7.0"; | ||
| 230 | - } | ||
| 231 | - else { | ||
| 232 | - $distro="TB$1"; | ||
| 233 | - } | ||
| 234 | - close(TURBOLINUX_RELEASE); | ||
| 235 | + } | ||
| 236 | + else { | ||
| 237 | + # JJB/HP - Should this be B_log? | ||
| 238 | + print STDERR "$err Could not infer Red Hat version! Setting to 9!\n"; | ||
| 239 | + $distro="RH9"; | ||
| 240 | + } | ||
| 241 | + close(REDHAT_RELEASE); | ||
| 242 | + | ||
| 243 | + } | ||
| 244 | + elsif ( -e "/etc/debian_version" ) { | ||
| 245 | + $stable="3.1"; #Change this when Debian stable changes | ||
| 246 | + open(*DEBIAN_RELEASE,"/etc/debian_version"); | ||
| 247 | + $release=<DEBIAN_RELEASE>; | ||
| 248 | + unless ($release =~ /^(\d+\.\d+\w*)/) { | ||
| 249 | + print STDERR "$err System is not running a stable Debian GNU/Linux version. Setting to $stable.\n"; | ||
| 250 | + $distro="DB$stable"; | ||
| 251 | + } | ||
| 252 | + else { | ||
| 253 | + $distro="DB$1"; | ||
| 254 | + } | ||
| 255 | + close(DEBIAN_RELEASE); | ||
| 256 | + } | ||
| 257 | + elsif ( -e "/etc/SuSE-release" ) { | ||
| 258 | + open(*SUSE_RELEASE,"/etc/SuSE-release"); | ||
| 259 | + $release=<SUSE_RELEASE>; | ||
| 260 | + if ($release =~ /^SuSE Linux (\d+\.\d+\w*)/i) { | ||
| 261 | + $distro="SE$1"; | ||
| 262 | + } | ||
| 263 | + elsif ($release =~ /^SUSE LINUX Enterprise Server (\d+\.?\d?\w*)/i) { | ||
| 264 | + $distro="SESLES$1"; | ||
| 265 | + } | ||
| 266 | + elsif ($release =~ /^SUSE Linux Enterprise Server (\d+\.?\d?\w*)/i) { | ||
| 267 | + $distro="SESLES$1"; | ||
| 268 | + } | ||
| 269 | + elsif ($release =~ /^openSuSE (\d+\.\d+\w*)/i) { | ||
| 270 | + $distro="SE$1"; | ||
| 271 | + } | ||
| 272 | + else { | ||
| 273 | + print STDERR "$err Could not infer SuSE version! Setting to 10.3!\n"; | ||
| 274 | + $distro="SE10.3"; | ||
| 275 | } | ||
| 276 | + close(SUSE_RELEASE); | ||
| 277 | + } | ||
| 278 | + elsif ( -e "/etc/turbolinux-release") { | ||
| 279 | + open(*TURBOLINUX_RELEASE,"/etc/turbolinux-release"); | ||
| 280 | + $release=<TURBOLINUX_RELEASE>; | ||
| 281 | + unless ($release =~ /^Turbolinux Workstation (\d+\.\d+\w*)/) { | ||
| 282 | + print STDERR "$err Could not infer TurboLinux version! Setting to 7.0!\n"; | ||
| 283 | + $distro="TB7.0"; | ||
| 284 | + } | ||
| 285 | else { | ||
| 286 | - # We're either on Mac OS X, HP-UX or an unsupported O/S. | ||
| 287 | - if ( -x '/usr/bin/uname') { | ||
| 288 | + $distro="TB$1"; | ||
| 289 | + } | ||
| 290 | + close(TURBOLINUX_RELEASE); | ||
| 291 | + } | ||
| 292 | + else { | ||
| 293 | + # We're either on Mac OS X, HP-UX or an unsupported O/S. | ||
| 294 | + if ( -x '/usr/bin/uname') { | ||
| 295 | # uname is in /usr/bin on Mac OS X and HP-UX | ||
| 296 | - $release=`/usr/bin/uname -sr`; | ||
| 297 | - } | ||
| 298 | - else { | ||
| 299 | - print STDERR "$err Could not determine operating system version!\n"; | ||
| 300 | - $distro="unknown" | ||
| 301 | - } | ||
| 302 | - | ||
| 303 | - # Figure out what kind of system we're on. | ||
| 304 | - if ($release ne "") { | ||
| 305 | - if ($release =~ /^Darwin\s+(\d+)\.(\d+)/) { | ||
| 306 | - if ($1 == 6 ) { | ||
| 307 | - $distro = "OSX10.2"; | ||
| 308 | - } | ||
| 309 | - elsif ($1 == 7) { | ||
| 310 | - $distro = "OSX10.3"; | ||
| 311 | - } | ||
| 312 | - elsif ($1 == 8) { | ||
| 313 | - $distro = "OSX10.3"; | ||
| 314 | - } | ||
| 315 | - else { | ||
| 316 | - $distro = "unknown"; | ||
| 317 | - } | ||
| 318 | + $release=`/usr/bin/uname -sr`; | ||
| 319 | + } | ||
| 320 | + else { | ||
| 321 | + print STDERR "$err Could not infer operating system version from filesystem context. Setting inferred distro to 'unknown'.\n"; | ||
| 322 | + $distro="unknown"; | ||
| 323 | + } | ||
| 324 | + | ||
| 325 | + # Figure out what kind of system we're on. | ||
| 326 | + if ($release ne "") { | ||
| 327 | + if ($release =~ /^Darwin\s+(\d+)\.(\d+)/) { | ||
| 328 | + if ($1 == 6 ) { | ||
| 329 | + $distro = "OSX10.2"; | ||
| 330 | } | ||
| 331 | - elsif ( $release =~ /(^HP-UX)\s*B\.(\d+\.\d+)/ ) { | ||
| 332 | - $distro="$1$2"; | ||
| 333 | + elsif ($1 == 7) { | ||
| 334 | + $distro = "OSX10.3"; | ||
| 335 | } | ||
| 336 | + elsif ($1 == 8) { | ||
| 337 | + $distro = "OSX10.3"; | ||
| 338 | + } | ||
| 339 | else { | ||
| 340 | - print STDERR "$err Could not determine operating system version!\n"; | ||
| 341 | - $distro="unknown"; | ||
| 342 | + print STDERR "$err Could not infer operating system version from filesystem context. Setting inferred distro to 'unknown'.\n"; | ||
| 343 | + $distro = "unknown"; | ||
| 344 | } | ||
| 345 | } | ||
| 346 | + elsif ( $release =~ /(^HP-UX)\s*B\.(\d+\.\d+)/ ) { | ||
| 347 | + $distro="$1$2"; | ||
| 348 | + } | ||
| 349 | + else { | ||
| 350 | + print STDERR "$err Could not infer operating system version from filesystem context. Setting inferred distro to 'unknown'.\n"; | ||
| 351 | + $distro="unknown"; | ||
| 352 | + } | ||
| 353 | } | ||
| 354 | - | ||
| 355 | - $GLOBAL_OS=$distro; | ||
| 356 | - } elsif (not (defined $GLOBAL_OS)) { | ||
| 357 | - print "ERROR: GLOBAL OS Scoping Issue\n"; | ||
| 358 | - } else { | ||
| 359 | - $distro = $GLOBAL_OS; | ||
| 360 | } | ||
| 361 | - | ||
| 362 | return $distro; | ||
| 363 | } | ||
| 364 | |||
| 365 | ################################################################################### | ||
| 366 | -# &getActualDistro; # | ||
| 367 | +# &getInferredDistro; # | ||
| 368 | # # | ||
| 369 | # This subroutine returns the actual os version in which is running on. This # | ||
| 370 | # os version is independent of the --os switch feed to bastille. # | ||
| 371 | # # | ||
| 372 | ################################################################################### | ||
| 373 | -sub getActualDistro { | ||
| 374 | - # set local variable to $GLOBAL_OS | ||
| 375 | +sub getInferredDistro { | ||
| 376 | + if ($GLOBAL_INFERRED_OS eq "None") { | ||
| 377 | + $GLOBAL_INFERRED_OS = &InferDistro; | ||
| 378 | + } | ||
| 379 | + return $GLOBAL_INFERRED_OS; | ||
| 380 | +} | ||
| 381 | |||
| 382 | - if ($GLOBAL_ACTUAL_OS eq "None") { | ||
| 383 | - my $os = $GLOBAL_OS; | ||
| 384 | - # undef GLOBAL_OS so that the GetDistro routine will return | ||
| 385 | - # the actualDistro, it might otherwise return the distro set | ||
| 386 | - # by the --os switch. | ||
| 387 | - $GLOBAL_OS = "None"; | ||
| 388 | - $GLOBAL_ACTUAL_OS = &GetDistro; | ||
| 389 | - # reset the GLOBAL_OS variable | ||
| 390 | - $GLOBAL_OS = $os; | ||
| 391 | +sub GetDistro { | ||
| 392 | + if ($GLOBAL_OS eq "None") { | ||
| 393 | + return &getInferredDistro; | ||
| 394 | } | ||
| 395 | - return $GLOBAL_ACTUAL_OS; | ||
| 396 | + return $GLOBAL_OS; | ||
| 397 | } | ||
| 398 | + | ||
| 399 | # These are helper routines which used to be included inside GetDistro | ||
| 400 | sub is_OS_supported($) { | ||
| 401 | my $os=$_[0]; | ||
| 402 | @@ -556,7 +545,8 @@ | ||
| 403 | "SE7.2","SE7.3", "SE8.0","SE8.1","SE9.0","SE9.1", | ||
| 404 | "SE9.2","SE9.3","SE10.0","SE10.1","SE10.2","SE10.3", | ||
| 405 | "SESLES8","SESLES9","SESLES10", | ||
| 406 | - "TB7.0" | ||
| 407 | + "TB7.0", | ||
| 408 | + "Yocto" | ||
| 409 | ], | ||
| 410 | |||
| 411 | "HP-UX" => [ | ||
| 412 | @@ -882,23 +872,19 @@ | ||
| 413 | ########################################################################### | ||
| 414 | sub ConfigureForDistro { | ||
| 415 | |||
| 416 | - my $retval=1; | ||
| 417 | - | ||
| 418 | - # checking to see if the os version given is in fact supported | ||
| 419 | my $distro = &GetDistro; | ||
| 420 | |||
| 421 | - # checking to see if the actual os version is in fact supported | ||
| 422 | - my $actualDistro = &getActualDistro; | ||
| 423 | + my $inferredDistro = &getInferredDistro; | ||
| 424 | + | ||
| 425 | + if (! ($inferredDistro eq $distro) ) { | ||
| 426 | + print STDERR "WARNING: Inferred distro $inferredDistro is not the same as specified distro $distro. Using specified distro.\n"; | ||
| 427 | + } | ||
| 428 | + | ||
| 429 | $ENV{'LOCALE'}=''; # So that test cases checking for english results work ok. | ||
| 430 | - if ((! &is_OS_supported($distro)) or (! &is_OS_supported($actualDistro)) ) { | ||
| 431 | - # if either is not supported then print out a list of supported versions | ||
| 432 | - if (! &is_OS_supported($distro)) { | ||
| 433 | - print STDERR "$err '$distro' is not a supported operating system.\n"; | ||
| 434 | - } | ||
| 435 | - else { | ||
| 436 | - print STDERR "$err Bastille is unable to operate correctly on this\n"; | ||
| 437 | - print STDERR "$spc $distro operating system.\n"; | ||
| 438 | - } | ||
| 439 | + | ||
| 440 | + if (! &is_OS_supported($distro)) { | ||
| 441 | + print STDERR "$err '$distro' is not a supported operating system.\n"; | ||
| 442 | + | ||
| 443 | my %supportedOSHash = &getSupportedOSHash; | ||
| 444 | print STDERR "$spc Valid operating system versions are as follows:\n"; | ||
| 445 | |||
| 446 | @@ -930,7 +916,7 @@ | ||
| 447 | # intend via setting the Perl umask | ||
| 448 | umask(077); | ||
| 449 | |||
| 450 | - &getFileAndServiceInfo($distro,$actualDistro); | ||
| 451 | + &getFileAndServiceInfo($distro,$distro); | ||
| 452 | |||
| 453 | # &dumpFileInfo; # great for debuging file location issues | ||
| 454 | # &dumpServiceInfo; # great for debuging service information issues | ||
| 455 | @@ -942,7 +928,7 @@ | ||
| 456 | "$spc You must use Bastille\'s -n flag (for example:\n" . | ||
| 457 | "$spc bastille -f -n) or \'touch $nodisclaim_file \'\n"; | ||
| 458 | |||
| 459 | - return $retval; | ||
| 460 | + return 1; | ||
| 461 | } | ||
| 462 | |||
| 463 | |||
| 464 | Index: Bastille/Bastille/LogAPI.pm | ||
| 465 | =================================================================== | ||
| 466 | --- Bastille.orig/Bastille/LogAPI.pm 2013-08-22 04:32:38.269968002 -0400 | ||
| 467 | +++ Bastille/Bastille/LogAPI.pm 2013-08-22 04:32:47.509968002 -0400 | ||
| 468 | @@ -111,7 +111,7 @@ | ||
| 469 | # do this here to prevent bootstrapping problem, where we need to | ||
| 470 | # write an error that the errorlog location isn't defined. | ||
| 471 | my $logdir="/var/log/Bastille"; | ||
| 472 | - if(&getActualDistro =~ "^HP-UX"){ | ||
| 473 | + if(&getInferredDistro =~ "^HP-UX"){ | ||
| 474 | $logdir = "/var/opt/sec_mgmt/bastille/log/"; | ||
| 475 | } | ||
| 476 | |||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/remove_questions_text_file_references.patch b/dynamic-layers/meta-perl/recipes-security/bastille/files/remove_questions_text_file_references.patch new file mode 100644 index 0000000..bd094ee --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/remove_questions_text_file_references.patch | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | Upstream Status: Inappropriate [No upstream maintenance] | ||
| 2 | |||
| 3 | Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> | ||
| 4 | |||
| 5 | --- | ||
| 6 | |||
| 7 | Index: Bastille/OSMap/LINUX.bastille | ||
| 8 | =================================================================== | ||
| 9 | --- Bastille.orig/OSMap/LINUX.bastille 2008-01-25 18:31:35.000000000 -0500 | ||
| 10 | +++ Bastille/OSMap/LINUX.bastille 2013-08-22 04:48:32.677968002 -0400 | ||
| 11 | @@ -12,7 +12,6 @@ | ||
| 12 | |||
| 13 | bfile,InteractiveBastille,'/usr/sbin/InteractiveBastille' | ||
| 14 | bfile,BastilleBackEnd,'/usr/sbin/BastilleBackEnd' | ||
| 15 | -bfile,Questions,'/usr/share/Bastille/Questions.txt' | ||
| 16 | bfile,QuestionsModules,'/usr/share/Bastille/Modules.txt' | ||
| 17 | bfile,TODO,'/var/log/Bastille/TODO' | ||
| 18 | bfile,TODOFlag,'/var/log/Bastille/TODOFlag.txt' | ||
| 19 | Index: Bastille/OSMap/OSX.bastille | ||
| 20 | =================================================================== | ||
| 21 | --- Bastille.orig/OSMap/OSX.bastille 2007-09-11 18:09:26.000000000 -0400 | ||
| 22 | +++ Bastille/OSMap/OSX.bastille 2013-08-22 04:48:47.245968001 -0400 | ||
| 23 | @@ -10,7 +10,6 @@ | ||
| 24 | bdir,share,'/usr/share/Bastille' | ||
| 25 | |||
| 26 | bfile,BastilleBackEnd,'/var/root/Bastille/BastilleBackEnd' | ||
| 27 | -bfile,Questions,'/usr/share/Bastille/Questions.txt' | ||
| 28 | bfile,QuestionsModules,'/usr/share/Bastille/Modules.txt' | ||
| 29 | bfile,TODO,'/var/log/Bastille/TODO' | ||
| 30 | bfile,TODOFlag,'/var/log/Bastille/TODOFlag.txt' | ||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/set_required_questions.py b/dynamic-layers/meta-perl/recipes-security/bastille/files/set_required_questions.py new file mode 100755 index 0000000..f306109 --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/set_required_questions.py | |||
| @@ -0,0 +1,157 @@ | |||
| 1 | #!/usr/bin/env python3 | ||
| 2 | |||
| 3 | #Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> | ||
| 4 | |||
| 5 | import argparse, os, shutil, sys, tempfile, traceback | ||
| 6 | from os import path | ||
| 7 | |||
| 8 | |||
| 9 | |||
| 10 | def get_config(lines): | ||
| 11 | """ | ||
| 12 | From a sequence of lines retrieve the question file name, question identifier | ||
| 13 | pairs. | ||
| 14 | """ | ||
| 15 | for l in lines: | ||
| 16 | if not l.startswith("#"): | ||
| 17 | try: | ||
| 18 | (coord, value) = l.split("=") | ||
| 19 | try: | ||
| 20 | (fname, ident) = coord.split(".") | ||
| 21 | yield fname, ident | ||
| 22 | except ValueError as e: | ||
| 23 | raise ValueError("Badly formatted coordinates %s in line %s." % (coord, l.strip())) | ||
| 24 | except ValueError as e: | ||
| 25 | raise ValueError("Skipping badly formatted line %s, %s" % (l.strip(), e)) | ||
| 26 | |||
| 27 | |||
| 28 | |||
| 29 | def check_contains(line, name): | ||
| 30 | """ | ||
| 31 | Check if the value field for REQUIRE_DISTRO contains the given name. | ||
| 32 | @param name line The REQUIRE_DISTRO line | ||
| 33 | @param name name The name to look for in the value field of the line. | ||
| 34 | """ | ||
| 35 | try: | ||
| 36 | (label, distros) = line.split(":") | ||
| 37 | return name in distros.split() | ||
| 38 | except ValueError as e: | ||
| 39 | raise ValueError("Error splitting REQUIRE_DISTRO line: %s" % e) | ||
| 40 | |||
| 41 | |||
| 42 | |||
| 43 | def add_requires(the_ident, distro, lines): | ||
| 44 | |||
| 45 | """ | ||
| 46 | Yield a sequence of lines the same as lines except that where | ||
| 47 | the_ident matches a question identifier change the REQUIRE_DISTRO so that | ||
| 48 | it includes the specified distro. | ||
| 49 | |||
| 50 | @param name the_ident The question identifier to be matched. | ||
| 51 | @param name distro The distribution to added to the questions REQUIRE_DISTRO | ||
| 52 | field. | ||
| 53 | @param lines The sequence to be processed. | ||
| 54 | """ | ||
| 55 | for l in lines: | ||
| 56 | yield l | ||
| 57 | if l.startswith("LABEL:"): | ||
| 58 | try: | ||
| 59 | (label, ident) = l.split(":") | ||
| 60 | if ident.strip() == the_ident: | ||
| 61 | break | ||
| 62 | except ValueError as e: | ||
| 63 | raise ValueError("Unexpected line %s in questions file." % l.strip()) | ||
| 64 | for l in lines: | ||
| 65 | if l.startswith("REQUIRE_DISTRO"): | ||
| 66 | if not check_contains(l, distro): | ||
| 67 | yield l.rstrip() + " " + distro + "\n" | ||
| 68 | else: | ||
| 69 | yield l | ||
| 70 | break; | ||
| 71 | else: | ||
| 72 | yield l | ||
| 73 | for l in lines: | ||
| 74 | yield l | ||
| 75 | |||
| 76 | |||
| 77 | |||
| 78 | def xform_file(qfile, distro, qlabel): | ||
| 79 | """ | ||
| 80 | Transform a Questions file. | ||
| 81 | @param name qfile The designated questions file. | ||
| 82 | @param name distro The distribution to add to the required distributions. | ||
| 83 | @param name qlabel The question label for which the distro is to be added. | ||
| 84 | """ | ||
| 85 | questions_in = open(qfile) | ||
| 86 | questions_out = tempfile.NamedTemporaryFile(mode="w+", delete=False) | ||
| 87 | for l in add_requires(qlabel, distro, questions_in): | ||
| 88 | questions_out.write(l) | ||
| 89 | questions_out.close() | ||
| 90 | questions_in.close() | ||
| 91 | shutil.copystat(qfile, questions_out.name) | ||
| 92 | os.remove(qfile) | ||
| 93 | shutil.move(questions_out.name, qfile) | ||
| 94 | |||
| 95 | |||
| 96 | |||
| 97 | def handle_args(parser): | ||
| 98 | parser.add_argument('config_file', | ||
| 99 | help = "Configuration file path.") | ||
| 100 | parser.add_argument('questions_dir', | ||
| 101 | help = "Directory containing Questions files.") | ||
| 102 | parser.add_argument('--distro', '-d', | ||
| 103 | help = "The distribution, the default is Yocto.", | ||
| 104 | default = "Yocto") | ||
| 105 | parser.add_argument('--debug', '-b', | ||
| 106 | help = "Print debug information.", | ||
| 107 | action = 'store_true') | ||
| 108 | return parser.parse_args() | ||
| 109 | |||
| 110 | |||
| 111 | |||
| 112 | def check_args(args): | ||
| 113 | args.config_file = os.path.abspath(args.config_file) | ||
| 114 | args.questions_dir = os.path.abspath(args.questions_dir) | ||
| 115 | |||
| 116 | if not os.path.isdir(args.questions_dir): | ||
| 117 | raise ValueError("Specified Questions directory %s does not exist or is not a directory." % args.questions_dir) | ||
| 118 | |||
| 119 | if not os.path.isfile(args.config_file): | ||
| 120 | raise ValueError("Specified configuration file %s not found." % args.config_file) | ||
| 121 | |||
| 122 | |||
| 123 | |||
| 124 | def main(): | ||
| 125 | opts = handle_args(argparse.ArgumentParser(description="A simple script that sets required questions based on the question/answer pairs in a configuration file.")) | ||
| 126 | |||
| 127 | try: | ||
| 128 | check_args(opts) | ||
| 129 | except ValueError as e: | ||
| 130 | if opts.debug: | ||
| 131 | traceback.print_exc() | ||
| 132 | else: | ||
| 133 | sys.exit("Fatal error:\n%s" % e) | ||
| 134 | |||
| 135 | |||
| 136 | try: | ||
| 137 | config_in = open(opts.config_file) | ||
| 138 | for qfile, qlabel in get_config(config_in): | ||
| 139 | questions_file = os.path.join(opts.questions_dir, qfile + ".txt") | ||
| 140 | xform_file(questions_file, opts.distro, qlabel) | ||
| 141 | config_in.close() | ||
| 142 | |||
| 143 | except IOError as e: | ||
| 144 | if opts.debug: | ||
| 145 | traceback.print_exc() | ||
| 146 | else: | ||
| 147 | sys.exit("Fatal error reading or writing file:\n%s" % e) | ||
| 148 | except ValueError as e: | ||
| 149 | if opts.debug: | ||
| 150 | traceback.print_exc() | ||
| 151 | else: | ||
| 152 | sys.exit("Fatal error:\n%s" % e) | ||
| 153 | |||
| 154 | |||
| 155 | |||
| 156 | if __name__ == "__main__": | ||
| 157 | main() | ||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/simplify_B_place.patch b/dynamic-layers/meta-perl/recipes-security/bastille/files/simplify_B_place.patch new file mode 100644 index 0000000..307fdca --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/simplify_B_place.patch | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | Upstream Status: Inappropriate [No upstream maintenance] | ||
| 2 | |||
| 3 | Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> | ||
| 4 | |||
| 5 | --- | ||
| 6 | |||
| 7 | Index: Bastille/Bastille/API.pm | ||
| 8 | =================================================================== | ||
| 9 | --- Bastille.orig/Bastille/API.pm 2013-08-21 08:59:17.939950001 -0400 | ||
| 10 | +++ Bastille/Bastille/API.pm 2013-08-21 08:59:30.983950001 -0400 | ||
| 11 | @@ -1679,24 +1679,22 @@ | ||
| 12 | |||
| 13 | use File::Copy; | ||
| 14 | |||
| 15 | - my $original_source=$source; | ||
| 16 | $source = &getGlobal('BDIR', "share") . $source; | ||
| 17 | - my $original_target=$target; | ||
| 18 | |||
| 19 | if ( -e $target and -f $target ) { | ||
| 20 | - &B_backup_file($original_target); | ||
| 21 | - &B_log("ACTION","About to copy $original_source to $original_target -- had to backup target\n"); | ||
| 22 | + &B_backup_file($target); | ||
| 23 | + &B_log("ACTION","About to copy $source to $target -- had to backup target\n"); | ||
| 24 | $had_to_backup_target=1; | ||
| 25 | } | ||
| 26 | $retval=copy($source,$target); | ||
| 27 | if ($retval) { | ||
| 28 | - &B_log("ACTION","placed file $original_source as $original_target\n"); | ||
| 29 | + &B_log("ACTION","placed file $source as $target\n"); | ||
| 30 | # | ||
| 31 | # We want to add a line to the &getGlobal('BFILE', "created-files") so that the | ||
| 32 | # file we just put at $original_target gets deleted. | ||
| 33 | - &B_revert_log(&getGlobal('BIN',"rm") . " $original_target\n"); | ||
| 34 | + &B_revert_log(&getGlobal('BIN',"rm") . " $target\n"); | ||
| 35 | } else { | ||
| 36 | - &B_log("ERROR","Failed to place $original_source as $original_target\n"); | ||
| 37 | + &B_log("ERROR","Failed to place $source as $target\n"); | ||
| 38 | } | ||
| 39 | |||
| 40 | # We add the file to the GLOBAL_SUMS hash if it is not already present | ||
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/upgrade_options_processing.patch b/dynamic-layers/meta-perl/recipes-security/bastille/files/upgrade_options_processing.patch new file mode 100644 index 0000000..4093867 --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/upgrade_options_processing.patch | |||
| @@ -0,0 +1,91 @@ | |||
| 1 | Upstream Status: Inappropriate [No upstream maintenance] | ||
| 2 | |||
| 3 | Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> | ||
| 4 | |||
| 5 | --- | ||
| 6 | |||
| 7 | Index: Bastille/Bastille/API.pm | ||
| 8 | =================================================================== | ||
| 9 | --- Bastille.orig/Bastille/API.pm 2013-08-21 11:41:09.235950000 -0400 | ||
| 10 | +++ Bastille/Bastille/API.pm 2013-08-21 11:41:16.183950000 -0400 | ||
| 11 | @@ -271,9 +271,15 @@ | ||
| 12 | # setOptions takes six arguments, $GLOBAL_DEBUG, $GLOBAL_LOGONLY, | ||
| 13 | # $GLOBAL_VERBOSE, $GLOBAL_AUDITONLY, $GLOBAL_AUDIT_NO_BROWSER, and GLOBAL_OS; | ||
| 14 | ########################################################################### | ||
| 15 | -sub setOptions($$$$$$) { | ||
| 16 | - ($GLOBAL_DEBUG,$GLOBAL_LOGONLY,$GLOBAL_VERBOSE,$GLOBAL_AUDITONLY, | ||
| 17 | - $GLOBAL_AUDIT_NO_BROWSER,$GLOBAL_OS) = @_; | ||
| 18 | +sub setOptions { | ||
| 19 | + my %opts = @_; | ||
| 20 | + | ||
| 21 | + $GLOBAL_DEBUG = $opts{debug}; | ||
| 22 | + $GLOBAL_LOGONLY = $opts{logonly}; | ||
| 23 | + $GLOBAL_VERBOSE = $opts{verbose}; | ||
| 24 | + $GLOBAL_AUDITONLY = $opts{auditonly}; | ||
| 25 | + $GLOBAL_AUDIT_NO_BROWSER = $opts{audit_no_browser}; | ||
| 26 | + $GLOBAL_OS = $opts{os}; | ||
| 27 | if ($GLOBAL_AUDIT_NO_BROWSER) { | ||
| 28 | $GLOBAL_AUDITONLY = 1; | ||
| 29 | } | ||
| 30 | Index: Bastille/BastilleBackEnd | ||
| 31 | =================================================================== | ||
| 32 | --- Bastille.orig/BastilleBackEnd 2013-08-21 11:41:09.235950000 -0400 | ||
| 33 | +++ Bastille/BastilleBackEnd 2013-08-21 12:40:54.055950001 -0400 | ||
| 34 | @@ -50,15 +50,13 @@ | ||
| 35 | my $nodisclaim = 0; | ||
| 36 | my $verbose = 0; | ||
| 37 | my $force = 0; | ||
| 38 | -my $log_only = 0; | ||
| 39 | my $debug = 0; | ||
| 40 | my $alternate_config=undef; | ||
| 41 | |||
| 42 | if( Getopt::Long::GetOptions( "n" => \$nodisclaim, | ||
| 43 | "v" => \$verbose, | ||
| 44 | "force" => \$force, | ||
| 45 | -# "log" => \$log_only, # broken | ||
| 46 | - "f:s" => \$alternate_config, | ||
| 47 | + "f=s" => \$alternate_config, | ||
| 48 | "debug" => \$debug) ) { | ||
| 49 | $error = 0; # no parse error | ||
| 50 | |||
| 51 | @@ -66,7 +64,9 @@ | ||
| 52 | $error = 1; # parse error | ||
| 53 | } | ||
| 54 | |||
| 55 | -&setOptions($debug,$log_only,$verbose); | ||
| 56 | +&setOptions( | ||
| 57 | + debug => $debug, | ||
| 58 | + verbose => $verbose); | ||
| 59 | &ConfigureForDistro; | ||
| 60 | |||
| 61 | if ( $error ) { # GetOptions couldn't parse all of the args | ||
| 62 | Index: Bastille/InteractiveBastille | ||
| 63 | =================================================================== | ||
| 64 | --- Bastille.orig/InteractiveBastille 2013-08-21 11:41:09.235950000 -0400 | ||
| 65 | +++ Bastille/InteractiveBastille 2013-08-21 12:40:30.531950001 -0400 | ||
| 66 | @@ -234,8 +234,8 @@ | ||
| 67 | "a" => \$audit, | ||
| 68 | "force" => \$force, | ||
| 69 | "log" => \$log_only, | ||
| 70 | - "os:s" => \$os_version, | ||
| 71 | - "f:s" => \$alternate_config, | ||
| 72 | + "os=s" => \$os_version, | ||
| 73 | + "f=s" => \$alternate_config, | ||
| 74 | "debug" => \$debug) ) { | ||
| 75 | $error = 0; # no parse error | ||
| 76 | } else { | ||
| 77 | @@ -293,7 +293,13 @@ | ||
| 78 | $UseRequiresRules = 'N'; | ||
| 79 | } | ||
| 80 | |||
| 81 | -&setOptions($debug,$log_only,$verbose,$audit,$auditnobrowser,$os_version); | ||
| 82 | +&setOptions( | ||
| 83 | + debug => $debug, | ||
| 84 | + logonly => $log_only, | ||
| 85 | + verbose => $verbose, | ||
| 86 | + auditonly => $audit, | ||
| 87 | + audit_no_browser => $auditnobrowser, | ||
| 88 | + os => $os_version); | ||
| 89 | &ConfigureForDistro; | ||
| 90 | |||
| 91 | # ensuring mutually exclusive options are exclusive | ||
diff --git a/dynamic-layers/meta-perl/recipes-security/nikto/files/location.patch b/dynamic-layers/meta-perl/recipes-security/nikto/files/location.patch new file mode 100644 index 0000000..edaa204 --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/nikto/files/location.patch | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | From d1cb702d5147abea0d3208a4d554c61a6f2decd6 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Scott Ellis <scott@jumpnowtek.com> | ||
| 3 | Date: Fri, 28 Dec 2018 11:08:25 -0500 | ||
| 4 | Subject: [PATCH] Set custom paths | ||
| 5 | |||
| 6 | Upstream Status: Inappropriate | ||
| 7 | |||
| 8 | Signed-off-by: Scott Ellis <scott@jumpnowtek.com> | ||
| 9 | --- | ||
| 10 | nikto.conf | 10 +++++----- | ||
| 11 | 1 file changed, 5 insertions(+), 5 deletions(-) | ||
| 12 | |||
| 13 | diff --git a/program/nikto.conf b/program/nikto.conf | ||
| 14 | index bf36c58..8c55415 100644 | ||
| 15 | --- a/nikto.conf | ||
| 16 | +++ b/nikto.conf | ||
| 17 | @@ -61,11 +61,11 @@ CIRT=107.170.99.251 | ||
| 18 | CHECKMETHODS=HEAD GET | ||
| 19 | |||
| 20 | # If you want to specify the location of any of the files, specify them here | ||
| 21 | -# EXECDIR=/opt/nikto # Location of Nikto | ||
| 22 | -# PLUGINDIR=/opt/nikto/plugins # Location of plugin dir | ||
| 23 | -# DBDIR=/opt/nikto/databases # Location of database dir | ||
| 24 | -# TEMPLATEDIR=/opt/nikto/templates # Location of template dir | ||
| 25 | -# DOCDIR=/opt/nikto/docs # Location of docs dir | ||
| 26 | +EXECDIR=/usr/bin/nikto # Location of Nikto | ||
| 27 | +PLUGINDIR=/etc/nikto/plugins # Location of plugin dir | ||
| 28 | +DBDIR=/etc/nikto/databases # Location of database dir | ||
| 29 | +TEMPLATEDIR=/etc/nikto/templates # Location of template dir | ||
| 30 | +DOCDIR=/usr/share/doc/nikto # Location of docs dir | ||
| 31 | |||
| 32 | # Default plugin macros | ||
| 33 | # Remove plugins designed to be run standalone | ||
| 34 | -- | ||
| 35 | 2.7.4 | ||
| 36 | |||
diff --git a/dynamic-layers/meta-perl/recipes-security/nikto/nikto_2.1.6.bb b/dynamic-layers/meta-perl/recipes-security/nikto/nikto_2.1.6.bb new file mode 100644 index 0000000..8c21b30 --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/nikto/nikto_2.1.6.bb | |||
| @@ -0,0 +1,118 @@ | |||
| 1 | SUMMARY = "web server scanner" | ||
| 2 | DESCRIPTION = "Nikto is an Open Source web server scanner which performs comprehensive tests against web servers" | ||
| 3 | SECTION = "security" | ||
| 4 | HOMEPAGE = "https://cirt.net/Nikto2" | ||
| 5 | |||
| 6 | LICENSE = "GPL-2.0-only" | ||
| 7 | LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0-only;md5=801f80980d171dd6425610833a22dbe6" | ||
| 8 | |||
| 9 | SRCREV = "f1bbd1a8756c076c8fd4f4dd0bc34a8ef215ae79" | ||
| 10 | SRC_URI = "git://github.com/sullo/nikto.git;branch=master;protocol=https \ | ||
| 11 | file://location.patch" | ||
| 12 | |||
| 13 | S = "${WORKDIR}/git/program" | ||
| 14 | |||
| 15 | do_install() { | ||
| 16 | install -d ${D}${bindir} | ||
| 17 | install -d ${D}${datadir} | ||
| 18 | install -d ${D}${datadir}/man/man1 | ||
| 19 | install -d ${D}${datadir}/doc/nikto | ||
| 20 | install -d ${D}${sysconfdir}/nikto | ||
| 21 | install -d ${D}${sysconfdir}/nikto/databases | ||
| 22 | install -d ${D}${sysconfdir}/nikto/plugins | ||
| 23 | install -d ${D}${sysconfdir}/nikto/templates | ||
| 24 | |||
| 25 | install -m 0644 databases/db_404_strings ${D}${sysconfdir}/nikto/databases | ||
| 26 | install -m 0644 databases/db_content_search ${D}${sysconfdir}/nikto/databases | ||
| 27 | install -m 0644 databases/db_dictionary ${D}${sysconfdir}/nikto/databases | ||
| 28 | install -m 0644 databases/db_dir_traversal ${D}${sysconfdir}/nikto/databases | ||
| 29 | install -m 0644 databases/db_domino ${D}${sysconfdir}/nikto/databases | ||
| 30 | install -m 0644 databases/db_drupal ${D}${sysconfdir}/nikto/databases | ||
| 31 | install -m 0644 databases/db_embedded ${D}${sysconfdir}/nikto/databases | ||
| 32 | install -m 0644 databases/db_favicon ${D}${sysconfdir}/nikto/databases | ||
| 33 | install -m 0644 databases/db_headers ${D}${sysconfdir}/nikto/databases | ||
| 34 | install -m 0644 databases/db_httpoptions ${D}${sysconfdir}/nikto/databases | ||
| 35 | install -m 0644 databases/db_multiple_index ${D}${sysconfdir}/nikto/databases | ||
| 36 | install -m 0644 databases/db_outdated ${D}${sysconfdir}/nikto/databases | ||
| 37 | install -m 0644 databases/db_parked_strings ${D}${sysconfdir}/nikto/databases | ||
| 38 | install -m 0644 databases/db_realms ${D}${sysconfdir}/nikto/databases | ||
| 39 | install -m 0644 databases/db_server_msgs ${D}${sysconfdir}/nikto/databases | ||
| 40 | install -m 0644 databases/db_tests ${D}${sysconfdir}/nikto/databases | ||
| 41 | install -m 0644 databases/db_variables ${D}${sysconfdir}/nikto/databases | ||
| 42 | |||
| 43 | install -m 0644 plugins/LW2.pm ${D}${sysconfdir}/nikto/plugins | ||
| 44 | install -m 0644 plugins/nikto_apache_expect_xss.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 45 | install -m 0644 plugins/nikto_apacheusers.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 46 | install -m 0644 plugins/nikto_auth.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 47 | install -m 0644 plugins/nikto_cgi.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 48 | install -m 0644 plugins/nikto_clientaccesspolicy.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 49 | install -m 0644 plugins/nikto_content_search.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 50 | install -m 0644 plugins/nikto_cookies.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 51 | install -m 0644 plugins/nikto_core.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 52 | install -m 0644 plugins/nikto_dictionary_attack.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 53 | install -m 0644 plugins/nikto_dir_traversal.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 54 | install -m 0644 plugins/nikto_dishwasher.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 55 | install -m 0644 plugins/nikto_docker_registry.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 56 | install -m 0644 plugins/nikto_domino.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 57 | install -m 0644 plugins/nikto_drupal.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 58 | install -m 0644 plugins/nikto_embedded.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 59 | install -m 0644 plugins/nikto_favicon.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 60 | install -m 0644 plugins/nikto_fileops.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 61 | install -m 0644 plugins/nikto_headers.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 62 | install -m 0644 plugins/nikto_httpoptions.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 63 | install -m 0644 plugins/nikto_ms10_070.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 64 | install -m 0644 plugins/nikto_msgs.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 65 | install -m 0644 plugins/nikto_multiple_index.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 66 | install -m 0644 plugins/nikto_negotiate.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 67 | install -m 0644 plugins/nikto_origin_reflection.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 68 | install -m 0644 plugins/nikto_outdated.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 69 | install -m 0644 plugins/nikto_parked.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 70 | install -m 0644 plugins/nikto_paths.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 71 | install -m 0644 plugins/nikto_put_del_test.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 72 | install -m 0644 plugins/nikto_report_csv.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 73 | install -m 0644 plugins/nikto_report_html.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 74 | install -m 0644 plugins/nikto_report_json.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 75 | install -m 0644 plugins/nikto_report_nbe.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 76 | install -m 0644 plugins/nikto_report_sqlg.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 77 | install -m 0644 plugins/nikto_report_text.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 78 | install -m 0644 plugins/nikto_report_xml.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 79 | install -m 0644 plugins/nikto_robots.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 80 | install -m 0644 plugins/nikto_siebel.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 81 | install -m 0644 plugins/nikto_sitefiles.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 82 | install -m 0644 plugins/nikto_ssl.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 83 | install -m 0644 plugins/nikto_strutshock.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 84 | install -m 0644 plugins/nikto_tests.plugin ${D}${sysconfdir}/nikto/plugins | ||
| 85 | |||
| 86 | install -m 0644 templates/htm_close.tmpl ${D}${sysconfdir}/nikto/templates | ||
| 87 | install -m 0644 templates/htm_end.tmpl ${D}${sysconfdir}/nikto/templates | ||
| 88 | install -m 0644 templates/htm_host_head.tmpl ${D}${sysconfdir}/nikto/templates | ||
| 89 | install -m 0644 templates/htm_host_im.tmpl ${D}${sysconfdir}/nikto/templates | ||
| 90 | install -m 0644 templates/htm_host_item.tmpl ${D}${sysconfdir}/nikto/templates | ||
| 91 | install -m 0644 templates/htm_start.tmpl ${D}${sysconfdir}/nikto/templates | ||
| 92 | install -m 0644 templates/htm_stop.tmpl ${D}${sysconfdir}/nikto/templates | ||
| 93 | install -m 0644 templates/htm_start.tmpl ${D}${sysconfdir}/nikto/templates | ||
| 94 | install -m 0644 templates/htm_summary.tmpl ${D}${sysconfdir}/nikto/templates | ||
| 95 | install -m 0644 templates/xml_end.tmpl ${D}${sysconfdir}/nikto/templates | ||
| 96 | install -m 0644 templates/xml_host_head.tmpl ${D}${sysconfdir}/nikto/templates | ||
| 97 | install -m 0644 templates/xml_host_im.tmpl ${D}${sysconfdir}/nikto/templates | ||
| 98 | install -m 0644 templates/xml_host_item.tmpl ${D}${sysconfdir}/nikto/templates | ||
| 99 | install -m 0644 templates/xml_start.tmpl ${D}${sysconfdir}/nikto/templates | ||
| 100 | install -m 0644 templates/xml_summary.tmpl ${D}${sysconfdir}/nikto/templates | ||
| 101 | |||
| 102 | install -m 0644 nikto.conf ${D}${sysconfdir} | ||
| 103 | |||
| 104 | install -m 0755 nikto.pl ${D}${bindir}/nikto | ||
| 105 | install -m 0644 replay.pl ${D}${bindir} | ||
| 106 | install -m 0644 docs/nikto.1 ${D}${datadir}/man/man1 | ||
| 107 | |||
| 108 | install -m 0644 docs/CHANGES.txt ${D}${datadir}/doc/nikto | ||
| 109 | install -m 0644 docs/LICENSE.txt ${D}${datadir}/doc/nikto | ||
| 110 | install -m 0644 docs/nikto.dtd ${D}${datadir}/doc/nikto | ||
| 111 | install -m 0644 docs/nikto_manual.html ${D}${datadir}/doc/nikto | ||
| 112 | } | ||
| 113 | |||
| 114 | RDEPENDS:${PN} = "perl libnet-ssleay-perl libwhisker2-perl \ | ||
| 115 | perl-module-getopt-long perl-module-time-local \ | ||
| 116 | perl-module-io-socket perl-module-overloading \ | ||
| 117 | perl-module-base perl-module-b perl-module-bytes" | ||
| 118 | |||
