diff options
Diffstat (limited to 'meta-security/recipes-security')
159 files changed, 20447 insertions, 0 deletions
diff --git a/meta-security/recipes-security/AppArmor/apparmor_2.11.0.bb b/meta-security/recipes-security/AppArmor/apparmor_2.11.0.bb new file mode 100644 index 000000000..fc9b614f1 --- /dev/null +++ b/meta-security/recipes-security/AppArmor/apparmor_2.11.0.bb @@ -0,0 +1,159 @@ +SUMMARY = "AppArmor another MAC control system" +DESCRIPTION = "user-space parser utility for AppArmor \ + This provides the system initialization scripts needed to use the \ + AppArmor Mandatory Access Control system, including the AppArmor Parser \ + which is required to convert AppArmor text profiles into machine-readable \ + policies that are loaded into the kernel for use with the AppArmor Linux \ + Security Module." +HOMEAPAGE = "http://apparmor.net/" +SECTION = "admin" + +LICENSE = "GPLv2 & GPLv2+ & BSD-3-Clause & LGPLv2.1+" +LIC_FILES_CHKSUM = "file://${S}/LICENSE;md5=fd57a4b0bc782d7b80fd431f10bbf9d0" + +DEPENDS = "bison-native apr gettext-native coreutils-native" + +SRC_URI = " \ + http://archive.ubuntu.com/ubuntu/pool/main/a/${BPN}/${BPN}_${PV}.orig.tar.gz \ + file://disable_perl_h_check.patch \ + file://crosscompile_perl_bindings.patch \ + file://apparmor.rc \ + file://functions \ + file://apparmor \ + file://apparmor.service \ + file://run-ptest \ + " + +SRC_URI[md5sum] = "899fd834dc5c8ebf2d52b97e4a174af7" +SRC_URI[sha256sum] = "b1c489ea11e7771b8e6b181532cafbf9ebe6603e3cb00e2558f21b7a5bdd739a" + +PARALLEL_MAKE = "" + +inherit pkgconfig autotools-brokensep update-rc.d python3native perlnative ptest cpan +inherit ${@bb.utils.contains('VIRTUAL-RUNTIME_init_manager','systemd','systemd','', d)} + +S = "${WORKDIR}/apparmor-${PV}" + +PACKAGECONFIG ?="man python perl" +PACKAGECONFIG[man] = "--enable-man-pages, --disable-man-pages" +PACKAGECONFIG[python] = "--with-python, --without-python, python3 swig-native" +PACKAGECONFIG[perl] = "--with-perl, --without-perl, perl perl-native swig-native" +PACKAGECONFIG[apache2] = ",,apache2," + +PAMLIB="${@bb.utils.contains('DISTRO_FEATURES', 'pam', '1', '0', d)}" +HTTPD="${@bb.utils.contains('PACKAGECONFIG', 'apache2', '1', '0', d)}" + + +python() { + if 'apache2' in d.getVar('PACKAGECONFIG').split() and \ + 'webserver' not in d.getVar('BBFILE_COLLECTIONS').split(): + raise bb.parse.SkipRecipe('Requires meta-webserver to be present.') +} + +CONFIGUREOPTS_remove = "--disable-static" +EXTRA_OECONF_append = " --enable-static" + +do_configure() { + cd ${S}/libraries/libapparmor + aclocal + autoconf --force + libtoolize --automake -c --force + automake -ac + ./configure ${CONFIGUREOPTS} ${EXTRA_OECONF} + sed -i -e 's#^YACC.*#YACC := bison#' ${S}/parser/Makefile + sed -i -e 's#^LEX.*#LEX := flex#' ${S}/parser/Makefile +} + +do_compile () { + oe_runmake -C ${B}/libraries/libapparmor + oe_runmake -C ${B}/binutils + oe_runmake -C ${B}/utils + oe_runmake -C ${B}/parser + oe_runmake -C ${B}/profiles + + if test -z "${HTTPD}" ; then + oe_runmake -C ${B}/changehat/mod_apparmor + fi + + if test -z "${PAMLIB}" ; then + oe_runmake -C ${B}/changehat/pam_apparmor + fi +} + +do_install () { + install -d ${D}/${INIT_D_DIR} + install -d ${D}/lib/apparmor + + oe_runmake -C ${B}/libraries/libapparmor DESTDIR="${D}" install + oe_runmake -C ${B}/binutils DESTDIR="${D}" install + oe_runmake -C ${B}/utils DESTDIR="${D}" install + oe_runmake -C ${B}/parser DESTDIR="${D}" install + oe_runmake -C ${B}/profiles DESTDIR="${D}" install + + if test -z "${HTTPD}" ; then + oe_runmake -C ${B}/changehat/mod_apparmor DESTDIR="${D}" install + fi + + if test -z "${PAMLIB}" ; then + oe_runmake -C ${B}/changehat/pam_apparmor DESTDIR="${D}" install + fi + + # aa-easyprof is installed by python-tools-setup.py, fix it up + sed -i -e 's:/usr/bin/env.*:/usr/bin/python3:' ${D}${bindir}/aa-easyprof + chmod 0755 ${D}${bindir}/aa-easyprof + + install ${WORKDIR}/apparmor ${D}/${INIT_D_DIR}/apparmor + install ${WORKDIR}/functions ${D}/lib/apparmor + if [ "${VIRTUAL-RUNTIME_init_manager}" = "systemd" ]; then + install -d ${D}${systemd_system_unitdir} + install ${WORKDIR}/apparmor.service \ + ${D}${systemd_system_unitdir} + fi +} + +do_compile_ptest () { + oe_runmake -C ${B}/tests/regression/apparmor + oe_runmake -C ${B}/parser/tst + oe_runmake -C ${B}/libraries/libapparmor +} + +do_install_ptest () { + t=${D}/${PTEST_PATH}/testsuite + install -d ${t} + install -d ${t}/tests/regression/apparmor + cp -rf ${B}/tests/regression/apparmor ${t}/tests/regression + + install -d ${t}/parser/tst + cp -rf ${B}/parser/tst ${t}/parser + cp ${B}/parser/apparmor_parser ${t}/parser + cp ${B}/parser/frob_slack_rc ${t}/parser + + install -d ${t}/libraries/libapparmor + cp -rf ${B}/libraries/libapparmor ${t}/libraries + + install -d ${t}/common + cp -rf ${B}/common ${t} + + install -d ${t}/binutils + cp -rf ${B}/binutils ${t} +} + +INITSCRIPT_PACKAGES = "${PN}" +INITSCRIPT_NAME = "apparmor" +INITSCRIPT_PARAMS = "start 16 2 3 4 5 . stop 35 0 1 6 ." + +SYSTEMD_PACKAGES = "${PN}" +SYSTEMD_SERVICE_${PN} = "apparmor.service" +SYSTEMD_AUTO_ENABLE = "disable" + +PACKAGES += "${@bb.utils.contains('PACKAGECONFIG', 'apache2', 'mod-${PN}', '', d)}" + +FILES_${PN} += "/lib/apparmor/ ${sysconfdir}/apparmor ${PYTHON_SITEPACKAGES_DIR}" +FILES_mod-${PN} = "${libdir}/apache2/modules/*" + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "bash lsb" +RDEPENDS_${PN} += "${@bb.utils.contains('PACKAGECONFIG','python','python3 python3-modules','', d)}" +RDEPENDS_${PN}_remove += "${@bb.utils.contains('PACKAGECONFIG','perl','','perl', d)}" +RDEPENDS_${PN}-ptest += "perl coreutils dbus-lib" diff --git a/meta-security/recipes-security/AppArmor/files/apparmor b/meta-security/recipes-security/AppArmor/files/apparmor new file mode 100644 index 000000000..ac3ab9a4a --- /dev/null +++ b/meta-security/recipes-security/AppArmor/files/apparmor @@ -0,0 +1,227 @@ +#!/bin/sh +# ---------------------------------------------------------------------- +# Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 +# NOVELL (All rights reserved) +# Copyright (c) 2008, 2009 Canonical, Ltd. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of version 2 of the GNU General Public +# License published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, contact Novell, Inc. +# ---------------------------------------------------------------------- +# Authors: +# Steve Beattie <steve.beattie@canonical.com> +# Kees Cook <kees@ubuntu.com> +# +# /etc/init.d/apparmor +# +### BEGIN INIT INFO +# Provides: apparmor +# Required-Start: $local_fs +# Required-Stop: umountfs +# Default-Start: S +# Default-Stop: +# Short-Description: AppArmor initialization +# Description: AppArmor init script. This script loads all AppArmor profiles. +### END INIT INFO + +log_daemon_msg() { + echo $* +} + +log_end_msg () { + retval=$1 + if [ $retval -eq 0 ]; then + echo "." + else + echo " failed!" + fi + return $retval +} + +. /lib/apparmor/functions +. /lib/lsb/init-functions + +usage() { + echo "Usage: $0 {start|stop|restart|reload|force-reload|status|recache}" +} + +test -x ${PARSER} || exit 0 # by debian policy +# LSM is built-in, so it is either there or not enabled for this boot +test -d /sys/module/apparmor || exit 0 + +securityfs() { + # Need securityfs for any mode + if [ ! -d "${AA_SFS}" ]; then + if cut -d" " -f2,3 /proc/mounts | grep -q "^${SECURITYFS} securityfs"'$' ; then + log_daemon_msg "AppArmor not available as kernel LSM." + log_end_msg 1 + exit 1 + else + log_daemon_msg "Mounting securityfs on ${SECURITYFS}" + if ! mount -t securityfs none "${SECURITYFS}"; then + log_end_msg 1 + exit 1 + fi + fi + fi + if [ ! -w "$AA_SFS"/.load ]; then + log_daemon_msg "Insufficient privileges to change profiles." + log_end_msg 1 + exit 1 + fi +} + +handle_system_policy_package_updates() { + apparmor_was_updated=0 + + if ! compare_previous_version ; then + # On snappy flavors, if the current and previous versions are + # different then clear the system cache. snappy will handle + # "$PROFILES_CACHE_VAR" itself (on Touch flavors + # compare_previous_version always returns '0' since snappy + # isn't available). + clear_cache_system + apparmor_was_updated=1 + elif ! compare_and_save_debsums apparmor ; then + # If the system policy has been updated since the last time we + # ran, clear the cache to prevent potentially stale binary + # cache files after an Ubuntu image based upgrade (LP: + # #1350673). This can be removed once all system image flavors + # move to snappy (on snappy systems compare_and_save_debsums + # always returns '0' since /var/lib/dpkg doesn't exist). + clear_cache + apparmor_was_updated=1 + fi + + if [ -x /usr/bin/aa-clickhook ] || [ -x /usr/bin/aa-profile-hook ] ; then + # If packages for system policy that affect click packages have + # been updated since the last time we ran, run aa-clickhook -f + force_clickhook=0 + force_profile_hook=0 + if ! compare_and_save_debsums apparmor-easyprof-ubuntu ; then + force_clickhook=1 + fi + if ! compare_and_save_debsums apparmor-easyprof-ubuntu-snappy ; then + force_clickhook=1 + fi + if ! compare_and_save_debsums click-apparmor ; then + force_clickhook=1 + force_profile_hook=1 + fi + if [ -x /usr/bin/aa-clickhook ] && ([ $force_clickhook -eq 1 ] || [ $apparmor_was_updated -eq 1 ]) ; then + aa-clickhook -f + fi + if [ -x /usr/bin/aa-profile-hook ] && ([ $force_profile_hook -eq 1 ] || [ $apparmor_was_updated -eq 1 ]) ; then + aa-profile-hook -f + fi + fi +} + +# Allow "recache" even when running on the liveCD +if [ "$1" = "recache" ]; then + log_daemon_msg "Recaching AppArmor profiles" + recache_profiles + rc=$? + log_end_msg "$rc" + exit $rc +fi + +# do not perform start/stop/reload actions when running from liveCD +test -d /rofs/etc/apparmor.d && exit 0 + +rc=255 +case "$1" in + start) + if test -x /sbin/systemd-detect-virt && \ + systemd-detect-virt --quiet --container && \ + ! is_container_with_internal_policy; then + log_daemon_msg "Not starting AppArmor in container" + log_end_msg 0 + exit 0 + fi + log_daemon_msg "Starting AppArmor profiles" + securityfs + # That is only useful for click, snappy and system images, + # i.e. not in Debian. And it reads and writes to /var, that + # can be remote-mounted, so it would prevent us from using + # Before=sysinit.target without possibly introducing dependency + # loops. + handle_system_policy_package_updates + load_configured_profiles + rc=$? + log_end_msg "$rc" + ;; + stop) + log_daemon_msg "Clearing AppArmor profiles cache" + clear_cache + rc=$? + log_end_msg "$rc" + cat >&2 <<EOM +All profile caches have been cleared, but no profiles have been unloaded. +Unloading profiles will leave already running processes permanently +unconfined, which can lead to unexpected situations. + +To set a process to complain mode, use the command line tool +'aa-complain'. To really tear down all profiles, run the init script +with the 'teardown' option." +EOM + ;; + teardown) + if test -x /sbin/systemd-detect-virt && \ + systemd-detect-virt --quiet --container && \ + ! is_container_with_internal_policy; then + log_daemon_msg "Not tearing down AppArmor in container" + log_end_msg 0 + exit 0 + fi + log_daemon_msg "Unloading AppArmor profiles" + securityfs + running_profile_names | while read profile; do + if ! unload_profile "$profile" ; then + log_end_msg 1 + exit 1 + fi + done + rc=0 + log_end_msg $rc + ;; + restart|reload|force-reload) + if test -x /sbin/systemd-detect-virt && \ + systemd-detect-virt --quiet --container && \ + ! is_container_with_internal_policy; then + log_daemon_msg "Not reloading AppArmor in container" + log_end_msg 0 + exit 0 + fi + log_daemon_msg "Reloading AppArmor profiles" + securityfs + clear_cache + load_configured_profiles + rc=$? + unload_obsolete_profiles + + log_end_msg "$rc" + ;; + status) + securityfs + if [ -x /usr/sbin/aa-status ]; then + aa-status --verbose + else + cat "$AA_SFS"/profiles + fi + rc=$? + ;; + *) + usage + rc=1 + ;; + esac +exit $rc diff --git a/meta-security/recipes-security/AppArmor/files/apparmor.rc b/meta-security/recipes-security/AppArmor/files/apparmor.rc new file mode 100644 index 000000000..1507d7b5f --- /dev/null +++ b/meta-security/recipes-security/AppArmor/files/apparmor.rc @@ -0,0 +1,98 @@ +description "Pre-cache and pre-load apparmor profiles" +author "Dimitri John Ledkov <xnox@ubuntu.com> and Jamie Strandboge <jamie@ubuntu.com>" + +task + +start on starting rc-sysinit + +script + [ -d /rofs/etc/apparmor.d ] && exit 0 # do not load on liveCD + [ -d /sys/module/apparmor ] || exit 0 # do not load without AppArmor + [ -x /sbin/apparmor_parser ] || exit 0 # do not load without parser + + . /lib/apparmor/functions + + systemd-detect-virt --quiet --container && ! is_container_with_internal_policy && exit 0 || true + + # Need securityfs for any mode + if [ ! -d /sys/kernel/security/apparmor ]; then + if cut -d" " -f2,3 /proc/mounts | grep -q "^/sys/kernel/security securityfs"'$' ; then + exit 0 + else + mount -t securityfs none /sys/kernel/security || exit 0 + fi + fi + + [ -w /sys/kernel/security/apparmor/.load ] || exit 0 + + apparmor_was_updated=0 + if ! compare_previous_version ; then + # On snappy flavors, if the current and previous versions are + # different then clear the system cache. snappy will handle + # "$PROFILES_CACHE_VAR" itself (on Touch flavors + # compare_previous_version always returns '0' since snappy + # isn't available). + clear_cache_system + apparmor_was_updated=1 + elif ! compare_and_save_debsums apparmor ; then + # If the system policy has been updated since the last time we + # ran, clear the cache to prevent potentially stale binary + # cache files after an Ubuntu image based upgrade (LP: + # #1350673). This can be removed once all system image flavors + # move to snappy (on snappy systems compare_and_save_debsums + # always returns '0' since /var/lib/dpkg doesn't exist). + clear_cache + apparmor_was_updated=1 + fi + + if [ -x /usr/bin/aa-clickhook ] || [ -x /usr/bin/aa-profile-hook ] ; then + # If packages for system policy that affect click packages have + # been updated since the last time we ran, run aa-clickhook -f + force_clickhook=0 + force_profile_hook=0 + if ! compare_and_save_debsums apparmor-easyprof-ubuntu ; then + force_clickhook=1 + fi + if ! compare_and_save_debsums apparmor-easyprof-ubuntu-snappy ; then + force_clickhook=1 + fi + if ! compare_and_save_debsums click-apparmor ; then + force_clickhook=1 + force_profile_hook=1 + fi + if [ -x /usr/bin/aa-clickhook ] && ([ $force_clickhook -eq 1 ] || [ $apparmor_was_updated -eq 1 ]) ; then + aa-clickhook -f + fi + if [ -x /usr/bin/aa-profile-hook ] && ([ $force_profile_hook -eq 1 ] || [ $apparmor_was_updated -eq 1 ]) ; then + aa-profile-hook -f + fi + fi + + if [ "$ACTION" = "teardown" ]; then + running_profile_names | while read profile; do + unload_profile "$profile" + done + exit 0 + fi + + if [ "$ACTION" = "clear" ]; then + clear_cache + exit 0 + fi + + if [ "$ACTION" = "reload" ] || [ "$ACTION" = "force-reload" ]; then + clear_cache + load_configured_profiles + unload_obsolete_profiles + exit 0 + fi + + # Note: if apparmor-easyprof-ubuntu md5sums didn't match up above, + # aa-clickhook will have already compiled the policy, generated the cache + # files and loaded them into the kernel by this point, so reloading click + # policy from cache, while fairly fast (<2 seconds for 250 profiles on + # armhf), is redundant. Fixing this would complicate the logic quite a bit + # and it wouldn't improve the (by far) common case (ie, when + # 'aa-clickhook -f' is not run). + load_configured_profiles +end script diff --git a/meta-security/recipes-security/AppArmor/files/apparmor.service b/meta-security/recipes-security/AppArmor/files/apparmor.service new file mode 100644 index 000000000..e66afe4e1 --- /dev/null +++ b/meta-security/recipes-security/AppArmor/files/apparmor.service @@ -0,0 +1,22 @@ +[Unit] +Description=AppArmor initialization +After=local-fs.target +Before=sysinit.target +AssertPathIsReadWrite=/sys/kernel/security/apparmor/.load +ConditionSecurity=apparmor +DefaultDependencies=no +Documentation=man:apparmor(7) +Documentation=http://wiki.apparmor.net/ + +# Don't start this unit on the Ubuntu Live CD +ConditionPathExists=!/rofs/etc/apparmor.d + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/etc/init.d/apparmor start +ExecStop=/etc/init.d/apparmor stop +ExecReload=/etc/init.d/apparmor reload + +[Install] +WantedBy=sysinit.target diff --git a/meta-security/recipes-security/AppArmor/files/crosscompile_perl_bindings.patch b/meta-security/recipes-security/AppArmor/files/crosscompile_perl_bindings.patch new file mode 100644 index 000000000..ef55de717 --- /dev/null +++ b/meta-security/recipes-security/AppArmor/files/crosscompile_perl_bindings.patch @@ -0,0 +1,25 @@ +Upstream-Status: Inappropriate [configuration] + +As we're cross-compiling here we need to override CC/LD that MakeMaker has +stuck in the generated Makefile with our cross tools. In this case, linking is +done via the compiler rather than the linker directly so pass in CC not LD +here. + +Signed-Off-By: Tom Rini <trini@konsulko.com> + +--- a/libraries/libapparmor/swig/perl/Makefile.am.orig 2017-06-13 19:04:43.296676212 -0400 ++++ b/libraries/libapparmor/swig/perl/Makefile.am 2017-06-13 19:05:03.488676693 -0400 +@@ -16,11 +16,11 @@ + + LibAppArmor.so: libapparmor_wrap.c Makefile.perl + if test ! -f libapparmor_wrap.c; then cp $(srcdir)/libapparmor_wrap.c . ; fi +- $(MAKE) -fMakefile.perl ++ $(MAKE) -fMakefile.perl CC='$(CC)' LD='$(CC)' + if test $(top_srcdir) != $(top_builddir) ; then rm -f libapparmor_wrap.c ; fi + + install-exec-local: Makefile.perl +- $(MAKE) -fMakefile.perl install_vendor ++ $(MAKE) -fMakefile.perl install_vendor CC='$(CC)' LD='$(CC)' + + # sadly there is no make uninstall for perl + #uninstall-local: Makefile.perl diff --git a/meta-security/recipes-security/AppArmor/files/disable_pdf.patch b/meta-security/recipes-security/AppArmor/files/disable_pdf.patch new file mode 100644 index 000000000..c6b4bddc2 --- /dev/null +++ b/meta-security/recipes-security/AppArmor/files/disable_pdf.patch @@ -0,0 +1,33 @@ +Index: apparmor-2.10.95/parser/Makefile +=================================================================== +--- apparmor-2.10.95.orig/parser/Makefile ++++ apparmor-2.10.95/parser/Makefile +@@ -139,17 +139,6 @@ export Q VERBOSE BUILD_OUTPUT + po/${NAME}.pot: ${SRCS} ${HDRS} + $(MAKE) -C po ${NAME}.pot NAME=${NAME} SOURCES="${SRCS} ${HDRS}" + +-techdoc.pdf: techdoc.tex +- timestamp=$(shell date --utc "+%Y%m%d%H%M%S%z" -r $< );\ +- while pdflatex "\def\fixedpdfdate{$$timestamp}\input $<" ${BUILD_OUTPUT} || exit 1 ; \ +- grep -q "Label(s) may have changed" techdoc.log; \ +- do :; done +- +-techdoc/index.html: techdoc.pdf +- latex2html -show_section_numbers -split 0 -noinfo -nonavigation -noaddress techdoc.tex ${BUILD_OUTPUT} +- +-techdoc.txt: techdoc/index.html +- w3m -dump $< > $@ + + # targets arranged this way so that people who don't want full docs can + # pick specific targets they want. +@@ -159,9 +148,7 @@ manpages: $(MANPAGES) + + htmlmanpages: $(HTMLMANPAGES) + +-pdf: techdoc.pdf +- +-docs: manpages htmlmanpages pdf ++docs: manpages htmlmanpages + + indep: docs + $(Q)$(MAKE) -C po all diff --git a/meta-security/recipes-security/AppArmor/files/disable_perl_h_check.patch b/meta-security/recipes-security/AppArmor/files/disable_perl_h_check.patch new file mode 100644 index 000000000..cf2640fce --- /dev/null +++ b/meta-security/recipes-security/AppArmor/files/disable_perl_h_check.patch @@ -0,0 +1,19 @@ +Upstream-Status: Inappropriate [configuration] + +Remove file check for $perl_includedir/perl.h. AC_CHECK_FILE will fail on +cross compilation. Rather than try and get a compile check to work here, +we know that we have what's required via our metadata so remove only this +check. + +Signed-Off-By: Tom Rini <trini@konsulko.com> + +--- a/libraries/libapparmor/configure.ac.orig 2017-06-13 16:41:38.668471495 -0400 ++++ b/libraries/libapparmor/configure.ac 2017-06-13 16:41:40.708471543 -0400 +@@ -58,7 +58,6 @@ + AC_PATH_PROG(PERL, perl) + test -z "$PERL" && AC_MSG_ERROR([perl is required when enabling perl bindings]) + perl_includedir="`$PERL -e 'use Config; print $Config{archlib}'`/CORE" +- AC_CHECK_FILE($perl_includedir/perl.h, enable_perl=yes, enable_perl=no) + fi + + diff --git a/meta-security/recipes-security/AppArmor/files/functions b/meta-security/recipes-security/AppArmor/files/functions new file mode 100644 index 000000000..cef8cfe7d --- /dev/null +++ b/meta-security/recipes-security/AppArmor/files/functions @@ -0,0 +1,271 @@ +# /lib/apparmor/functions for Debian -*- shell-script -*- +# ---------------------------------------------------------------------- +# Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 +# NOVELL (All rights reserved) +# Copyright (c) 2008-2010 Canonical, Ltd. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of version 2 of the GNU General Public +# License published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, contact Novell, Inc. +# ---------------------------------------------------------------------- +# Authors: +# Kees Cook <kees@ubuntu.com> + +PROFILES="/etc/apparmor.d" +PROFILES_CACHE="$PROFILES/cache" +PROFILES_VAR="/var/lib/apparmor/profiles" +PROFILES_SNAPPY="/var/lib/snapd/apparmor/profiles" +PROFILES_CACHE_VAR="/var/cache/apparmor" +PARSER="/sbin/apparmor_parser" +SECURITYFS="/sys/kernel/security" +export AA_SFS="$SECURITYFS/apparmor" + +# Suppress warnings when booting in quiet mode +quiet_arg="" +[ "${QUIET:-no}" = yes ] && quiet_arg="-q" +[ "${quiet:-n}" = y ] && quiet_arg="-q" + +foreach_configured_profile() { + rc_all="0" + for pdir in "$PROFILES" "$PROFILES_VAR" "$PROFILES_SNAPPY" ; do + if [ ! -d "$pdir" ]; then + continue + fi + num=`find "$pdir" -type f ! -name '*.md5sums' | wc -l` + if [ "$num" = "0" ]; then + continue + fi + + cache_dir="$PROFILES_CACHE" + if [ -d "$PROFILES_CACHE_VAR" ] && [ "$pdir" = "$PROFILES_VAR" ] || [ "$pdir" = "$PROFILES_SNAPPY" ]; then + cache_dir="$PROFILES_CACHE_VAR" + fi + cache_args="--cache-loc=$cache_dir" + if [ ! -d "$cache_dir" ]; then + cache_args= + fi + + # LP: #1383858 - expr tree simplification is too slow for + # Touch policy on ARM, so disable it for now + cache_extra_args= + if [ -d "$PROFILES_CACHE_VAR" ] && [ "$pdir" = "$PROFILES_VAR" ] || [ "$pdir" = "$PROFILES_SNAPPY" ]; then + cache_extra_args="-O no-expr-simplify" + fi + + # If need to compile everything, then use -n1 with xargs to + # take advantage of -P. When cache files are in use, omit -n1 + # since it is considerably faster on moderately sized profile + # sets to give the parser all the profiles to load at once + n1_args= + num=`find "$cache_dir" -type f ! -name '.features' | wc -l` + if [ "$num" = "0" ]; then + n1_args="-n1" + fi + + (ls -1 "$pdir" | egrep -v '(\.dpkg-(new|old|dist|bak)|~)$' | \ + while read profile; do + if [ -f "$pdir"/"$profile" ]; then + echo "$pdir"/"$profile" + fi + done) | \ + xargs $n1_args -d"\n" -P$(getconf _NPROCESSORS_ONLN) "$PARSER" "$@" $cache_args $cache_extra_args -- || { + rc_all="$?" + # FIXME: when the parser properly handles broken + # profiles (LP: #1377338), remove this if statement. + # For now, if the xargs returns with error, just run + # through everything with -n1. (This could be broken + # out and refactored, but this is temporary so make it + # easy to understand and revert) + if [ "$rc_all" != "0" ]; then + (ls -1 "$pdir" | \ + egrep -v '(\.dpkg-(new|old|dist|bak)|~)$' | \ + while read profile; do + if [ -f "$pdir"/"$profile" ]; then + echo "$pdir"/"$profile" + fi + done) | \ + xargs -n1 -d"\n" -P$(getconf _NPROCESSORS_ONLN) "$PARSER" "$@" $cache_args $cache_extra_args -- || { + rc_all="$?" + } + fi + } + done + return $rc_all +} + +load_configured_profiles() { + clear_cache_if_outdated + foreach_configured_profile $quiet_arg --write-cache --replace +} + +load_configured_profiles_without_caching() { + foreach_configured_profile $quiet_arg --replace +} + +recache_profiles() { + clear_cache + foreach_configured_profile $quiet_arg --write-cache --skip-kernel-load +} + +configured_profile_names() { + foreach_configured_profile $quiet_arg -N 2>/dev/null | LC_COLLATE=C sort | grep -v '//' +} + +running_profile_names() { + # Output a sorted list of loaded profiles, skipping libvirt's + # dynamically generated files + cat "$AA_SFS"/profiles | sed -e "s/ (\(enforce\|complain\))$//" | egrep -v '^libvirt-[0-9a-f\-]+$' | LC_COLLATE=C sort | grep -v '//' +} + +unload_profile() { + echo -n "$1" > "$AA_SFS"/.remove +} + +clear_cache() { + clear_cache_system + clear_cache_var +} + +clear_cache_system() { + find "$PROFILES_CACHE" -maxdepth 1 -type f -print0 | xargs -0 rm -f -- +} + +clear_cache_var() { + find "$PROFILES_CACHE_VAR" -maxdepth 1 -type f -print0 | xargs -0 rm -f -- +} + +read_features_dir() +{ + for f in `ls -AU "$1"` ; do + if [ -f "$1/$f" ] ; then + read -r KF < "$1/$f" || true + echo -n "$f {$KF } " + elif [ -d "$1/$f" ] ; then + echo -n "$f {" + KF=`read_features_dir "$1/$f"` || true + echo -n "$KF} " + fi + done +} + +clear_cache_if_outdated() { + if [ -r "$PROFILES_CACHE"/.features ]; then + if [ -d "$AA_SFS"/features ]; then + KERN_FEATURES=`read_features_dir "$AA_SFS"/features` + else + read -r KERN_FEATURES < "$AA_SFS"/features + fi + CACHE_FEATURES=`tr '\n' ' ' < "$PROFILES_CACHE"/.features` + if [ "$KERN_FEATURES" != "$CACHE_FEATURES" ]; then + clear_cache + fi + fi +} + +unload_obsolete_profiles() { + # Currently we must re-parse all the profiles to get policy names. :( + aa_configured=$(mktemp -t aa-XXXXXX) + configured_profile_names > "$aa_configured" || true + aa_loaded=$(mktemp -t aa-XXXXXX) + running_profile_names > "$aa_loaded" || true + LC_COLLATE=C comm -2 -3 "$aa_loaded" "$aa_configured" | while read profile ; do + unload_profile "$profile" + done + rm -f "$aa_configured" "$aa_loaded" +} + +# If the system debsum differs from the saved debsum, the new system debsum is +# saved and non-zero is returned. Returns 0 if the two debsums matched or if +# the system debsum file does not exist. This can be removed when system image +# flavors all move to snappy. +compare_and_save_debsums() { + pkg="$1" + + if [ -n $pkg ] && [ -d "$PROFILES_VAR" ]; then + sums="/var/lib/dpkg/info/${pkg}.md5sums" + # store saved md5sums in /var/lib/apparmor/profiles since + # /var/cache/apparmor might be cleared by apparmor + saved_sums="${PROFILES_VAR}/.${pkg}.md5sums" + + if [ -f "$sums" ] && \ + ! diff -q "$sums" "$saved_sums" 2>&1 >/dev/null ; then + cp -f "$sums" "$saved_sums" + return 1 + fi + fi + + return 0 +} + +compare_previous_version() { + installed="/usr/share/snappy/security-policy-version" + previous="/var/lib/snappy/security-policy-version" + + # When just $previous doesn't exist, assume this is a new system with + # no cache and don't do anything special. + if [ -f "$installed" ] && [ -f "$previous" ]; then + pv=`grep '^apparmor/' "$previous" | cut -d ' ' -f 2` + iv=`grep '^apparmor/' "$installed" | cut -d ' ' -f 2` + if [ -n "$iv" ] && [ -n "$pv" ] && [ "$iv" != "$pv" ]; then + # snappy updates $previous elsewhere, so just return + return 1 + fi + fi + + return 0 +} + +# Checks to see if the current container is capable of having internal AppArmor +# profiles that should be loaded. Callers of this function should have already +# verified that they're running inside of a container environment with +# something like `systemd-detect-virt --container`. +# +# The only known container environments capable of supporting internal policy +# are LXD and LXC environment. +# +# Returns 0 if the container environment is capable of having its own internal +# policy and non-zero otherwise. +# +# IMPORTANT: This function will return 0 in the case of a non-LXD/non-LXC +# system container technology being nested inside of a LXD/LXC container that +# utilized an AppArmor namespace and profile stacking. The reason 0 will be +# returned is because .ns_stacked will be "yes" and .ns_name will still match +# "lx[dc]-*" since the nested system container technology will not have set up +# a new AppArmor profile namespace. This will result in the nested system +# container's boot process to experience failed policy loads but the boot +# process should continue without any loss of functionality. This is an +# unsupported configuration that cannot be properly handled by this function. +is_container_with_internal_policy() { + local ns_stacked_path="${AA_SFS}/.ns_stacked" + local ns_name_path="${AA_SFS}/.ns_name" + local ns_stacked + local ns_name + + if ! [ -f "$ns_stacked_path" ] || ! [ -f "$ns_name_path" ]; then + return 1 + fi + + read -r ns_stacked < "$ns_stacked_path" + if [ "$ns_stacked" != "yes" ]; then + return 1 + fi + + # LXD and LXC set up AppArmor namespaces starting with "lxd-" and + # "lxc-", respectively. Return non-zero for all other namespace + # identifiers. + read -r ns_name < "$ns_name_path" + if [ "${ns_name#lxd-*}" = "$ns_name" ] && \ + [ "${ns_name#lxc-*}" = "$ns_name" ]; then + return 1 + fi + + return 0 +} diff --git a/meta-security/recipes-security/AppArmor/files/run-ptest b/meta-security/recipes-security/AppArmor/files/run-ptest new file mode 100644 index 000000000..3b8e427eb --- /dev/null +++ b/meta-security/recipes-security/AppArmor/files/run-ptest @@ -0,0 +1,4 @@ +#! /bin/sh +cd testsuite + +make -C tests/regression/apparmor tests diff --git a/meta-security/recipes-security/aircrack-ng/aircrack-ng_1.2.bb b/meta-security/recipes-security/aircrack-ng/aircrack-ng_1.2.bb new file mode 100644 index 000000000..4df072e0b --- /dev/null +++ b/meta-security/recipes-security/aircrack-ng/aircrack-ng_1.2.bb @@ -0,0 +1,37 @@ +SUMMARY = "Aircrack-ng is a set of tools for auditing wireless networks" +DESCRIPTION = "Aircrack-ng is an 802.11 WEP and WPA-PSK keys cracking program that can recover keys once enough data packets have been captured. It implements the standard FMS attack along with some optimizations like KoreK attacks, as well as the PTW attack, thus making the attack much faster compared to other WEP cracking tools." +SECTION = "security" +LICENSE = "GPL-2.0" + +LIC_FILES_CHKSUM = "file://LICENSE;beginline=1;endline=2;md5=1fbd81241fe252ec0f5658a521ab7dd8" + +DEPENDS = "libnl openssl sqlite3 libpcre libpcap" +RC = "rc2" +SRC_URI = "http://download.aircrack-ng.org/${BP}-${RC}.tar.gz \ + file://fixup_cflags.patch" + +SRC_URI[md5sum] = "ebe9d537f06f4d6956213af09c4476da" +SRC_URI[sha256sum] = "ba5b3eda44254efc5b7c9f776eb756f7cc323ad5d0813c101e92edb483d157e9" + +inherit autotools-brokensep pkgconfig + +S = "${WORKDIR}/${BP}-rc2" + +PACKAGECONFIG ?= "" +CFLAGS += " -I${S}/src/include" + +OEMAKE_EXTRA = "sqlite=true experimental=true pcre=true \ + prefix=${prefix} \ + " + +do_compile () { + make ${OEMAKE_EXTRA} TOOL_PREFIX=${TARGET_SYS}- +} + +do_install () { + make DESTDIR=${D} ${OEMAKE_EXTRA} ext_scripts=true install +} + +FILES_${PN} += "/usr/local/" + +RDEPENDS_${PN} = "libpcap" diff --git a/meta-security/recipes-security/aircrack-ng/files/fixup_cflags.patch b/meta-security/recipes-security/aircrack-ng/files/fixup_cflags.patch new file mode 100644 index 000000000..e13dd24ba --- /dev/null +++ b/meta-security/recipes-security/aircrack-ng/files/fixup_cflags.patch @@ -0,0 +1,28 @@ +Upstream Status: Iinappropriate + +Issues do to build env. + +Signed-off-by: Armin Kuster <akuster808@gmail.com> + +Index: aircrack-ng-1.2-rc2/src/Makefile +=================================================================== +--- aircrack-ng-1.2-rc2.orig/src/Makefile ++++ aircrack-ng-1.2-rc2/src/Makefile +@@ -3,8 +3,6 @@ include $(AC_ROOT)/common.mak + + TEST_DIR = $(AC_ROOT)/test + +-CFLAGS += -Iinclude +- + iCC = $(shell find /opt/intel/cc/*/bin/icc) + iCFLAGS = -w -mcpu=pentiumpro -march=pentiumpro $(COMMON_CFLAGS) + iOPTFLAGS = -O3 -ip -ipo -D_FILE_OFFSET_BITS=64 +@@ -102,7 +100,7 @@ endif + + + ifeq ($(subst TRUE,true,$(filter TRUE true,$(sqlite) $(SQLITE))),true) +- LIBSQL = -L/usr/local/lib -lsqlite3 ++ LIBSQL = -lsqlite3 + else + LIBSQL = + endif diff --git a/meta-security/recipes-security/bastille/bastille_3.2.1.bb b/meta-security/recipes-security/bastille/bastille_3.2.1.bb new file mode 100644 index 000000000..eee1a38e1 --- /dev/null +++ b/meta-security/recipes-security/bastille/bastille_3.2.1.bb @@ -0,0 +1,157 @@ +#The functionality of Bastille that is actually available is restricted. Please +#consult the README file for the meta-security layer for additional information. +SUMMARY = "Linux hardening tool" +DESCRIPTION = "Bastille Linux is a Hardening and Reporting/Auditing Program which enhances the security of a Linux box, by configuring daemons, system settings and firewalling." +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://${S}/COPYING;md5=c93c0550bd3173f4504b2cbd8991e50b" +# Bash is needed for set +o privileged (check busybox), might also need ncurses +DEPENDS = "virtual/kernel" +RDEPENDS_${PN} = "perl bash tcl perl-module-getopt-long perl-module-text-wrap lib-perl perl-module-file-path perl-module-mime-base64 perl-module-file-find perl-module-errno perl-module-file-glob perl-module-tie-hash-namedcapture perl-module-file-copy perl-module-english perl-module-exporter perl-module-cwd libcurses-perl coreutils" +FILES_${PN} += "/run/lock/subsys/bastille" + +inherit allarch module-base + +SRC_URI = "http://sourceforge.net/projects/bastille-linux/files/bastille-linux/3.2.1/Bastille-3.2.1.tar.bz2 \ + file://AccountPermission.pm \ + file://FileContent.pm \ + file://HPSpecific.pm \ + file://Miscellaneous.pm \ + file://ServiceAdmin.pm \ + file://config \ + file://fix_version_parse.patch \ + file://fixed_defined_warnings.patch \ + file://call_output_config.patch \ + file://fix_missing_use_directives.patch \ + file://fix_number_of_modules.patch \ + file://remove_questions_text_file_references.patch \ + file://simplify_B_place.patch \ + file://find_existing_config.patch \ + file://upgrade_options_processing.patch \ + file://accept_os_flag_in_backend.patch \ + file://allow_os_with_assess.patch \ + file://edit_usage_message.patch \ + file://organize_distro_discovery.patch \ + file://do_not_apply_config.patch \ + " + +SRC_URI[md5sum] = "df803f7e38085aa5da79f85d0539f91b" +SRC_URI[sha256sum] = "0ea25191b1dc1c8f91e1b6f8cb5436a3aa1e57418809ef902293448efed5021a" + +S = "${WORKDIR}/Bastille" + +do_install () { + install -d ${D}${sbindir} + install -d ${D}${libdir}/perl/site_perl/Curses + ln -sf perl ${D}/${libdir}/perl5 + + install -d ${D}${libdir}/Bastille + install -d ${D}${libdir}/Bastille/API + install -d ${D}${datadir}/Bastille + install -d ${D}${datadir}/Bastille/OSMap + install -d ${D}${datadir}/Bastille/OSMap/Modules + install -d ${D}${datadir}/Bastille/Questions + install -d ${D}${datadir}/Bastille/FKL/configs/ + install -d ${D}${localstatedir}/lock/subsys/bastille + install -d ${D}${localstatedir}/log/Bastille + install -d ${D}${sysconfdir}/Bastille + install -m 0755 AutomatedBastille ${D}${sbindir} + install -m 0755 BastilleBackEnd ${D}${sbindir} + install -m 0755 InteractiveBastille ${D}${sbindir} + install -m 0644 Modules.txt ${D}${datadir}/Bastille + # New Weights file(s). + install -m 0644 Weights.txt ${D}${datadir}/Bastille + # Castle graphic + install -m 0644 bastille.jpg ${D}${datadir}/Bastille/ + # Javascript file + install -m 0644 wz_tooltip.js ${D}${datadir}/Bastille/ + install -m 0644 Credits ${D}${datadir}/Bastille + install -m 0644 FKL/configs/fkl_config_redhat.cfg ${D}${datadir}/Bastille/FKL/configs/ + install -m 0755 RevertBastille ${D}${sbindir} + install -m 0755 bin/bastille ${D}${sbindir} + install -m 0644 bastille-firewall ${D}${datadir}/Bastille + install -m 0644 bastille-firewall-reset ${D}${datadir}/Bastille + install -m 0644 bastille-firewall-schedule ${D}${datadir}/Bastille + install -m 0644 bastille-tmpdir-defense.sh ${D}${datadir}/Bastille + install -m 0644 bastille-tmpdir.csh ${D}${datadir}/Bastille + install -m 0644 bastille-tmpdir.sh ${D}${datadir}/Bastille + install -m 0644 bastille-firewall.cfg ${D}${datadir}/Bastille + install -m 0644 bastille-ipchains ${D}${datadir}/Bastille + install -m 0644 bastille-netfilter ${D}${datadir}/Bastille + install -m 0644 bastille-firewall-early.sh ${D}${datadir}/Bastille + install -m 0644 bastille-firewall-pre-audit.sh ${D}${datadir}/Bastille + install -m 0644 complete.xbm ${D}${datadir}/Bastille + install -m 0644 incomplete.xbm ${D}${datadir}/Bastille + install -m 0644 disabled.xpm ${D}${datadir}/Bastille + install -m 0644 ifup-local ${D}${datadir}/Bastille + install -m 0644 hosts.allow ${D}${datadir}/Bastille + + install -m 0644 Bastille/AccountSecurity.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/Apache.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/API.pm ${D}${libdir}/Bastille + install -m 0644 ${WORKDIR}/AccountPermission.pm ${D}${libdir}/Bastille/API + install -m 0644 ${WORKDIR}/FileContent.pm ${D}${libdir}/Bastille/API + install -m 0644 ${WORKDIR}/HPSpecific.pm ${D}${libdir}/Bastille/API + install -m 0644 ${WORKDIR}/ServiceAdmin.pm ${D}${libdir}/Bastille/API + install -m 0644 ${WORKDIR}/Miscellaneous.pm ${D}${libdir}/Bastille/API + install -m 0644 Bastille/BootSecurity.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/ConfigureMiscPAM.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/DisableUserTools.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/DNS.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/FilePermissions.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/FTP.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/Firewall.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/OSX_API.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/LogAPI.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/HP_UX.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/IOLoader.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/Patches.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/Logging.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/MiscellaneousDaemons.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/PatchDownload.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/Printing.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/PSAD.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/RemoteAccess.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/SecureInetd.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/Sendmail.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/TestDriver.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/TMPDIR.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/test_AccountSecurity.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/test_Apache.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/test_DNS.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/test_FTP.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/test_HP_UX.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/test_MiscellaneousDaemons.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/test_Patches.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/test_SecureInetd.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/test_Sendmail.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/test_BootSecurity.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/test_DisableUserTools.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/test_FilePermissions.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/test_Logging.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/test_Printing.pm ${D}${libdir}/Bastille + install -m 0644 Bastille/IPFilter.pm ${D}${libdir}/Bastille + install -m 0644 Bastille_Curses.pm ${D}${libdir}/perl5/site_perl + install -m 0644 Bastille_Tk.pm ${D}${libdir}/perl5/site_perl + install -m 0644 Curses/Widgets.pm ${D}${libdir}/perl5/site_perl/Curses + + install -m 0644 OSMap/LINUX.bastille ${D}${datadir}/Bastille/OSMap + install -m 0644 OSMap/LINUX.system ${D}${datadir}/Bastille/OSMap + install -m 0644 OSMap/LINUX.service ${D}${datadir}/Bastille/OSMap + install -m 0644 OSMap/HP-UX.bastille ${D}${datadir}/Bastille/OSMap + install -m 0644 OSMap/HP-UX.system ${D}${datadir}/Bastille/OSMap + install -m 0644 OSMap/HP-UX.service ${D}${datadir}/Bastille/OSMap + install -m 0644 OSMap/OSX.bastille ${D}${datadir}/Bastille/OSMap + install -m 0644 OSMap/OSX.system ${D}${datadir}/Bastille/OSMap + + install -m 0777 ${WORKDIR}/config ${D}${sysconfdir}/Bastille/config + + for file in `cat Modules.txt` ; do + install -m 0644 Questions/$file.txt ${D}${datadir}/Bastille/Questions + done + + ${THISDIR}/files/set_required_questions.py ${D}${sysconfdir}/Bastille/config ${D}${datadir}/Bastille/Questions + + ln -s RevertBastille ${D}${sbindir}/UndoBastille +} + +FILES_${PN} += "${datadir}/Bastille ${libdir}/Bastille ${libdir}/perl* ${sysconfdir}/*" diff --git a/meta-security/recipes-security/bastille/files/API.pm b/meta-security/recipes-security/bastille/files/API.pm new file mode 100644 index 000000000..5060f52a4 --- /dev/null +++ b/meta-security/recipes-security/bastille/files/API.pm @@ -0,0 +1,2528 @@ +# Copyright (C) 1999-2007 Jay Beale +# Copyright (C) 2001-2008 Hewlett-Packard Development Company, L.P. +# Licensed under the GNU General Public License, version 2 + +package Bastille::API; + +## TO DO: +# +# +# 1) Look for more places to insert error handling... +# +# 2) Document this module more +# +# + + +########################################################################## +# +# This module forms the basis for the v1.1 API. +# + ########################################################################## + +# +# This module forms the initial basis for the Bastille Engine, implemented +# presently via a Perl API for Perl modules. +# +# This is still under construction -- it is very usable, but not very well +# documented, yet. +# + +########################################################################## +# +# API Function Listing +# +########################################################################## +# The routines which should be called by Bastille modules are listed here, +# though they are better documented throughout this file. +# +# Distro Specific Stuff: +# +# &GetDistro - figures out what distro we're running, if it knows it... +# &ConfigureForDistro - sets global variables based on the distro +# &GetGlobal - returns hash values defined in ConfigureForDistro +# +# &getGlobalConfig - returns value of hash set up by ReadConfig +# +# Logging Specific Stuff has moved to LogAPI.pm: +# +# &B_log(type,msg) -- takes care of all logging +# +# +# Input functions for the old input method... +# +# File open/close/backup functions +# +# &B_open * -- opens a file handle and logs the action/error (OLD WAY!) +# &B_open_plus -- opens a pair of file handles for the old and new version +# of a file; respects logonly flag. (NEW WAY) +# &B_close * -- closes a file handle and logs the action/error (OLD WAY!) +# &B_close_plus -- closes a pair of file handles opened by B_open_plus, +# backing up one file and renaming the new file to the +# old one's name, logging actions/errors. Respects the +# logonly flag -- needs B_backup file. Finally, sets +# new file's mode,uid,gid to old file's... (NEW WAY) +# &B_backup_file - backs up a file that is being changed/deleted into the +# $GLOBAL_BDIR{"backup"} directory. +# +# Non-content file modification functions +# +# &B_delete_file - deletes the named file, backing up a copy +# &B_create_file - creates the named file, if it doesn't exist +# +# &B_symlink - create a symlink to a file, recording the revert rm +# +# More stuff +# +# &B_createdir - make a directory, if it doesn't exist, record revert rmdir +# &B_cp - copy a file, respecting LOGONLY and revert func. +# &B_mknod - wrap mknod with revert and logonly and prefix functionality +# +# &B_read_sums - reads sum.csv file and parses input into the GLOBAL_SUM hash +# &B_write_sums - writes sum.csv file from GLOBAL_SUM hash +# &B_check_sum($) - take a file name and compares the stored cksum with the current +# cksum of said file +# &B_set_sum($) - takes a file name and gets that files current cksum then sets +# that sum in the GLOBAL_SUM hash +# &B_revert_log - create entry in shell script, executed later by bastille -r +# &showDisclaimer - Print the disclaimer and wait for 5 minutes for acceptance +########################################################################### +# Note: GLOBAL_VERBOSE +# +# All logging functions now check GLOBAL_VERBOSE and, if set, will print +# all the information sent to log files to STDOUT/STDERR as well. +# + +# +# Note: GLOBAL_LOGONLY +# +# All Bastille API functions now check for the existence of a GLOBAL_LOGONLY +# variable. When said variable is set, no function actually modifies the +# system. +# +# Note: GLOBAL_DEBUG +# +# The B_log("DEBUG",...) function now checks GLOBAL_DEBUG and, if set, it will +# print all the information to a new debug-log file. If GLOBAL_VERBOSE is +# set it might log to STDOUT/STDERR as well (not yet implemented, pending +# discussion). Developers should populate appropriate places with &B_log(DEBUG) +# in order to be able to tell users to use this options and send the logs +# for inspection and debugging. +# +# + + +# Libraries for the Backup_file routine: Cwd and File::Path +use Cwd; +use Bastille::OSX_API; +use Bastille::LogAPI; +use File::Path; +use File::Basename; + +# Export the API functions listed below for use by the modules. + +use Exporter; +@ISA = qw ( Exporter ); +@EXPORT = qw( + setOptions GetDistro ConfigureForDistro B_log B_revert_log + SanitizeEnv + B_open B_close B_symlink StopLogging + B_open_plus B_close_plus + B_isFileinSumDB + B_create_file B_read_sums B_check_sum B_set_sum isSumDifferent listModifiedFiles + B_create_dir B_create_log_file + B_delete_file + B_cp B_place B_mknod + showDisclaimer + getSupportedOSHash + B_Backtick + B_System + isProcessRunning + checkProcsForService + + + $GLOBAL_OS $GLOBAL_ACTUAL_OS $CLI + $GLOBAL_LOGONLY $GLOBAL_VERBOSE $GLOBAL_DEBUG $GLOBAL_AUDITONLY $GLOBAL_AUDIT_NO_BROWSER $errorFlag + %GLOBAL_BIN %GLOBAL_DIR %GLOBAL_FILE + %GLOBAL_BDIR %GLOBAL_BFILE + %GLOBAL_CONFIG %GLOBAL_SUM + + %GLOBAL_SERVICE %GLOBAL_SERVTYPE %GLOBAL_PROCESS %GLOBAL_RC_CONFIG + %GLOBAL_TEST + + getGlobal setGlobal getGlobalConfig + + + B_parse_fstab + B_parse_mtab B_is_rpm_up_to_date + + NOTSECURE_CAN_CHANGE SECURE_CANT_CHANGE + NOT_INSTALLED INCONSISTENT MANUAL NOTEST SECURE_CAN_CHANGE + STRING_NOT_DEFINED NOT_INSTALLED_NOTSECURE DONT_KNOW + RELEVANT_HEADERQ NOTRELEVANT_HEADERQ +); + + + +###################################################### +###Testing Functions +################################################################## + +#Define "Constants" for test functions. Note these constants sometimes get +#interpreted as literal strings when used as hash references, so you may +# have to use CONSTANT() to disambiguate, like below. Sorry, it was either +# that or create even *more* global variables. +# See TestDriver.pm for definitions, and test design doc for full explaination +use constant { + NOTSECURE_CAN_CHANGE => 0, + SECURE_CANT_CHANGE => 1, + NOT_INSTALLED => 2, # (where the lack makes the system secure, eg telnet) + INCONSISTENT => 3, + MANUAL => 4, + NOTEST => 5, + SECURE_CAN_CHANGE => 6, + STRING_NOT_DEFINED => 7, + NOT_INSTALLED_NOTSECURE => 8, #(Where the missing s/w makes the system less secure eg IPFilter) + #Intentional duplicates follow + DONT_KNOW => 5, + RELEVANT_HEADERQ => 6, + NOTRELEVANT_HEADERQ => 0 +}; + +&SanitizeEnv; + +# Set up some common error messages. These are independent of +# operating system + +# These will allow us to line up the warnings and error messages +my $err ="ERROR: "; +my $spc =" "; +my $GLOBAL_OS="None"; +my $GLOBAL_ACTUAL_OS="None"; +my %GLOBAL_SUMS=(); +my $CLI=''; + +#OS independent Error Messages Follow, normally "bastille" script filters +#options before interactive or Bastille runs, so this check is often redundant +$GLOBAL_ERROR{"usage"}="\n". + "$spc Usage: bastille [ -b | -c | -x ] [ --os <version> ] [ -f <alternate config> ]\n". + "$spc bastille [ -r | --assess | --assessnobowser ]\n\n". + "$spc --assess : check status of system and report in browser\n". + "$spc --assessnobrowser : check status of system and list report locations\n". + "$spc -b : use a saved config file to apply changes\n". + "$spc directly to system\n". + "$spc -c : use the Curses (non-X11) TUI\n". + "$spc -f <alternate config>: populate answers with a different config file\n". + "$spc -r : revert all Bastille changes to-date\n". + "$spc -x : use the Perl/Tk (X11) GUI\n" . + "$spc --os <version> : ask all questions for the given operating system\n" . + "$spc version. e.g. --os RH6.0\n"; + +# These options don't work universally, so it's best not to +# document them here (yet). Hopefully, we'll get them +# straightened out soon. +#"$spc --log : log-only option\n". +#"$spc -v : verbose mode\n". +#"$spc --debug : debug mode\n"; + + +############################################################################## +# +# Directory structure for Bastille Linux v1.2 and up +# +############################################################################## +# +# /usr/sbin/ -- location of Bastille binaries +# /usr/lib/Bastille -- location of Bastille modules +# /usr/share/Bastille -- location of Bastille data files +# /etc/Bastille -- location of Bastille config files +# +# /var/log/Bastille -- location of Bastille log files +# /var/log/Bastille/revert -- directory holding all Bastille-created revert scripts +# /var/log/Bastille/revert/backup -- directory holding the original files that +# Bastille modifies, with permissions intact +# +############################################################################## + +############################################################################## +# +# Directory structure for HP-UX Bastille v2.0 and up +# +############################################################################## +# +# /opt/sec_mgmt/bastille/bin/ -- location of Bastille binaries +# /opt/sec_mgmt/bastille/lib/ -- location of Bastille modules +# /etc/opt/sec_mgmt/bastille/ -- location of Bastille data and config files +# +# /var/opt/sec_mgmt/bastille/log/ -- location of Bastille log files +# /var/opt/sec_mgmt/bastille/revert -- directory holding all Bastille-created +# revert scripts and save files +# +############################################################################## + + +############################################################################## +############################################################################## +################## Actual functions start here... ########################### +############################################################################## +############################################################################## + +########################################################################### +# setOptions takes six arguments, $GLOBAL_DEBUG, $GLOBAL_LOGONLY, +# $GLOBAL_VERBOSE, $GLOBAL_AUDITONLY, $GLOBAL_AUDIT_NO_BROWSER, and GLOBAL_OS; +########################################################################### +sub setOptions($$$$$$) { + ($GLOBAL_DEBUG,$GLOBAL_LOGONLY,$GLOBAL_VERBOSE,$GLOBAL_AUDITONLY, + $GLOBAL_AUDIT_NO_BROWSER,$GLOBAL_OS) = @_; + if ($GLOBAL_AUDIT_NO_BROWSER) { + $GLOBAL_AUDITONLY = 1; + } + if (not(defined($GLOBAL_OS))){ + $GLOBAL_OS="None"; + } +} +########################################################################### +# +# SanitizeEnv load a proper environment so Bastille cannot be tricked +# and Perl modules work correctly. +# +########################################################################### +sub SanitizeEnv { + delete @ENV{'IFS','CDPATH','ENV','BASH_ENV'}; + $ENV{CDPATH}="."; + $ENV{BASH_ENV}= ""; + # Bin is needed here or else /usr/lib/perl5/5.005/Cwd.pm + # will not find `pwd` + # Detected while testing with -w, jfs + $ENV{PATH} = "/bin:/usr/bin"; + # Giorgi, is /usr/local/bin needed? (jfs) +} + +########################################################################### +# +# GetDistro checks to see if the target is a known distribution and reports +# said distribution. +# +# This is used throughout the script, but also by ConfigureForDistro. +# +# +########################################################################### + +sub GetDistro() { + + my ($release,$distro); + + # Only read files for the distro once. + # if the --os option was used then + if ($GLOBAL_OS eq "None") { + if ( -e "/etc/mandrake-release" ) { + open(MANDRAKE_RELEASE,"/etc/mandrake-release"); + $release=<MANDRAKE_RELEASE>; + + if ( ($release =~ /^Mandrake Linux release (\d+\.\d+\w*)/) or ($release =~ /^Linux Mandrake release (\d+\.\d+\w*)/) ) { + $distro="MN$1"; + } + elsif ( $release =~ /^Mandrakelinux release (\d+\.\d+)\b/ ) { + $distro="MN$1"; + } + else { + print STDERR "$err Couldn't determine Mandrake/Mandriva version! Setting to 10.1!\n"; + $distro="MN10.1"; + } + + close(MANDRAKE_RELEASE); + } + elsif ( -e "/etc/immunix-release" ) { + open(IMMUNIX_RELEASE,"/etc/immunix-release"); + $release=<IMMUNIX_RELEASE>; + unless ($release =~ /^Immunix Linux release (\d+\.\d+\w*)/) { + print STDERR "$err Couldn't determine Immunix version! Setting to 6.2!\n"; + $distro="RH6.2"; + } + else { + $distro="RH$1"; + } + close(*IMMUNIX_RELEASE); + } + elsif ( -e '/etc/fedora-release' ) { + open(FEDORA_RELEASE,'/etc/fedora-release'); + $release=<FEDORA_RELEASE>; + close FEDORA_RELEASE; + if ($release =~ /^Fedora Core release (\d+\.?\d*)/) { + $distro = "RHFC$1"; + } + elsif ($release =~ /^Fedora release (\d+\.?\d*)/) { + $distro = "RHFC$1"; + } + else { + print STDERR "$err Could not determine Fedora version! Setting to Fedora Core 8\n"; + $distro='RHFC8'; + } + } + elsif ( -e "/etc/redhat-release" ) { + open(*REDHAT_RELEASE,"/etc/redhat-release"); + $release=<REDHAT_RELEASE>; + if ($release =~ /^Red Hat Linux release (\d+\.?\d*\w*)/) { + $distro="RH$1"; + } + elsif ($release =~ /^Red Hat Linux .+ release (\d+)\.?\d*([AEW]S)/) { + $distro="RHEL$1$2"; + } + elsif ($release =~ /^Red Hat Enterprise Linux ([AEW]S) release (\d+)/) { + $distro="RHEL$2$1"; + } + elsif ($release =~ /^CentOS release (\d+\.\d+)/) { + my $version = $1; + if ($version =~ /^4\./) { + $distro='RHEL4AS'; + } + elsif ($version =~ /^3\./) { + $distro='RHEL3AS'; + } + else { + print STDERR "$err Could not determine CentOS version! Setting to Red Hat Enterprise 4 AS.\n"; + $distro='RHEL4AS'; + } + } + else { + # JJB/HP - Should this be B_log? + print STDERR "$err Couldn't determine Red Hat version! Setting to 9!\n"; + $distro="RH9"; + } + close(REDHAT_RELEASE); + + } + elsif ( -e "/etc/debian_version" ) { + $stable="3.1"; #Change this when Debian stable changes + open(*DEBIAN_RELEASE,"/etc/debian_version"); + $release=<DEBIAN_RELEASE>; + unless ($release =~ /^(\d+\.\d+\w*)/) { + print STDERR "$err System is not running a stable Debian GNU/Linux version. Setting to $stable.\n"; + $distro="DB$stable"; + } + else { + $distro="DB$1"; + } + close(DEBIAN_RELEASE); + } + elsif ( -e "/etc/SuSE-release" ) { + open(*SUSE_RELEASE,"/etc/SuSE-release"); + $release=<SUSE_RELEASE>; + if ($release =~ /^SuSE Linux (\d+\.\d+\w*)/i) { + $distro="SE$1"; + } + elsif ($release =~ /^SUSE LINUX Enterprise Server (\d+\.?\d?\w*)/i) { + $distro="SESLES$1"; + } + elsif ($release =~ /^SUSE Linux Enterprise Server (\d+\.?\d?\w*)/i) { + $distro="SESLES$1"; + } + elsif ($release =~ /^openSuSE (\d+\.\d+\w*)/i) { + $distro="SE$1"; + } + else { + print STDERR "$err Couldn't determine SuSE version! Setting to 10.3!\n"; + $distro="SE10.3"; + } + close(SUSE_RELEASE); + } + elsif ( -e "/etc/turbolinux-release") { + open(*TURBOLINUX_RELEASE,"/etc/turbolinux-release"); + $release=<TURBOLINUX_RELEASE>; + unless ($release =~ /^Turbolinux Workstation (\d+\.\d+\w*)/) { + print STDERR "$err Couldn't determine TurboLinux version! Setting to 7.0!\n"; + $distro="TB7.0"; + } + else { + $distro="TB$1"; + } + close(TURBOLINUX_RELEASE); + } + else { + # We're either on Mac OS X, HP-UX or an unsupported O/S. + if ( -x '/usr/bin/uname') { + # uname is in /usr/bin on Mac OS X and HP-UX + $release=`/usr/bin/uname -sr`; + } + else { + print STDERR "$err Could not determine operating system version!\n"; + $distro="unknown"; + } + + # Figure out what kind of system we're on. + if ($release ne "") { + if ($release =~ /^Darwin\s+(\d+)\.(\d+)/) { + if ($1 == 6 ) { + $distro = "OSX10.2"; + } + elsif ($1 == 7) { + $distro = "OSX10.3"; + } + elsif ($1 == 8) { + $distro = "OSX10.3"; + } + else { + $distro = "unknown"; + } + } + elsif ( $release =~ /(^HP-UX)\s*B\.(\d+\.\d+)/ ) { + $distro="$1$2"; + } + else { + print STDERR "$err Could not determine operating system version!\n"; + $distro="unknown"; + } + } + } + + $GLOBAL_OS=$distro; + } elsif (not (defined $GLOBAL_OS)) { + print "ERROR: GLOBAL OS Scoping Issue\n"; + } else { + $distro = $GLOBAL_OS; + } + + return $distro; +} + +################################################################################### +# &getActualDistro; # +# # +# This subroutine returns the actual os version in which is running on. This # +# os version is independent of the --os switch feed to bastille. # +# # +################################################################################### +sub getActualDistro { + # set local variable to $GLOBAL_OS + + if ($GLOBAL_ACTUAL_OS eq "None") { + my $os = $GLOBAL_OS; + # undef GLOBAL_OS so that the GetDistro routine will return + # the actualDistro, it might otherwise return the distro set + # by the --os switch. + $GLOBAL_OS = "None"; + $GLOBAL_ACTUAL_OS = &GetDistro; + # reset the GLOBAL_OS variable + $GLOBAL_OS = $os; + } + return $GLOBAL_ACTUAL_OS; +} +# These are helper routines which used to be included inside GetDistro +sub is_OS_supported($) { + my $os=$_[0]; + my $supported=0; + my %supportedOSHash = &getSupportedOSHash; + + foreach my $oSType (keys %supportedOSHash) { + foreach my $supported_os ( @{$supportedOSHash{$oSType}} ) { + if ( $supported_os eq $os ) { + $supported=1; + } + } + } + + return $supported; +} + +############################################################################### +# getSupportedOSHash +# +# This subrountine returns a hash of supported OSTypes, which point to a +# a list of supported distros. When porting to a new distro, add the +# distro id to the hash in its appropriate list. +############################################################################### +sub getSupportedOSHash () { + + my %osHash = ("LINUX" => [ + "DB2.2", "DB3.0", + "RH6.0","RH6.1","RH6.2","RH7.0", + "RH7.1","RH7.2","RH7.3","RH8.0", + "RH9", + "RHEL5", + "RHEL4AS","RHEL4ES","RHEL4WS", + "RHEL3AS","RHEL3ES","RHEL3WS", + "RHEL2AS","RHEL2ES","RHEL2WS", + "RHFC1","RHFC2","RHFC3","RHFC4", + "RHFC5","RHFC6","RHFC7","RHFC8", + "MN6.0","MN6.1 ","MN7.0","MN7.1", + "MN7.2","MN8.0","MN8.1","MN8.2", + "MN10.1", + "SE7.2","SE7.3", "SE8.0","SE8.1","SE9.0","SE9.1", + "SE9.2","SE9.3","SE10.0","SE10.1","SE10.2","SE10.3", + "SESLES8","SESLES9","SESLES10", + "TB7.0" + ], + + "HP-UX" => [ + "HP-UX11.00","HP-UX11.11", + "HP-UX11.22", "HP-UX11.23", + "HP-UX11.31" + ], + + "OSX" => [ + 'OSX10.2','OSX10.3','OSX10.4' + ] + ); + + return %osHash; + +} + + +############################################################################### +# setFileLocations(OSMapFile, currentDistro); +# +# Given a file map location this subroutine will create the GLOBAL_* +# hash entries specified within this file. +############################################################################### +sub setFileLocations($$) { + + my ($fileInfoFile,$currentDistro) = @_; + + # define a mapping from the first argument to the proper hash + my %map = ("BIN" => \%GLOBAL_BIN, + "FILE" => \%GLOBAL_FILE, + "BFILE" => \%GLOBAL_BFILE, + "DIR" => \%GLOBAL_DIR, + "BDIR" => \%GLOBAL_BDIR + ); + my @fileInfo = (); + + # File containing file location information + if(open(FILEINFO, "<$fileInfoFile" )) { + + @fileInfo = <FILEINFO>; + + close(FILEINFO); + + } + else { + print STDERR "$err Unable to find file location information for '$distro'.\n" . + "$spc Contact the Bastille support list for details.\n"; + exit(1); + } + + # Each line of the file map follows the pattern below: + # bdir,init.d,'/etc/rc.d/init.d',RH7.2,RH7.3 + # if the distro information is not available, e.g. + # bdir,init.d,'/etc/rc.d/init.d' + # then the line applies to all distros under the OSType + foreach my $file (@fileInfo) { + # Perl comments are allowed within the file but only entire line comments + if($file !~ /^\s+\#|^\s+$/) { + chomp $file; + # type relates to the map above, type bin will map to GLOBAL_BIN + # id is the identifier used as the hash key by the GLOBAL hash + # fileLocation is the full path to the file + # distroList is an optional list of distros that this particular + # file location, if no distro list is presented the file location + # is considered to apply to all distros + my ($type,$id,$fileLocation,@distroList) = split /\s*,\s*/, $file; + $fileLocation =~ s/^\'(.*)\'$/$1/; + if($#distroList == -1) { + $map{uc($type)}->{$id}=$fileLocation; + } + else { + foreach my $distro (@distroList) { + # if the current distro matches the distro listed then + # this file location applies + if($currentDistro =~ /$distro/) { + $map{uc($type)}->{$id}=$fileLocation; + } + } + } + } + } + unless(defined($map{uc("BFILE")}->{"current_config"})) { + &setGlobal("BFILE","current_config",&getGlobal("BFILE","config")); + } +} + +############################################################################### +# setServiceInfo($OSServiceMapFile, $currentDistro +# +# Given the location of an OS Service map file, which describes +# a service in terms of configurables, processes and a service type. +# The subroutine fills out the GLOBAL_SERVICE, $GLOBAL_RC_CONFIG, GLOBAL_SERVTYPE, and +# GLOBAL_PROCESS hashes for a given service ID. +############################################################################### +sub setServiceInfo($$) { + my ($serviceInfoFile,$currentDistro) = @_; + my @serviceInfo = (); + + if(open(SERVICEINFO, "<$serviceInfoFile" )) { + + @serviceInfo = <SERVICEINFO>; + + close(SERVICEINFO); + + } + else { + print STDERR "$err Unable to find service, service type, and process information\n" . + "$spc for '$distro'.\n" . + "$spc Contact the Bastille support list for details.\n"; + exit(1); + } + + + # The following loop, parses the entire (YOUR OS).service file + # to provide service information for YOUR OS. + # The files format is as follows: + # serviceID,servType,('service' 'configuration' 'list'),('process' 'list')[,DISTROS]* + # if distros are not present then the service is assumed to be + # relevant the the current distro + + +# +# More specifically, this file's format for rc-based daemons is: +# +# script_name,rc,(rc-config-file rc-config-file ...),(rc-variable1 rc-variable2 ...),('program_name1 program_name2 ...') +# +# ...where script_name is a file in /etc/init.d/ and +# ...program_nameN is a program launced by the script. +# +# This file's format for inet-based daemons is: +# +# identifier, inet, line name/file name, program name +# +# label,inet,(port1 port2 ...),(daemon1 daemon2 ...) +# +# ...where label is arbitrary, portN is one of the ports +# ...this one listens on, and daemonN is a program launched +# ...in response to a connection on a port. + + foreach my $service (@serviceInfo) { + # This file accepts simple whole line comments perl style + if($service !~ /^\s+\#|^\s+$/) { + chomp $service; + my ($serviceID,$servType,$strConfigList,$strServiceList, + $strProcessList,@distroList) = split /\s*,\s*/, $service; + + sub MakeArrayFromString($){ + my $entryString = $_[0]; + my @destArray = (); + if ($entryString =~ /\'\S+\'/) { #Make sure we have something to extract before we try + @destArray = split /\'\s+\'/, $entryString; + $destArray[0] =~ s/^\(\'(.+)$/$1/; # Remove leading quotation mark + $destArray[$#destArray] =~ s/^(.*)\'\)$/$1/; #Remove trailing quotation mark + } + return @destArray; + } + + # produce a list of configuration files from the files + # format ('configuration' 'files') + my @configList = MakeArrayFromString($strConfigList); + + # produce a list of service configurables from the files + # format ('service' 'configurable') + my @serviceList = MakeArrayFromString($strServiceList); + + # produce a list of process names from the files format + # ('my' 'process' 'list') + my @processList = MakeArrayFromString($strProcessList); + + # if distros were not specified then accept the service information + if($#distroList == -1) { + @{$GLOBAL_SERVICE{$serviceID}} = @serviceList; + $GLOBAL_SERVTYPE{$serviceID} = $servType; + @{$GLOBAL_PROCESS{$serviceID}} = @processList; + @{$GLOBAL_RC_CONFIG{$serviceID}} = @configList; + } + else { + # only if the current distro matches one of the listed distros + # include the service information. + foreach my $distro (@distroList) { + if($currentDistro =~ /$distro/) { + @{$GLOBAL_SERVICE{$serviceID}} = @serviceList; + $GLOBAL_SERVTYPE{$serviceID} = $servType; + @{$GLOBAL_PROCESS{$serviceID}} = @processList; + @{$GLOBAL_RC_CONFIG{$serviceID}} = @configList; + } + } + } + } + } +} + + + +############################################################################### +# getFileAndServiceInfo($distro,$actualDistro) +# +# This subrountine, given distribution information, will import system file +# and service information into the GLOBA_* hashes. +# +# NOTE: $distro and $actualDistro will only differ when the --os switch is +# used to generate a configuration file for an arbitrary operating +# system. +# +############################################################################### +sub getFileAndServiceInfo($$) { + + my ($distro,$actualDistro) = @_; + + # defines the path to the OS map information for any supported OS type. + # OS map information is used to determine file locations for a given + # distribution. + my %oSInfoPath = ( + "LINUX" => "/usr/share/Bastille/OSMap/", + "HP-UX" => "/etc/opt/sec_mgmt/bastille/OSMap/", + "OSX" => "/usr/share/Bastille/OSMap/" + ); + + # returns the OS, LINUX, HP-UX, or OSX, associated with this + # distribution + my $actualOS = &getOSType($actualDistro); + my $oS = &getOSType($distro); + + if(defined $actualOS && defined $oS) { + my $bastilleInfoFile = $oSInfoPath{$actualOS} . "${actualOS}.bastille"; + my $systemInfoFile = $oSInfoPath{$actualOS} . "${oS}.system"; + my $serviceInfoFile = $oSInfoPath{$actualOS} . "${oS}.service"; + + if(-f $bastilleInfoFile) { + &setFileLocations($bastilleInfoFile,$actualDistro); + } + else { + print STDERR "$err Unable to find bastille file information.\n" . + "$spc $bastilleInfoFile does not exist on the system"; + exit(1); + } + + if(-f $systemInfoFile) { + &setFileLocations($systemInfoFile,$distro); + } + else { + print STDERR "$err Unable to find system file information.\n" . + "$spc $systemInfoFile does not exist on the system"; + exit(1); + } + # Service info File is optional + if(-f $serviceInfoFile) { + &setServiceInfo($serviceInfoFile,$distro); + } + } + else { + print STDERR "$err Unable to determine operating system type\n" . + "$spc for $actualDistro or $distro\n"; + exit(1); + } + +} + + +# returns the Operating System type associated with the specified +# distribution. +sub getOSType($) { + + my $distro = $_[0]; + + my %supportedOSHash = &getSupportedOSHash; + foreach my $oSType (keys %supportedOSHash) { + foreach my $oSDistro (@{$supportedOSHash{$oSType}}) { + if($distro eq $oSDistro) { + return $oSType; + } + } + } + + return undef; + +} + + +# Test subroutine used to debug file location info for new Distributions as +# they are ported. +sub dumpFileInfo { + print "Dumping File Information\n"; + foreach my $hashref (\%GLOBAL_BIN,\%GLOBAL_DIR,\%GLOBAL_FILE,\%GLOBAL_BFILE,\%GLOBAL_BDIR) { + foreach my $id (keys %{$hashref}) { + print "$id: ${$hashref}{$id}\n"; + } + print "-----------------------\n\n"; + } +} + +# Test subroutine used to debug service info for new Distributions as +# they are ported. +sub dumpServiceInfo { + print "Dumping Service Information\n"; + foreach my $serviceId (keys %GLOBAL_SERVICE) { + print "$serviceId:\n"; + print "Type - $GLOBAL_SERVTYPE{$serviceId}\n"; + print "Service List:\n"; + foreach my $service (@{$GLOBAL_SERVICE{$serviceId}}) { + print "$service "; + } + print "\nProcess List:\n"; + foreach my $process (@{$GLOBAL_PROCESS{$serviceId}}) { + print "$process "; + } + print "\n----------------------\n"; + } +} + + +########################################################################### +# +# &ConfigureForDistro configures the API for a given distribution. This +# includes setting global variables that tell the Bastille API about +# given binaries and directories. +# +# WARNING: If a distro is not covered here, Bastille may not be 100% +# compatible with it, though 1.1 is written to be much smarter +# about unknown distros... +# +########################################################################### +sub ConfigureForDistro { + + my $retval=1; + + # checking to see if the os version given is in fact supported + my $distro = &GetDistro; + + # checking to see if the actual os version is in fact supported + my $actualDistro = &getActualDistro; + $ENV{'LOCALE'}=''; # So that test cases checking for english results work ok. + if ((! &is_OS_supported($distro)) or (! &is_OS_supported($actualDistro)) ) { + # if either is not supported then print out a list of supported versions + if (! &is_OS_supported($distro)) { + print STDERR "$err '$distro' is not a supported operating system.\n"; + } + else { + print STDERR "$err Bastille is unable to operate correctly on this\n"; + print STDERR "$spc $distro operating system.\n"; + } + my %supportedOSHash = &getSupportedOSHash; + print STDERR "$spc Valid operating system versions are as follows:\n"; + + foreach my $oSType (keys %supportedOSHash) { + + print STDERR "$spc $oSType:\n$spc "; + + my $os_number = 1; + foreach my $os (@{$supportedOSHash{$oSType}}) { + print STDERR "'$os' "; + if ($os_number == 5){ + print STDERR "\n$spc "; + $os_number = 1; + } + else { + $os_number++; + } + + } + print STDERR "\n"; + } + + print "\n" . $GLOBAL_ERROR{"usage"}; + exit(1); + } + + # First, let's make sure that we do not create any files or + # directories with more permissive permissions than we + # intend via setting the Perl umask + umask(077); + + &getFileAndServiceInfo($distro,$actualDistro); + +# &dumpFileInfo; # great for debuging file location issues +# &dumpServiceInfo; # great for debuging service information issues + + # OS dependent error messages (after configuring file locations) + my $nodisclaim_file = &getGlobal('BFILE', "nodisclaimer"); + + $GLOBAL_ERROR{"disclaimer"}="$err Unable to touch $nodisclaim_file:" . + "$spc You must use Bastille\'s -n flag (for example:\n" . + "$spc bastille -f -n) or \'touch $nodisclaim_file \'\n"; + + return $retval; +} + + +########################################################################### +########################################################################### +# # +# The B_<perl_function> file utilities are replacements for their Perl # +# counterparts. These replacements log their actions and their errors, # +# but are very similar to said counterparts. # +# # +########################################################################### +########################################################################### + + +########################################################################### +# B_open is used for opening a file for reading. B_open_plus is the preferred +# function for writing, since it saves a backup copy of the file for +# later restoration. +# +# B_open opens the given file handle, associated with the given filename +# and logs appropriately. +# +########################################################################### + +sub B_open { + my $retval=1; + my ($handle,$filename)=@_; + + unless ($GLOBAL_LOGONLY) { + $retval = open $handle,$filename; + } + + ($handle) = "$_[0]" =~ /[^:]+::[^:]+::([^:]+)/; + &B_log("ACTION","open $handle,\"$filename\";\n"); + unless ($retval) { + &B_log("ERROR","open $handle, $filename failed...\n"); + } + + return $retval; +} + +########################################################################### +# B_open_plus is the v1.1 open command. +# +# &B_open_plus($handle_file,$handle_original,$file) opens the file $file +# for reading and opens the file ${file}.bastille for writing. It is the +# counterpart to B_close_plus, which will move the original file to +# $GLOBAL_BDIR{"backup"} and will place the new file ${file}.bastille in its +# place. +# +# &B_open_plus makes the appropriate log entries in the action and error +# logs. +########################################################################### + +sub B_open_plus { + + my ($handle_file,$handle_original,$file)=@_; + my $retval=1; + my $return_file=1; + my $return_old=1; + + my $original_file = $file; + + # Open the original file and open a copy for writing. + unless ($GLOBAL_LOGONLY) { + # if the temporary filename already exists then the open operation will fail. + if ( $file eq "" ){ + &B_log("ERROR","Internal Error - Attempt Made to Open Blank Filename"); + $return_old=0; + $return_file=0; + return 0; #False + } elsif (-e "${file}.bastille") { + &B_log("ERROR","Unable to open $file as the swap file ". + "${file}.bastille\" already exists. Rename the swap ". + "file to allow Bastille to make desired file modifications."); + $return_old=0; + $return_file=0; + } + else { + $return_old = open $handle_original,"$file"; + $return_file = open $handle_file,("> $file.bastille"); + } + } + + # Error handling/logging here... + #&B_log("ACTION","# Modifying file $original_file via temporary file $original_file.bastille\n"); + unless ($return_file) { + $retval=0; + &B_log("ERROR","open file: \"$original_file.bastille\" failed...\n"); + } + unless ($return_old) { + $retval=0; + &B_log("ERROR","open file: \"$original_file\" failed.\n"); + } + + return $retval; + +} + +########################################################################### +# B_close was the v1.0 close command. It is still used in places in the +# code. +# However the use of B _close_plus, which implements a new, smarter, +# backup scheme is preferred. +# +# B_close closes the given file handle, associated with the given filename +# and logs appropriately. +########################################################################### + + +sub B_close { + my $retval=1; + + unless ($GLOBAL_LOGONLY) { + $retval = close $_[0]; + } + + &B_log("ACTION", "close $_[0];\n"); + unless ($retval) { + &B_log("ERROR", "close $_[0] failed...\n"); + } + + return $retval; +} + + +########################################################################### +# B_close_plus is the v1.1 close command. +# +# &B_close_plus($handle_file,$handle_original,$file) closes the files +# $file and ${file}.bastille, backs up $file to $GLOBAL_BDIR{"backup"} and +# renames ${file}.bastille to $file. This backup is made using the +# internal API function &B_backup_file. Further, it sets the new file's +# permissions and uid/gid to the same as the old file. +# +# B_close_plus is the counterpart to B_open_plus, which opened $file and +# $file.bastille with the file handles $handle_original and $handle_file, +# respectively. +# +# &B_close_plus makes the appropriate log entries in the action and error +# logs. +########################################################################### + +sub B_close_plus { + my ($handle_file,$handle_original,$file)=@_; + my ($mode,$uid,$gid); + my @junk; + + my $original_file; + + my $retval=1; + my $return_file=1; + my $return_old=1; + + # Append the global prefix, but save the original for B_backup_file b/c + # it appends the prefix on its own... + + $original_file=$file; + + # + # Close the files and prepare for the rename + # + + if (($file eq "") or (not(-e $file ))) { + &B_log("ERROR","Internal Error, attempted to close a blank filename ". + "or nonexistent file."); + return 0; #False + } + + unless ($GLOBAL_LOGONLY) { + $return_file = close $handle_file; + $return_old = close $handle_original; + } + + # Error handling/logging here... + #&B_log("ACTION","#Closing $original_file and backing up to " . &getGlobal('BDIR', "backup")); + #&B_log("ACTION","/$original_file\n"); + + unless ($return_file) { + $retval=0; + &B_log("ERROR","close $original_file failed...\n"); + } + unless ($return_old) { + $retval=0; + &B_log("ERROR","close $original_file.bastille failed.\n"); + } + + # + # If we've had no errors, backup the old file and put the new one + # in its place, with the Right permissions. + # + + unless ( ($retval == 0) or $GLOBAL_LOGONLY) { + + # Read the permissions/owners on the old file + + @junk=stat ($file); + $mode=$junk[2]; + $uid=$junk[4]; + $gid=$junk[5]; + + # Set the permissions/owners on the new file + + chmod $mode, "$file.bastille" or &B_log("ERROR","Not able to retain permissions on $original_file!!!\n"); + chown $uid, $gid, "$file.bastille" or &B_log("ERROR","Not able to retain owners on $original_file!!!\n"); + + # Backup the old file and put a new one in place. + + &B_backup_file($original_file); + rename "$file.bastille", $file or + &B_log("ERROR","B_close_plus: not able to move $original_file.bastille to $original_file\n"); + + # We add the file to the GLOBAL_SUMS hash if it is not already present + &B_set_sum($file); + + } + + return $retval; +} + +########################################################################### +# &B_backup_file ($file) makes a backup copy of the file $file in +# &getGlobal('BDIR', "backup"). Note that this routine is intended for internal +# use only -- only Bastille API functions should call B_backup_file. +# +########################################################################### + +sub B_backup_file { + + my $file=$_[0]; + my $complain = 1; + my $original_file = $file; + + my $backup_dir = &getGlobal('BDIR', "backup"); + my $backup_file = $backup_dir . $original_file; + + my $retval=1; + + # First, separate the file into the directory and the relative filename + + my $directory =""; + if ($file =~ /^(.*)\/([^\/]+)$/) { + #$relative_file=$2; + $directory = $1; + } else { + $directory=cwd; + } + + # Now, if the directory does not exist, create it. + # Later: + # Try to set the same permissions on the patch directory that the + # original had...? + + unless ( -d ($backup_dir . $directory) ) { + mkpath(( $backup_dir . $directory),0,0700); + + } + + # Now we backup the file. If there is already a backup file there, + # we will leave it alone, since it exists from a previous run and + # should be the _original_ (possibly user-modified) distro's version + # of the file. + + if ( -e $file ) { + + unless ( -e $backup_file ) { + my $command=&getGlobal("BIN","cp"); + &B_Backtick("$command -p $file $backup_file"); + &B_revert_log (&getGlobal("BIN","mv"). " $backup_file $file"); + } + + } else { + # The file we were trying to backup doesn't exist. + + $retval=0; + # This is a non-fatal error, not worth complaining about + $complain = 0; + #&ErrorLog ("# Failed trying to backup file $file -- it doesn't exist!\n"); + } + + # Check to make sure that the file does exist in the backup location. + + unless ( -e $backup_file ) { + $retval=0; + if ( $complain == 1 ) { + &B_log("ERROR","Failed trying to backup $file -- the copy was not created.\n"); + } + } + + return $retval; +} + + +########################################################################### +# &B_read_sums reads in the sum.csv file which contains information +# about Bastille modified files. The file structure is as follows: +# +# filename,filesize,cksum +# +# It reads the information into the GLOBAL_SUM hash i.e. +# $GLOBAL_SUM{$file}{sum} = $cksum +# $GLOBAL_SUM{$file}{filesize} = $size +# For the first run of Bastille on a given system this subroutine +# is a no-op, and returns "undefined." +########################################################################### + +sub B_read_sums { + + my $sumFile = &getGlobal('BFILE',"sum.csv"); + + if ( -e $sumFile ) { + + open( SUM, "< $sumFile") or &B_log("ERROR","Unable to open $sumFile for read.\n$!\n"); + + while( my $line = <SUM> ) { + chomp $line; + my ($file,$filesize,$sum,$flag) = split /,/, $line; + if(-e $file) { + $GLOBAL_SUM{"$file"}{filesize} = $filesize; + $GLOBAL_SUM{"$file"}{sum} = $sum; + } + } + + close(SUM); + } else { + return undef; + } +} + + +########################################################################### +# &B_write_sums writes out the sum.csv file which contains information +# about Bastille modified files. The file structure is as follows: +# +# filename,filesize,cksum +# +# It writes the information from the GLOBAL_SUM hash i.e. +# +# $file,$GLOBAL_SUM{$file}{sum},$GLOBAL_SUM{$file}{filesize} +# +# This subroutine requires access to the GLOBAL_SUM hash. +########################################################################### + +sub B_write_sums { + + my $sumFile = &getGlobal('BFILE',"sum.csv"); + + if ( %GLOBAL_SUM ) { + + open( SUM, "> $sumFile") or &B_log("ERROR","Unable to open $sumFile for write.\n$!\n"); + + for my $file (sort keys %GLOBAL_SUM) { + if( -e $file) { + print SUM "$file,$GLOBAL_SUM{\"$file\"}{filesize},$GLOBAL_SUM{\"$file\"}{sum}\n"; + } + } + + close(SUM); + } + +} + + +########################################################################### +# &B_check_sum($file) compares the stored cksum and filesize of the given +# file compared to the current cksum and filesize respectively. +# This subroutine also keeps the state of the sum check by setting the +# checked flag which tells the subroutine that on this run this file +# has already been checked. +# +# $GLOBAL_SUM{$file}{checked} = 1; +# +# This subroutine requires access to the GLOBAL_SUM hash. +# +# Returns 1 if sum checks out and 0 if not +########################################################################### + +sub B_check_sum($) { + my $file = $_[0]; + my $cksum = &getGlobal('BIN',"cksum"); + + if (not(%GLOBAL_SUM)) { + &B_read_sums; + } + + if(-e $file) { + my ($sum,$size,$ckfile) = split(/\s+/, `$cksum $file`); + my $commandRetVal = ($? >> 8); # find the command's return value + + if($commandRetVal != 0) { + &B_log("ERROR","$cksum reported the following error:\n$!\n"); + return 0; + } else { + if ( exists $GLOBAL_SUM{$file} ) { + # if the file size or file sum differ from those recorded. + if (( $GLOBAL_SUM{$file}{filesize} == $size) and + ($GLOBAL_SUM{$file}{sum} == $sum )) { + return 1; #True, since saved state matches up, all is well. + } else { + return 0; #False, since saved state doesn't match + } + } else { + &B_log("ERROR","File: $file does not exist in sums database."); + return 0; + } + } + } else { + &B_log("ERROR","The file: $file does not exist for comparison in B_check_sum."); + return 0; + } +} + +# Don't think we need this anymore as function now check_sums returns +# results directly +#sub isSumDifferent($) { +# my $file = $_[0]; +# if(exists $GLOBAL_SUM{$file}) { +# return $GLOBAL_SUM{$file}{flag} +# } +#} + +sub listModifiedFiles { + my @listModifiedFiles=sort keys %GLOBAL_SUM; + return @listModifiedFiles; +} + +########################################################################### +# &B_isFileinSumDB($file) checks to see if a given file's sum was saved. +# +# $GLOBAL_SUM{$file}{filesize} = $size; +# $GLOBAL_SUM{$file}{sum} = $cksum; +# +# This subroutine requires access to the GLOBAL_SUM hash. +########################################################################### + +sub B_isFileinSumDB($) { + my $file = $_[0]; + + if (not(%GLOBAL_SUM)) { + &B_log("DEBUG","Reading in DB from B_isFileinSumDB"); + &B_read_sums; + } + if (exists($GLOBAL_SUM{"$file"})){ + &B_log("DEBUG","$file is in sum database"); + return 1; #true + } else { + &B_log("DEBUG","$file is not in sum database"); + return 0; #false + } +} + +########################################################################### +# &B_set_sum($file) sets the current cksum and filesize of the given +# file into the GLOBAL_SUM hash. +# +# $GLOBAL_SUM{$file}{filesize} = $size; +# $GLOBAL_SUM{$file}{sum} = $cksum; +# +# This subroutine requires access to the GLOBAL_SUM hash. +########################################################################### + +sub B_set_sum($) { + + my $file = $_[0]; + my $cksum = &getGlobal('BIN',"cksum"); + if( -e $file) { + + my ($sum,$size,$ckfile) = split(/\s+/, `$cksum $file`); + my $commandRetVal = ($? >> 8); # find the command's return value + + if($commandRetVal != 0) { + + &B_log("ERROR","$cksum reported the following error:\n$!\n"); + + } + else { + + # new file size and sum are added to the hash + $GLOBAL_SUM{$file}{filesize} = $size; + $GLOBAL_SUM{$file}{sum} = $sum; + &B_write_sums; + + } + } else { + &B_log("ERROR","Can not save chksum for file: $file since it does not exist"); + } +} + + +########################################################################### +# +# &B_delete_file ($file) deletes the file $file and makes a backup to +# the backup directory. +# +########################################################################## + + +sub B_delete_file($) { #Currently Linux only (TMPDIR) + #consideration: should create clear_sum routine if this is ever used to remove + # A Bastille-generated file. + + # + # This API routine deletes the named file, backing it up first to the + # backup directory. + # + + my $filename=shift @_; + my $retval=1; + + # We have to append the prefix ourselves since we don't use B_open_plus + + my $original_filename=$filename; + + &B_log("ACTION","Deleting (and backing-up) file $original_filename\n"); + &B_log("ACTION","rm $original_filename\n"); + + unless ($filename) { + &B_log("ERROR","B_delete_file called with no arguments!\n"); + } + + unless ($GLOBAL_LOGONLY) { + if ( B_backup_file($original_filename) ) { + unless ( unlink $filename ) { + &B_log("ERROR","Couldn't unlink file $original_filename"); + $retval=0; + } + } + else { + $retval=0; + &B_log("ERROR","B_delete_file did not delete $original_filename since it could not back it up\n"); + } + } + + $retval; + +} + + +########################################################################### +# &B_create_file ($file) creates the file $file, if it doesn't already +# exist. +# It will set a default mode of 0700 and a default uid/gid or 0/0. +# +# &B_create_file, to support Bastille's revert functionality, writes an +# rm $file command to the end of the file &getGlobal('BFILE', "created-files"). +# +########################################################################## + + +sub B_create_file($) { + + my $file = $_[0]; + my $retval=1; + + # We have to create the file ourselves since we don't use B_open_plus + + my $original_file = $file; + + if ($file eq ""){ + &B_log("ERROR","Internal Error, attempt made to create blank filename"); + return 0; #False + } + + unless ( -e $file ) { + + unless ($GLOBAL_LOGONLY) { + + # find the directory in which the file is to reside. + my $dirName = dirname($file); + # if the directory does not exist then + if(! -d $dirName) { + # create it. + mkpath ($dirName,0,0700); + } + + $retval=open CREATE_FILE,">$file"; + + if ($retval) { + close CREATE_FILE; + chmod 0700,$file; + # Make the revert functionality + &B_revert_log( &getGlobal('BIN','rm') . " $original_file \n"); + } else { + &B_log("ERROR","Couldn't create file $original_file even though " . + "it didn't already exist!\n"); + } + } + &B_log("ACTION","Created file $original_file\n"); + } else { + &B_log("DEBUG","Didn't create file $original_file since it already existed.\n"); + $retval=0; + } + + $retval; +} + + +########################################################################### +# &B_create_dir ($dir) creates the directory $dir, if it doesn't already +# exist. +# It will set a default mode of 0700 and a default uid/gid or 0/0. +# +########################################################################## + + +sub B_create_dir($) { + + my $dir = $_[0]; + my $retval=1; + + # We have to append the prefix ourselves since we don't use B_open_plus + + my $original_dir=$dir; + + unless ( -d $dir ) { + unless ($GLOBAL_LOGONLY) { + $retval=mkdir $dir,0700; + + if ($retval) { + # Make the revert functionality + &B_revert_log (&getGlobal('BIN','rmdir') . " $original_dir\n"); + } + else { + &B_log("ERROR","Couldn't create dir $original_dir even though it didn't already exist!"); + } + + } + &B_log("ACTION","Created directory $original_dir\n"); + } + else { + &B_log("ACTION","Didn't create directory $original_dir since it already existed.\n"); + $retval=0; + } + + $retval; +} + + + +########################################################################### +# &B_symlink ($original_file,$new_symlink) creates a symbolic link from +# $original_file to $new_symlink. +# +# &B_symlink respects $GLOBAL_LOGONLY. It supports +# the revert functionality that you've come to know and love by adding every +# symbolic link it creates to &getGlobal('BFILE', "created-symlinks"), currently set to: +# +# /root/Bastille/revert/revert-created-symlinks +# +# The revert script, if it works like I think it should, will run this file, +# which should be a script or rm's... +# +########################################################################## + +sub B_symlink($$) { + my ($source_file,$new_symlink)=@_; + my $retval=1; + my $original_source = $source_file; + my $original_symlink = $new_symlink; + + unless ($GLOBAL_LOGONLY) { + $retval=symlink $source_file,$new_symlink; + if ($retval) { + &B_revert_log (&getGlobal('BIN',"rm") . " $original_symlink\n"); + } + } + + &B_log("ACTION", "Created a symbolic link called $original_symlink from $original_source\n"); + &B_log("ACTION", "symlink \"$original_source\",\"$original_symlink\";\n"); + unless ($retval) { + &B_log("ERROR","Couldn't symlink $original_symlink -> $original_source\n"); + } + + $retval; + +} + + +sub B_cp($$) { + + my ($source,$target)=@_; + my $retval=0; + + my $had_to_backup_target=0; + + use File::Copy; + + my $original_source=$source; + my $original_target=$target; + + if( -e $target and -f $target ) { + &B_backup_file($original_target); + &B_log("ACTION","About to copy $original_source to $original_target -- had to backup target\n"); + $had_to_backup_target=1; + } + + $retval=copy($source,$target); + if ($retval) { + &B_log("ACTION","cp $original_source $original_target\n"); + + # + # We want to add a line to the &getGlobal('BFILE', "created-files") so that the + # file we just put at $original_target gets deleted. + # + &B_revert_log(&getGlobal('BIN',"rm") . " $original_target\n"); + } else { + &B_log("ERROR","Failed to copy $original_source to $original_target\n"); + } + # We add the file to the GLOBAL_SUMS hash if it is not already present + &B_set_sum($target); + $retval; +} + + + +############################################################################ +# &B_place puts a file in place, using Perl's File::cp. This file is taken +# from &getGlobal('BDIR', "share") and is used to place a file that came with +# Bastille. +# +# This should be DEPRECATED in favor of &B_cp, since the only reason it exists +# is because of GLOBAL_PREFIX, which has been broken for quite some time. +# Otherwise, the two routines are identical. +# +# It respects $GLOBAL_LOGONLY. +# If $target is an already-existing file, it is backed up. +# +# revert either appends another "rm $target" to &getGlobal('BFILE', "revert-actions") or +# backs up the file that _was_ there into the &getGlobal('BDIR', "backup"), +# appending a "mv" to revert-actions to put it back. +# +############################################################################ + +sub B_place { # Only Linux references left (Firewall / TMPDIR) + + my ($source,$target)=@_; + my $retval=0; + + my $had_to_backup_target=0; + + use File::Copy; + + my $original_source=$source; + $source = &getGlobal('BDIR', "share") . $source; + my $original_target=$target; + + if ( -e $target and -f $target ) { + &B_backup_file($original_target); + &B_log("ACTION","About to copy $original_source to $original_target -- had to backup target\n"); + $had_to_backup_target=1; + } + $retval=copy($source,$target); + if ($retval) { + &B_log("ACTION","placed file $original_source as $original_target\n"); + # + # We want to add a line to the &getGlobal('BFILE', "created-files") so that the + # file we just put at $original_target gets deleted. + &B_revert_log(&getGlobal('BIN',"rm") . " $original_target\n"); + } else { + &B_log("ERROR","Failed to place $original_source as $original_target\n"); + } + + # We add the file to the GLOBAL_SUMS hash if it is not already present + &B_set_sum($target); + + $retval; +} + + + + + +############################################################################# +############################################################################# +############################################################################# + +########################################################################### +# &B_mknod ($file) creates the node $file, if it doesn't already +# exist. It uses the prefix and suffix, like this: +# +# mknod $prefix $file $suffix +# +# This is just a wrapper to the mknod program, which tries to introduce +# revert functionality, by writing rm $file to the end of the +# file &getGlobal('BFILE', "created-files"). +# +########################################################################## + + +sub B_mknod($$$) { + + my ($prefix,$file,$suffix) = @_; + my $retval=1; + + # We have to create the filename ourselves since we don't use B_open_plus + + my $original_file = $file; + + unless ( -e $file ) { + my $command = &getGlobal("BIN","mknod") . " $prefix $file $suffix"; + + if ( system($command) == 0) { + # Since system will return 0 on success, invert the error code + $retval=1; + } + else { + $retval=0; + } + + if ($retval) { + + # Make the revert functionality + &B_revert_log(&getGlobal('BIN',"rm") . " $original_file\n"); + } else { + &B_log("ERROR","Couldn't mknod $prefix $original_file $suffix even though it didn't already exist!\n"); + } + + + &B_log("ACTION","mknod $prefix $original_file $suffix\n"); + } + else { + &B_log("ACTION","Didn't mknod $prefix $original_file $suffix since $original_file already existed.\n"); + $retval=0; + } + + $retval; +} + +########################################################################### +# &B_revert_log("reverse_command") prepends a command to a shell script. This +# shell script is intended to be run by bastille -r to reverse the changes that +# Bastille made, returning the files which Bastille changed to their original +# state. +########################################################################### + +sub B_revert_log($) { + + my $revert_command = $_[0]; + my $revert_actions = &getGlobal('BFILE', "revert-actions"); + my $revertdir= &getGlobal('BDIR', "revert"); + my @lines; + + + if (! (-e $revert_actions)) { + mkpath($revertdir); #if this doesn't work next line catches + if (open REVERT_ACTIONS,">" . $revert_actions){ # create revert file + close REVERT_ACTIONS; # chown to root, rwx------ + chmod 0700,$revert_actions; + chown 0,0,$revert_actions; + } + else { + &B_log("FATAL","Can not create revert-actions file: $revert_actions.\n" . + " Unable to add the following command to the revert\n" . + " actions script: $revert_command\n"); + } + + } + + &B_open_plus (*REVERT_NEW, *REVERT_OLD, $revert_actions); + + while (my $line=<REVERT_OLD>) { #copy file into @lines + push (@lines,$line); + } + print REVERT_NEW $revert_command . "\n"; #make the revert command first in the new file + while (my $line = shift @lines) { #write the rest of the lines of the file + print REVERT_NEW $line; + } + close REVERT_OLD; + close REVERT_NEW; + if (rename "${revert_actions}.bastille", $revert_actions) { #replace the old file with the new file we + chmod 0700,$revert_actions; # just made / mirrors B_close_plus logic + chown 0,0,$revert_actions; + } else { + &B_log("ERROR","B_revert_log: not able to move ${revert_actions}.bastille to ${revert_actions}!!! $!) !!!\n"); + } +} + + +########################################################################### +# &getGlobalConfig($$) +# +# returns the requested GLOBAL_CONFIG hash value, ignoring the error +# if the value does not exist (because every module uses this to find +# out if the question was answered "Y") +########################################################################### +sub getGlobalConfig ($$) { + my $module = $_[0]; + my $key = $_[1]; + if (exists $GLOBAL_CONFIG{$module}{$key}) { + my $answer=$GLOBAL_CONFIG{$module}{$key}; + &B_log("ACTION","Answer to question $module.$key is \"$answer\".\n"); + return $answer; + } else { + &B_log("ACTION","Answer to question $module.$key is undefined."); + return undef; + } +} + +########################################################################### +# &getGlobal($$) +# +# returns the requested GLOBAL_* hash value, and logs an error +# if the variable does not exist. +########################################################################### +sub getGlobal ($$) { + my $type = uc($_[0]); + my $key = $_[1]; + + # define a mapping from the first argument to the proper hash + my %map = ("BIN" => \%GLOBAL_BIN, + "FILE" => \%GLOBAL_FILE, + "BFILE" => \%GLOBAL_BFILE, + "DIR" => \%GLOBAL_DIR, + "BDIR" => \%GLOBAL_BDIR, + "ERROR" => \%GLOBAL_ERROR, + "SERVICE" => \%GLOBAL_SERVICE, + "SERVTYPE" => \%GLOBAL_SERVTYPE, + "PROCESS" => \%GLOBAL_PROCESS, + "RCCONFIG" => \%GLOBAL_RC_CONFIG + ); + + # check to see if the desired key is in the desired hash + if (exists $map{$type}->{$key}) { + # get the value from the right hash with the key + return $map{$type}->{$key}; + } else { + # i.e. Bastille tried to use $GLOBAL_BIN{'cp'} but it does not exist. + # Note that we can't use B_log, since it uses getGlobal ... recursive before + # configureForDistro is run. + print STDERR "ERROR: Bastille tried to use \$GLOBAL_${type}\{\'$key\'} but it does not exist.\n"; + return undef; + } +} + +########################################################################### +# &getGlobal($$) +# +# sets the requested GLOBAL_* hash value +########################################################################### +sub setGlobal ($$$) { + my $type = uc($_[0]); + my $key = $_[1]; + my $input_value = $_[2]; + + # define a mapping from the first argument to the proper hash + my %map = ("BIN" => \%GLOBAL_BIN, + "FILE" => \%GLOBAL_FILE, + "BFILE" => \%GLOBAL_BFILE, + "DIR" => \%GLOBAL_DIR, + "BDIR" => \%GLOBAL_BDIR, + "ERROR" => \%GLOBAL_ERROR, + "SERVICE" => \%GLOBAL_SERVICE, + "SERVTYPE" => \%GLOBAL_SERVTYPE, + "PROCESS" => \%GLOBAL_PROCESS, + ); + + if ($map{$type}->{$key} = $input_value) { + return 1; + } else { + &B_log('ERROR','Internal Error, Unable to set global config value:' . $type . ", " .$key); + return 0; + } +} + + +########################################################################### +# &showDisclaimer: +# Print the disclaimer and wait for 2 minutes for acceptance +# Do NOT do so if any of the following conditions hold +# 1. the -n option was used +# 2. the file ~/.bastille_disclaimer exists +########################################################################### + +sub showDisclaimer($) { + + my $nodisclaim = $_[0]; + my $nodisclaim_file = &getGlobal('BFILE', "nodisclaimer"); + my $response; + my $WAIT_TIME = 300; # we'll wait for 5 minutes + my $developersAnd; + my $developersOr; + if ($GLOBAL_OS =~ "^HP-UX") { + $developersAnd ="HP AND ITS"; + $developersOr ="HP OR ITS"; + }else{ + $developersAnd ="JAY BEALE, THE BASTILLE DEVELOPERS, AND THEIR"; + $developersOr ="JAY BEALE, THE BASTILLE DEVELOPERS, OR THEIR"; + } + my $DISCLAIMER = + "\n" . + "Copyright (C) 1999-2006 Jay Beale\n" . + "Copyright (C) 1999-2001 Peter Watkins\n" . + "Copyright (C) 2000 Paul L. Allen\n" . + "Copyright (C) 2001-2007 Hewlett-Packard Development Company, L.P.\n" . + "Bastille is free software; you are welcome to redistribute it under\n" . + "certain conditions. See the \'COPYING\' file in your distribution for terms.\n\n" . + "DISCLAIMER. Use of Bastille can help optimize system security, but does not\n" . + "guarantee system security. Information about security obtained through use of\n" . + "Bastille is provided on an AS-IS basis only and is subject to change without\n" . + "notice. Customer acknowledges they are responsible for their system\'s security.\n" . + "TO THE EXTENT ALLOWED BY LOCAL LAW, Bastille (\"SOFTWARE\") IS PROVIDED TO YOU \n" . + "\"AS IS\" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, WHETHER ORAL OR WRITTEN,\n" . + "EXPRESS OR IMPLIED. $developersAnd SUPPLIERS\n" . + "DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE \n" . + "IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n" . + "Some countries, states and provinces do not allow exclusions of implied\n" . + "warranties or conditions, so the above exclusion may not apply to you. You may\n" . + "have other rights that vary from country to country, state to state, or province\n" . + "to province. EXCEPT TO THE EXTENT PROHIBITED BY LOCAL LAW, IN NO EVENT WILL\n" . + "$developersOr SUBSIDIARIES, AFFILIATES OR\n" . + "SUPPLIERS BE LIABLE FOR DIRECT, SPECIAL, INCIDENTAL, CONSEQUENTIAL OR OTHER\n" . + "DAMAGES (INCLUDING LOST PROFIT, LOST DATA, OR DOWNTIME COSTS), ARISING OUT OF\n" . + "THE USE, INABILITY TO USE, OR THE RESULTS OF USE OF THE SOFTWARE, WHETHER BASED\n" . + "IN WARRANTY, CONTRACT, TORT OR OTHER LEGAL THEORY, AND WHETHER OR NOT ADVISED\n" . + "OF THE POSSIBILITY OF SUCH DAMAGES. Your use of the Software is entirely at your\n" . + "own risk. Should the Software prove defective, you assume the entire cost of all\n" . + "service, repair or correction. Some countries, states and provinces do not allow\n" . + "the exclusion or limitation of liability for incidental or consequential \n" . + "damages, so the above limitation may not apply to you. This notice will only \n". + "display on the first run on a given system.\n". + "To suppress the disclaimer on other machines, use Bastille\'s -n flag (example: bastille -n).\n"; + + +# If the user has specified not to show the disclaimer, or +# the .bastille_disclaimer file already exists, then return + if( ( $nodisclaim ) || -e $nodisclaim_file ) { return 1; } + +# otherwise, show the disclaimer + print ($DISCLAIMER); + +# there is a response + my $touch = &getGlobal('BIN', "touch"); + my $retVal = system("$touch $nodisclaim_file"); + if( $retVal != 0 ) { + &ErrorLog ( &getGlobal('ERROR','disclaimer')); + } +} # showDisclaimer + + + + +################################################################ +# &systemCall +#Function used by exported methods B_Backtick and B_system +#to handle the mechanics of system calls. +# This function also manages error handling. +# Input: a system call +# Output: a list containing the status, sstdout and stderr +# of the the system call +# +################################################################ +sub systemCall ($){ + no strict; + local $command=$_[0]; # changed scoping so eval below can read it + + local $SIG{'ALRM'} = sub { die "timeout" }; # This subroutine exits the "eval" below. The program + # can then move on to the next operation. Used "local" + # to avoid name space collision with disclaim alarm. + local $WAIT_TIME=120; # Wait X seconds for system commands + local $commandOutput = ''; + my $errOutput = ''; + eval{ + $errorFile = &getGlobal('BFILE','stderrfile'); + unlink($errorFile); #To make sure we don't mix output + alarm($WAIT_TIME); # start a time-out for command to complete. Some commands hang, and we want to + # fail gracefully. When we call "die" it exits this eval statement + # with a value we use below + $commandOutput = `$command 2> $errorFile`; # run the command and gather its output + my $commandRetVal = ($? >> 8); # find the commands return value + if ($commandRetVal == 0) { + &B_log("ACTION","Executed Command: " . $command . "\n"); + &B_log("ACTION","Command Output: " . $commandOutput . "\n"); + die "success"; + } else { + die "failure"; + }; + }; + + my $exitcode=$@; + alarm(0); # End of the timed operation + + my $cat = &getGlobal("BIN","cat"); + if ( -e $errorFile ) { + $errOutput = `$cat $errorFile`; + } + + if ($exitcode) { # The eval command above will exit with one of the 3 values below + if ($exitcode =~ /timeout/) { + &B_log("WARNING","No response received from $command after $WAIT_TIME seconds.\n" . + "Command Output: " . $commandOutput . "\n"); + return (0,'',''); + } elsif ($exitcode =~ /success/) { + return (1,$commandOutput,$errOutput); + } elsif ($exitcode =~ /failure/) { + return (0,$commandOutput,$errOutput); + } else { + &B_log("FATAL","Unexpected return state from command execution: $command\n" . + "Command Output: " . $commandOutput . "\n"); + } + } +} + +############################################# +# Use this **only** for commands used that are +# intended to test system state and +# not make any system change. Use this in place of the +# prior use of "backticks throughout Bastille +# Handles basic output redirection, but not for stdin +# Input: Command +# Output: Results +############################################# + +sub B_Backtick($) { + my $command=$_[0]; + my $combineOutput=0; + my $stdoutRedir = ""; + my $stderrRedir = ""; + my $echo = &getGlobal('BIN','echo'); + + if (($command =~ s/2>&1//) or + (s/>&2//)){ + $combineOutput=1; + } + if ($command =~ s/>\s*([^>\s])+// ) { + $stdoutRedir = $1; + } + if ($command =~ s/2>\s*([^>\s])+// ) { + $stderrRedir = $1; + } + + my ($ranFine, $stdout, $stderr) = &systemCall($command); + if ($ranFine) { + &B_log("DEBUG","Command: $command succeeded for test with output: $stdout , ". + "and stderr: $stderr"); + } else { + &B_log("DEBUG","Command: $command failed for test with output: $stdout , ". + "and stderr: $stderr"); + } + if ($combineOutput) { + $stdout .= $stderr; + $stderr = $stdout; #these should be the same + } + if ($stdoutRedir ne "") { + system("$echo \'$stdout\' > $stdoutRedir"); + } + if ($stderrRedir ne "") { + system("$echo \'$stderr\' > $stderrRedir"); + } + return $stdout; +} + +#################################################################### +# &B_System($command,$revertcommand); +# This function executes a command, then places the associated +# revert command in revert file. It takes two parameters, the +# command and the command that reverts that command. +# +# uses ActionLog and ErrorLog for logging purposes. +################################################################### +sub B_System ($$) { + my ($command,$revertcmd)=@_; + + my ($ranFine, $stdout, $stderr) = &systemCall($command); + if ($ranFine) { + &B_revert_log ("$revertcmd \n"); + if ($stderr ne '' ) { + &B_log("ACTION",$command . "suceeded with STDERR: " . + $stderr . "\n"); + } + return 1; + } else { + my $warningString = "Command Failed: " . $command . "\n" . + "Command Output: " . $stdout . "\n"; + if ($stderr ne '') { + $warningString .= "Error message: " . $stderr; + } + &B_log("WARNING", $warningString); + return 0; + } +} + + +########################################################################### +# &isProcessRunning($procPattern); +# +# If called in scalar context this subroutine will return a 1 if the +# pattern specified can be matched against the process table. It will +# return a 0 otherwise. +# If called in the list context this subroutine will return the list +# of processes which matched the pattern supplied +# +# scalar return values: +# 0: pattern not in process table +# 1: pattern is in process table +# +# list return values: +# proc lines from the process table if they are found +########################################################################### +sub isProcessRunning($) { + + my $procPattern= $_[0]; + my $ps = &getGlobal('BIN',"ps"); + + my $isRunning=0; + # process table. + my @psTable = `$ps -elf`; + # list of processes that match the $procPattern + my @procList; + foreach my $process (@psTable) { + if($process =~ $procPattern) { + $isRunning = 1; + push @procList, $process . "\n"; + } + } + + &B_log("DEBUG","$procPattern search yielded $isRunning\n\n"); + # if this subroutine was called in scalar context + if( ! wantarray ) { + return $isRunning; + } + + return @procList; +} + + +########################################################################### +# &checkProcsForService($service); +# +# Checks if the given service is running by analyzing the process table. +# This is a helper function to checkServiceOnLinux and checkServiceOnHP +# +# Return values: +# SECURE_CANT_CHANGE() if the service is off +# INCONSISTENT() if the state of the service cannot be determined +# +# Mostly used in "check service" direct-return context, but added option use. +# to ignore warning if a check for a service ... where a found service doesn't +# have direct security problems. +# +########################################################################### +sub checkProcsForService ($;$) { + my $service=$_[0]; + my $ignore_warning=$_[1]; + + my @psnames=@{ &getGlobal('PROCESS',$service)}; + + my @processes; + # inetd services don't have a separate process + foreach my $psname (@psnames) { + my @procList = &isProcessRunning($psname); + if(@procList >= 0){ + splice @processes,$#processes+1,0,@procList; + } + } + + if($#processes >= 0){ + if ((defined($ignore_warning)) and ($ignore_warning eq "ignore_warning")) { + &B_log("WARNING","The following processes were still running even though " . + "the corresponding service appears to be turned off. Bastille " . + "question and action will be skipped.\n\n" . + "@processes\n\n"); + # processes were still running, service is not off, but we don't know how + # to configure it so we skip the question + return INCONSISTENT(); + } else { + return NOTSECURE_CAN_CHANGE(); # In the case we're ignoring the warning, + # ie: checking to make *sure* a process + # is running, the answer isn't inconsistent + } + } else { + &B_log("DEBUG","$service is off. Found no processes running on the system."); + # no processes, so service is off + return SECURE_CANT_CHANGE(); + } + # Can't determine the state of the service by looking at the processes, + # so return INCONSISTENT(). + return INCONSISTENT(); +} + +########################################################################### +# B_parse_fstab() +# +# Search the filesystem table for a specific mount point. +# +# scalar return value: +# The line form the table that matched the mount point, or the null string +# if no match was found. +# +# list return value: +# A list of parsed values from the line of the table that matched, with +# element [3] containing a reference to a hash of the mount options. The +# keys are: acl, dev, exec, rw, suid, sync, or user. The value of each key +# can be either 0 or 1. To access the hash, use code similar to this: +# %HashResult = %{(&B_parse_fstab($MountPoint))[3]}; +# +########################################################################### + +sub B_parse_fstab($) +{ + my $name = shift; + my $file = &getGlobal('FILE','fstab'); + my ($enable, $disable, $infile); + my @lineopt; + my $retline = ""; + my @retlist = (); + + unless (open FH, $file) { + &B_log('ERROR',"B_parse_fstab couldn't open fstab file at path $file.\n"); + return 0; + } + while (<FH>) { + s/\#.*//; + next unless /\S/; + @retlist = split; + next unless $retlist[1] eq $name; + $retline .= $_; + if (wantarray) { + my $option = { # initialize to defaults + acl => 0, # for ext2, etx3, reiserfs + dev => 1, + exec => 1, + rw => 1, + suid => 1, + sync => 0, + user => 0, + }; + + my @lineopt = split(',',$retlist[3]); + foreach my $entry (@lineopt) { + if ($entry eq 'acl') { + $option->{'acl'} = 1; + } + elsif ($entry eq 'nodev') { + $option->{'dev'} = 0; + } + elsif ($entry eq 'noexec') { + $option->{'exec'} = 0; + } + elsif ($entry eq 'ro') { + $option->{'rw'} = 0; + } + elsif ($entry eq 'nosuid') { + $option->{'suid'} = 0; + } + elsif ($entry eq 'sync') { + $option->{'sync'} = 1; + } + elsif ($entry eq 'user') { + $option->{'user'} = 1; + } + } + $retlist[3]= $option; + } + last; + } + + if (wantarray) + { + return @retlist; + } + else + { + return $retline; + } + +} + + +########################################################################### +# B_parse_mtab() +# +# This routine returns a hash of devices and their mount points from mtab, +# simply so you can get a list of mounted filesystems. +# +########################################################################### + +sub B_parse_mtab +{ + my $mountpoints; + open(MTAB,&getGlobal('FILE','mtab')); + while(my $mtab_line = <MTAB>) { + #test if it's a device + if ($mtab_line =~ /^\//) + { + #parse out device and mount point + $mtab_line =~ /^(\S+)\s+(\S+)/; + $mountpoints->{$1} = $2; + } + } + return $mountpoints; +} + + +########################################################################### +# B_is_rpm_up_to_date() +# +# +########################################################################### + +sub B_is_rpm_up_to_date(@) +{ + my($nameB,$verB,$relB,$epochB) = @_; + my $installedpkg = $nameB; + + if ($epochB =~ /(none)/) { + $epochB = 0; + } + + my $rpmA = `rpm -q --qf '%{VERSION}-%{RELEASE}-%{EPOCH}\n' $installedpkg`; + my $nameA = $nameB; + my ($verA,$relA,$epochA); + + my $retval; + + # First, if the RPM isn't installed, let's handle that. + if ($rpmA =~ /is not installed/) { + $retval = -1; + return $retval; + } + else { + # Next, let's try to parse the EVR information without as few + # calls as possible to rpm. + if ($rpmA =~ /([^-]+)-([^-]+)-([^-]+)$/) { + $verA = $1; + $relA = $2; + $epochA = $3; + } + else { + $nameA = `rpm -q --qf '%{NAME}' $installedpkg`; + $verA = `rpm -q --qf '%{VERSION}' $installedpkg`; + $relA = `rpm -q --qf '%{RELEASE}' $installedpkg`; + $epochA = `rpm -q --qf '%{EPOCH}' $installedpkg`; + } + } + + # Parse "none" as 0. + if ($epochA =~ /(none)/) { + $epochA = 0; + } + + # Handle the case where only one of them is zero. + if ($epochA == 0 xor $epochB == 0) + { + if ($epochA != 0) + { + $retval = 1; + } + else + { + $retval = 0; + } + } + else + { + # ...otherwise they are either both 0 or both non-zero and + # so the situation isn't trivial. + + # Check epoch first - highest epoch wins. + my $rpmcmp = &cmp_vers_part($epochA, $epochB); + #print "epoch rpmcmp is $rpmcmp\n"; + if ($rpmcmp > 0) + { + $retval = 1; + } + elsif ($rpmcmp < 0) + { + $retval = 0; + } + else + { + # Epochs were the same. Check Version now. + $rpmcmp = &cmp_vers_part($verA, $verB); + #print "epoch rpmcmp is $rpmcmp\n"; + if ($rpmcmp > 0) + { + $retval = 1; + } + elsif ($rpmcmp < 0) + { + $retval = 0; + } + else + { + # Versions were the same. Check Release now. + my $rpmcmp = &cmp_vers_part($relA, $relB); + #print "epoch rpmcmp is $rpmcmp\n"; + if ($rpmcmp >= 0) + { + $retval = 1; + } + elsif ($rpmcmp < 0) + { + $retval = 0; + } + } + } + } + return $retval; +} + +################################################# +# Helper function for B_is_rpm_up_to_date() +################################################# + +#This cmp_vers_part function taken from Kirk Bauer's Autorpm. +# This version comparison code was sent in by Robert Mitchell and, although +# not yet perfect, is better than the original one I had. He took the code +# from freshrpms and did some mods to it. Further mods by Simon Liddington +# <sjl96v@ecs.soton.ac.uk>. +# +# Splits string into minors on . and change from numeric to non-numeric +# characters. Minors are compared from the beginning of the string. If the +# minors are both numeric then they are numerically compared. If both minors +# are non-numeric and a single character they are alphabetically compared, if +# they are not a single character they are checked to be the same if the are not +# the result is unknown (currently we say the first is newer so that we have +# a choice to upgrade). If one minor is numeric and one non-numeric then the +# numeric one is newer as it has a longer version string. +# We also assume that (for example) .15 is equivalent to 0.15 + +sub cmp_vers_part($$) { + my($va, $vb) = @_; + my(@va_dots, @vb_dots); + my($a, $b); + my($i); + + if ($vb !~ /^pre/ and $va =~ s/^pre(\d+.*)$/$1/) { + if ($va eq $vb) { return -1; } + } elsif ($va !~ /^pre/ and $vb =~ s/^pre(\d+.*)$/$1/) { + if ($va eq $vb) { return 1; } + } + + @va_dots = split(/\./, $va); + @vb_dots = split(/\./, $vb); + + $a = shift(@va_dots); + $b = shift(@vb_dots); + # We also assume that (for example) .15 is equivalent to 0.15 + if ($a eq '' && $va ne '') { $a = "0"; } + if ($b eq '' && $vb ne '') { $b = "0"; } + while ((defined($a) && $a ne '') || (defined($b) && $b ne '')) { + # compare each minor from left to right + if ((not defined($a)) || ($a eq '')) { return -1; } # the longer version is newer + if ((not defined($b)) || ($b eq '')) { return 1; } + if ($a =~ /^\d+$/ && $b =~ /^\d+$/) { + # I have changed this so that when the two strings are numeric, but one or both + # of them start with a 0, then do a string compare - Kirk Bauer - 5/28/99 + if ($a =~ /^0/ or $b =~ /^0/) { + # We better string-compare so that netscape-4.6 is newer than netscape-4.08 + if ($a ne $b) {return ($a cmp $b);} + } + # numeric compare + if ($a != $b) { return $a <=> $b; } + } elsif ($a =~ /^\D+$/ && $b =~ /^\D+$/) { + # string compare + if (length($a) == 1 && length($b) == 1) { + # only minors with one letter seem to be useful for versioning + if ($a ne $b) { return $a cmp $b; } + } elsif (($a cmp $b) != 0) { + # otherwise we should at least check they are the same and if not say unknown + # say newer for now so at least we get choice whether to upgrade or not + return -1; + } + } elsif ( ($a =~ /^\D+$/ && $b =~ /^\d+$/) || ($a =~ /^\d+$/ && $b =~ /^\D+$/) ) { + # if we get a number in one and a word in another the one with a number + # has a longer version string + if ($a =~ /^\d+$/) { return 1; } + if ($b =~ /^\d+$/) { return -1; } + } else { + # minor needs splitting + $a =~ /\d+/ || $a =~ /\D+/; + # split the $a minor into numbers and non-numbers + my @va_bits = ($`, $&, $'); + $b =~ /\d+/ || $b =~ /\D+/; + # split the $b minor into numbers and non-numbers + my @vb_bits = ($`, $&, $'); + for ( my $j=2; $j >= 0; $j--) { + if ($va_bits[$j] ne '') { unshift(@va_dots,$va_bits[$j]); } + if ($vb_bits[$j] ne '') { unshift(@vb_dots,$vb_bits[$j]); } + } + } + $a = shift(@va_dots); + $b = shift(@vb_dots); + } + return 0; +} + +1; + diff --git a/meta-security/recipes-security/bastille/files/AccountPermission.pm b/meta-security/recipes-security/bastille/files/AccountPermission.pm new file mode 100644 index 000000000..cfbaab1d9 --- /dev/null +++ b/meta-security/recipes-security/bastille/files/AccountPermission.pm @@ -0,0 +1,1060 @@ +package Bastille::API::AccountPermission; +use strict; + +use Bastille::API; + +use Bastille::API::HPSpecific; + +require Exporter; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw( +B_chmod +B_chmod_if_exists +B_chown +B_chown_link +B_chgrp +B_chgrp_link +B_userdel +B_groupdel +B_remove_user_from_group +B_check_owner_group +B_is_unowned_file +B_is_ungrouped_file +B_check_permissions +B_permission_test +B_find_homes +B_is_executable +B_is_suid +B_is_sgid +B_get_user_list +B_get_group_list +B_remove_suid +); +our @EXPORT = @EXPORT_OK; + +########################################################################### +# &B_chmod ($mode, $file) sets the mode of $file to $mode. $mode must +# be stored in octal, so if you want to give mode 700 to /etc/aliases, +# you need to use: +# +# &B_chmod ( 0700 , "/etc/aliases"); +# +# where the 0700 denotes "octal 7-0-0". +# +# &B_chmod ($mode_changes,$file) also respects the symbolic methods of +# changing file permissions, which are often what question authors are +# really seeking. +# +# &B_chmod ("u-s" , "/bin/mount") +# or +# &B_chmod ("go-rwx", "/bin/mount") +# +# +# &B_chmod respects GLOBAL_LOGONLY and uses +# &B_revert_log used to insert a shell command that will return +# the permissions to the pre-Bastille state. +# +# B_chmod allow for globbing now, as of 1.2.0. JJB +# +########################################################################## + + +sub B_chmod($$) { + my ($new_perm,$file_expr)=@_; + my $old_perm; + my $old_perm_raw; + my $new_perm_formatted; + my $old_perm_formatted; + + my $retval=1; + + my $symbolic = 0; + my ($chmod_noun,$add_remove,$capability) = (); + # Handle symbolic possibilities too + if ($new_perm =~ /([ugo]+)([+-]{1})([rwxst]+)/) { + $symbolic = 1; + $chmod_noun = $1; + $add_remove = $2; + $capability = $3; + } + + my $file; + my @files = glob ($file_expr); + + foreach $file (@files) { + + # Prepend global prefix, but save the original filename for B_backup_file + my $original_file=$file; + + # Store the old permissions so that we can log them. + unless (stat $file) { + &B_log("ERROR","Couldn't stat $original_file from $old_perm to change permissions\n"); + next; + } + + $old_perm_raw=(stat(_))[2]; + $old_perm= (($old_perm_raw/512) % 8) . + (($old_perm_raw/64) % 8) . + (($old_perm_raw/8) % 8) . + ($old_perm_raw % 8); + + # If we've gone symbolic, calculate the new permissions in octal. + if ($symbolic) { + # + # We calculate the new permissions by applying a bitmask to + # the current permissions, by OR-ing (for +) or XOR-ing (for -). + # + # We create this mask by first calculating a perm_mask that forms + # the right side of this, then multiplying it by 8 raised to the + # appropriate power to affect the correct digit of the octal mask. + # This means that we raise 8 to the power of 0,1,2, or 3, based on + # the noun of "other","group","user", or "suid/sgid/sticky". + # + # Actually, we handle multiple nouns by summing powers of 8. + # + # The only tough part is that we have to handle suid/sgid/sticky + # differently. + # + + # We're going to calculate a mask to OR or XOR with the current + # file mode. This mask is $mask. We calculate this by calculating + # a sum of powers of 8, corresponding to user/group/other, + # multiplied with a $premask. The $premask is simply the + # corresponding bitwise expression of the rwx bits. + # + # To handle SUID, SGID or sticky in the simplest way possible, we + # simply add their values to the $mask first. + + my $perm_mask = 00; + my $mask = 00; + + # Check for SUID, SGID or sticky as these are exceptional. + if ($capability =~ /s/) { + if ($chmod_noun =~ /u/) { + $mask += 04000; + } + if ($chmod_noun =~ /g/) { + $mask += 02000; + } + } + if ($capability =~ /t/) { + $mask += 01000; + } + + # Now handle the normal attributes + if ($capability =~ /[rwx]/) { + if ($capability =~ /r/) { + $perm_mask |= 04; + } + if ($capability =~ /w/) { + $perm_mask |= 02; + } + if ($capability =~ /x/) { + $perm_mask |= 01; + } + + # Now figure out which 3 bit octal digit we're affecting. + my $power = 0; + if ($chmod_noun =~ /u/) { + $mask += $perm_mask * 64; + } + if ($chmod_noun =~ /g/) { + $mask += $perm_mask * 8; + } + if ($chmod_noun =~ /o/) { + $mask += $perm_mask * 1; + } + } + # Now apply the mask to get the new permissions + if ($add_remove eq '+') { + $new_perm = $old_perm_raw | $mask; + } + elsif ($add_remove eq '-') { + $new_perm = $old_perm_raw & ( ~($mask) ); + } + } + + # formating for simple long octal output of the permissions in string form + $new_perm_formatted=sprintf "%5lo",$new_perm; + $old_perm_formatted=sprintf "%5lo",$old_perm_raw; + + &B_log("ACTION","change permissions on $original_file from $old_perm_formatted to $new_perm_formatted\n"); + + &B_log("ACTION", "chmod $new_perm_formatted,\"$original_file\";\n"); + + # Change the permissions on the file + + if ( -e $file ) { + unless ($GLOBAL_LOGONLY) { + $retval=chmod $new_perm,$file; + if($retval){ + # if the distribution is HP-UX then the modifications should + # also be made to the IPD (installed product database) + if(&GetDistro =~ "^HP-UX"){ + &B_swmodify($file); + } + # making changes revert-able + &B_revert_log(&getGlobal('BIN', "chmod") . " $old_perm $file\n"); + } + } + unless ($retval) { + &B_log("ERROR","Couldn't change permissions on $original_file from $old_perm_formatted to $new_perm_formatted\n"); + $retval=0; + } + } + else { + &B_log("ERROR", "chmod: File $original_file doesn't exist!\n"); + $retval=0; + } + } + + $retval; + +} + +########################################################################### +# &B_chmod_if_exists ($mode, $file) sets the mode of $file to $mode *if* +# $file exists. $mode must be stored in octal, so if you want to give +# mode 700 to /etc/aliases, you need to use: +# +# &B_chmod_if_exists ( 0700 , "/etc/aliases"); +# +# where the 0700 denotes "octal 7-0-0". +# +# &B_chmod_if_exists respects GLOBAL_LOGONLY and uses +# &B_revert_log to reset the permissions of the file. +# +# B_chmod_if_exists allow for globbing now, as of 1.2.0. JJB +# +########################################################################## + + +sub B_chmod_if_exists($$) { + my ($new_perm,$file_expr)=@_; + # If $file_expr has a glob character, pass it on (B_chmod won't complain + # about nonexistent files if given a glob pattern) + if ( $file_expr =~ /[\*\[\{]/ ) { # } just to match open brace for vi + &B_log("ACTION","Running chmod $new_perm $file_expr"); + return(&B_chmod($new_perm,$file_expr)); + } + # otherwise, test for file existence + if ( -e $file_expr ) { + &B_log("ACTION","File exists, running chmod $new_perm $file_expr"); + return(&B_chmod($new_perm,$file_expr)); + } +} + +########################################################################### +# &B_chown ($uid, $file) sets the owner of $file to $uid, like this: +# +# &B_chown ( 0 , "/etc/aliases"); +# +# &B_chown respects $GLOBAL_LOGONLY and uses +# &B_revert_log to insert a shell command that will return +# the file/directory owner to the pre-Bastille state. +# +# Unlike Perl, we've broken the chown function into B_chown/B_chgrp to +# make error checking simpler. +# +# As of 1.2.0, this now supports file globbing. JJB +# +########################################################################## + + +sub B_chown($$) { + my ($newown,$file_expr)=@_; + my $oldown; + my $oldgown; + + my $retval=1; + + my $file; + my @files = glob($file_expr); + + foreach $file (@files) { + + # Prepend prefix, but save original filename + my $original_file=$file; + + $oldown=(stat $file)[4]; + $oldgown=(stat $file)[5]; + + &B_log("ACTION","change ownership on $original_file from $oldown to $newown\n"); + &B_log("ACTION","chown $newown,$oldgown,\"$original_file\";\n"); + if ( -e $file ) { + unless ($GLOBAL_LOGONLY) { + # changing the files owner using perl chown function + $retval = chown $newown,$oldgown,$file; + if($retval){ + # if the distribution is HP-UX then the modifications should + # also be made to the IPD (installed product database) + if(&GetDistro =~ "^HP-UX"){ + &B_swmodify($file); + } + # making ownership change revert-able + &B_revert_log(&getGlobal('BIN', "chown") . " $oldown $file\n"); + } + } + unless ($retval) { + &B_log("ERROR","Couldn't change ownership to $newown on file $original_file\n"); + } + } + else { + &B_log("ERROR","chown: File $original_file doesn't exist!\n"); + $retval=0; + } + } + + $retval; +} + +########################################################################### +# &B_chown_link just like &B_chown but one exception: +# if the input file is a link it will not change the target's ownship, it only change the link itself's ownship +########################################################################### +sub B_chown_link($$){ + my ($newown,$file_expr)=@_; + my $chown = &getGlobal("BIN","chown"); + my @files = glob($file_expr); + my $retval = 1; + + foreach my $file (@files) { + # Prepend prefix, but save original filename + my $original_file=$file; + my $oldown=(stat $file)[4]; + my $oldgown=(stat $file)[5]; + + &B_log("ACTION","change ownership on $original_file from $oldown to $newown\n"); + &B_log("ACTION","chown -h $newown,\"$original_file\";\n"); + if ( -e $file ) { + unless ($GLOBAL_LOGONLY) { + `$chown -h $newown $file`; + $retval = ($? >> 8); + if($retval == 0 ){ + # if the distribution is HP-UX then the modifications should + # also be made to the IPD (installed product database) + if(&GetDistro =~ "^HP-UX"){ + &B_swmodify($file); + } + # making ownership change revert-able + &B_revert_log("$chown -h $oldown $file\n"); + } + } + unless ( ! $retval) { + &B_log("ERROR","Couldn't change ownership to $newown on file $original_file\n"); + } + } + else { + &B_log("ERROR","chown: File $original_file doesn't exist!\n"); + $retval=0; + } + } +} + + +########################################################################### +# &B_chgrp ($gid, $file) sets the group owner of $file to $gid, like this: +# +# &B_chgrp ( 0 , "/etc/aliases"); +# +# &B_chgrp respects $GLOBAL_LOGONLY and uses +# &B_revert_log to insert a shell command that will return +# the file/directory group to the pre-Bastille state. +# +# Unlike Perl, we've broken the chown function into B_chown/B_chgrp to +# make error checking simpler. +# +# As of 1.2.0, this now supports file globbing. JJB +# +########################################################################## + + +sub B_chgrp($$) { + my ($newgown,$file_expr)=@_; + my $oldown; + my $oldgown; + + my $retval=1; + + my $file; + my @files = glob($file_expr); + + foreach $file (@files) { + + # Prepend global prefix, but save original filename for &B_backup_file + my $original_file=$file; + + $oldown=(stat $file)[4]; + $oldgown=(stat $file)[5]; + + &B_log("ACTION", "Change group ownership on $original_file from $oldgown to $newgown\n"); + &B_log("ACTION", "chown $oldown,$newgown,\"$original_file\";\n"); + if ( -e $file ) { + unless ($GLOBAL_LOGONLY) { + # changing the group for the file/directory + $retval = chown $oldown,$newgown,$file; + if($retval){ + # if the distribution is HP-UX then the modifications should + # also be made to the IPD (installed product database) + if(&GetDistro =~ "^HP-UX"){ + &B_swmodify($file); + } + &B_revert_log(&getGlobal('BIN', "chgrp") . " $oldgown $file\n"); + } + } + unless ($retval) { + &B_log("ERROR","Couldn't change ownership to $newgown on file $original_file\n"); + } + } + else { + &B_log("ERROR","chgrp: File $original_file doesn't exist!\n"); + $retval=0; + } + } + + $retval; +} + +########################################################################### +# &B_chgrp_link just like &B_chgrp but one exception: +# if the input file is a link +# it will not change the target's ownship, it only change the link itself's ownship +########################################################################### +sub B_chgrp_link($$) { + my ($newgown,$file_expr)=@_; + my $chgrp = &getGlobal("BIN","chgrp"); + my @files = glob($file_expr); + my $retval=1; + + foreach my $file (@files) { + # Prepend prefix, but save original filename + my $original_file=$file; + my $oldgown=(stat $file)[5]; + + &B_log("ACTION","change group ownership on $original_file from $oldgown to $newgown\n"); + &B_log("ACTION","chgrp -h $newgown \"$original_file\";\n"); + if ( -e $file ) { + unless ($GLOBAL_LOGONLY) { + # do not follow link with option -h + `$chgrp -h $newgown $file`; + $retval = ($? >> 8); + if($retval == 0 ){ + # if the distribution is HP-UX then the modifications should + # also be made to the IPD (installed product database) + if(&GetDistro =~ "^HP-UX"){ + &B_swmodify($file); + } + # making ownership change revert-able + &B_revert_log("$chgrp" . " -h $oldgown $file\n"); + } + } + unless (! $retval) { + &B_log("ERROR","Couldn't change group ownership to $newgown on file $original_file\n"); + } + } + else { + &B_log("ERROR","chgrp: File $original_file doesn't exist!\n"); + $retval=0; + } + } +} + +########################################################################### +# B_userdel($user) removes $user from the system, chmoding her home +# directory to 000, root:root owned, and removes the user from all +# /etc/passwd, /etc/shadow and /etc/group lines. +# +# In the future, we may also choose to make a B_lock_account routine. +# +# This routine depends on B_remove_user_from_group. +########################################################################### + +sub B_userdel($) { + + my $user_to_remove = $_[0]; + + if (&GetDistro =~ /^HP-UX/) { + return 0; + + # Not yet suported on HP-UX, where we'd need to support + # the TCB files and such. + } + + # + # First, let's chmod/chown/chgrp the user's home directory. + # + + # Get the user's home directory from /etc/passwd + if (open PASSWD,&getGlobal('FILE','passwd')) { + my @lines=<PASSWD>; + close PASSWD; + + # Get the home directory + my $user_line = grep '^\s*$user_to_remove\s*:',@lines; + my $home_directory = (split /\s*:\s*/,$user_line)[5]; + + # Chmod that home dir to 0000,owned by uid 0, gid 0. + if (&B_chmod_if_exists(0000,$home_directory)) { + &B_chown(0,$home_directory); + &B_chgrp(0,$home_directory); + } + } + else { + &B_log('ERROR',"B_userdel couldn't open the passwd file to remove a user."); + return 0; + } + + # + # Next find out what groups the user is in, so we can call + # B_remove_user_from_group($user,$group) + # + # TODO: add this to the helper functions for the test suite. + # + + my @groups = (); + + # Parse /etc/group, looking for our user. + if (open GROUP,&getGlobal('FILE','group')) { + my @lines = <GROUP>; + close GROUP; + + foreach my $line (@lines) { + + # Parse the line -- first field is group, last is users in group. + if ($line =~ /([^\#^:]+):[^:]+:[^:]+:(.*)/) { + my $group = $1; + my $users_section = $2; + + # Get the user list and check if our user is in it. + my @users = split /\s*,\s*/,$users_section; + foreach my $user (@users) { + if ($user_to_remove eq $user) { + push @groups,$group; + last; + } + } + } + } + } + + # Now remove the user from each of those groups. + foreach my $group (@groups) { + &B_remove_user_from_group($user_to_remove,$group); + } + + # Remove the user's /etc/passwd and /etc/shadow lines + &B_delete_line(&getGlobal('FILE','passwd'),"^$user_to_remove\\s*:"); + &B_delete_line(&getGlobal('FILE','shadow'),"^$user_to_remove\\s*:"); + + + # + # We should delete the user's group as well, if it's a single-user group. + # + if (open ETCGROUP,&getGlobal('FILE','group')) { + my @group_lines = <ETCGROUP>; + close ETCGROUP; + chomp @group_lines; + + if (grep /^$user_to_remove\s*:[^:]*:[^:]*:\s*$/,@group_lines > 0) { + &B_groupdel($user_to_remove); + } + } + +} + +########################################################################### +# B_groupdel($group) removes $group from /etc/group. +########################################################################### + +sub B_groupdel($) { + + my $group = $_[0]; + + # First read /etc/group to make sure the group is in there. + if (open GROUP,&getGlobal('FILE','group')) { + my @lines=<GROUP>; + close GROUP; + + # Delete the line in /etc/group if present + if (grep /^$group:/,@lines > 0) { + # The group is named in /etc/group + &B_delete_line(&getGlobal('FILE','group'),"^$group:/"); + } + } + +} + + +########################################################################### +# B_remove_user_from_group($user,$group) removes $user from $group, +# by modifying $group's /etc/group line, pulling the user out. This +# uses B_chunk_replace thrice to replace these patterns: +# +# ":\s*$user\s*," --> ":" +# ",\s*$user" -> "" +# +########################################################################### + +sub B_remove_user_from_group($$) { + + my ($user_to_remove,$group) = @_; + + # + # We need to find the line from /etc/group that defines the group, parse + # it, and put it back together without this user. + # + + # Open the group file + unless (open GROUP,&getGlobal('FILE','group')) { + &B_log('ERROR',"&B_remove_user_from_group couldn't read /etc/group to remove $user_to_remove from $group.\n"); + return 0; + } + my @lines = <GROUP>; + close GROUP; + chomp @lines; + + # + # Read through the lines to find the one we care about. We'll construct a + # replacement and then use B_replace_line to make the switch. + # + + foreach my $line (@lines) { + + if ($line =~ /^\s*$group\s*:/) { + + # Parse this line. + my @group_entries = split ':',$line; + my @users = split ',',($group_entries[3]); + + # Now, recreate it. + my $first_user = 1; + my $group_line = $group_entries[0] . ':' . $group_entries[1] . ':' . $group_entries[2] . ':'; + + # Add every user except the one we're removing. + foreach my $user (@users) { + + # Remove whitespace. + $user =~ s/\s+//g; + + if ($user ne $user_to_remove) { + # Add the user to the end of the line, prefacing + # it with a comma if it's not the first user. + + if ($first_user) { + $group_line .= "$user"; + $first_user = 0; + } + else { + $group_line .= ",$user"; + } + } + } + + # The line is now finished. Replace the original line. + $group_line .= "\n"; + &B_replace_line(&getGlobal('FILE','group'),"^\\s*$group\\s*:",$group_line); + } + + } + return 1; +} + +########################################################################### +# &B_check_owner_group($$$) +# +# Checks if the given file has the given owner and/or group. +# If the given owner is "", checks group only. +# If the given group is "", checks owner only. +# +# return values: +# 1: file has the given owner and/or group +# or file exists, and both the given owner and group are "" +# 0: file does not has the given owner or group +# or file does not exists +############################################################################ + +sub B_check_owner_group ($$$){ + my ($fileName, $owner, $group) = @_; + + if (-e $fileName) { + my @junk=stat ($fileName); + my $uid=$junk[4]; + my $gid=$junk[5]; + + # Check file owner + if ($owner ne "") { + if (getpwnam($owner) != $uid) { + return 0; + } + } + + # Check file group + if ($group ne "") { + if (getgrnam($group) != $gid) { + return 0; + } + } + + return 1; + } + else { + # Something is wrong if the file not exist + return 0; + } +} + +########################################################################## +# this subroutine will test whether the given file is unowned +########################################################################## +sub B_is_unowned_file($) { + my $file =$_; + my $uid = (stat($file))[4]; + my $uname = (getpwuid($uid))[0]; + if ( $uname =~ /.+/ ) { + return 1; + } + return 0; +} + +########################################################################## +# this subroutine will test whether the given file is ungrouped +########################################################################## +sub B_is_ungrouped_file($){ + my $file =$_; + my $gid = (stat($file))[5]; + my $gname = (getgrgid($gid))[0]; + if ( $gname =~ /.+/ ) { + return 1; + } + return 0; +} + + + + +########################################################################### +# &B_check_permissions($$) +# +# Checks if the given file has the given permissions or stronger, where we +# define stronger as "less accessible." The file argument must be fully +# qualified, i.e. contain the absolute path. +# +# return values: +# 1: file has the given permissions or better +# 0: file does not have the given permsssions +# undef: file permissions cannot be determined +########################################################################### + +sub B_check_permissions ($$){ + my ($fileName, $reqdPerms) = @_; + my $filePerms; # actual permissions + + + if (-e $fileName) { + if (stat($fileName)) { + $filePerms = (stat($fileName))[2] & 07777; + } + else { + &B_log ("ERROR", "Can't stat $fileName.\n"); + return undef; + } + } + else { + # If the file does not exist, permissions are as good as they can get. + return 1; + } + + # + # We can check whether the $filePerms are as strong by + # bitwise ANDing them with $reqdPerms and checking if the + # result is still equal to $filePerms. If it is, the + # $filePerms are strong enough. + # + if ( ($filePerms & $reqdPerms) == $filePerms ) { + return 1; + } + else { + return 0; + } + +} + +########################################################################## +# B_permission_test($user, $previlege,$file) +# $user can be +# "owner" +# "group" +# "other" +# $previlege can be: +# "r" +# "w" +# "x" +# "suid" +# "sgid" +# "sticky" +# if previlege is set to suid or sgid or sticky, then $user can be empty +# this sub routine test whether the $user has the specified previlige to $file +########################################################################## + +sub B_permission_test($$$){ + my ($user, $previlege, $file) = @_; + + if (-e $file ) { + my $mode = (stat($file))[2]; + my $bitpos; + # bitmap is | suid sgid sticky | rwx | rwx | rwx + if ($previlege =~ /suid/ ) { + $bitpos = 11; + } + elsif ($previlege =~ /sgid/ ) { + $bitpos = 10; + } + elsif ($previlege =~ /sticky/ ) { + $bitpos = 9; + } + else { + if ( $user =~ /owner/) { + if ($previlege =~ /r/) { + $bitpos = 8; + } + elsif ($previlege =~ /w/) { + $bitpos =7; + } + elsif ($previlege =~ /x/) { + $bitpos =6; + } + else { + return 0; + } + } + elsif ( $user =~ /group/) { + if ($previlege =~ /r/) { + $bitpos =5; + } + elsif ($previlege =~ /w/) { + $bitpos =4; + } + elsif ($previlege =~ /x/) { + $bitpos =3; + } + else { + return 0; + } + } + elsif ( $user =~ /other/) { + if ($previlege =~ /r/) { + $bitpos =2; + } + elsif ($previlege =~ /w/) { + $bitpos =1; + } + elsif ($previlege =~ /x/) { + $bitpos =0; + } + else { + return 0; + } + } + else { + return 0; + } + } + $mode /= 2**$bitpos; + if ($mode % 2) { + return 1; + } + return 0; + } +} + +########################################################################## +# this subroutine will return a list of home directory +########################################################################## +sub B_find_homes(){ + # find loginable homes + my $logins = &getGlobal("BIN","logins"); + my @lines = `$logins -ox`; + my @homes; + foreach my $line (@lines) { + chomp $line; + my @data = split /:/, $line; + if ($data[7] =~ /PS/ && $data[5] =~ /home/) { + push @homes, $data[5]; + } + } + return @homes; +} + + +########################################################################### +# B_is_executable($) +# +# This routine reports on whether a file is executable by the current +# process' effective UID. +# +# scalar return values: +# 0: file is not executable +# 1: file is executable +# +########################################################################### + +sub B_is_executable($) +{ + my $name = shift; + my $executable = 0; + + if (-x $name) { + $executable = 1; + } + return $executable; +} + +########################################################################### +# B_is_suid($) +# +# This routine reports on whether a file is Set-UID and owned by root. +# +# scalar return values: +# 0: file is not SUID root +# 1: file is SUID root +# +########################################################################### + +sub B_is_suid($) +{ + my $name = shift; + + my @FileStatus = stat($name); + my $IsSuid = 0; + + if (-u $name) #Checks existence and suid + { + if($FileStatus[4] == 0) { + $IsSuid = 1; + } + } + + return $IsSuid; +} + +########################################################################### +# B_is_sgid($) +# +# This routine reports on whether a file is SGID and group owned by +# group root (gid 0). +# +# scalar return values: +# 0: file is not SGID root +# 1: file is SGID root +# +########################################################################### + +sub B_is_sgid($) +{ + my $name = shift; + + my @FileStatus = stat($name); + my $IsSgid = 0; + + if (-g $name) #checks existence and sgid + { + if($FileStatus[5] == 0) { + $IsSgid = 1; + } + } + + return $IsSgid; +} + +########################################################################### +# B_get_user_list() +# +# This routine outputs a list of users on the system. +# +########################################################################### + +sub B_get_user_list() +{ + my @users; + open(PASSWD,&getGlobal('FILE','passwd')); + while(<PASSWD>) { + #Get the users + if (/^([^:]+):/) + { + push (@users,$1); + } + } + return @users; +} + +########################################################################### +# B_get_group_list() +# +# This routine outputs a list of groups on the system. +# +########################################################################### + +sub B_get_group_list() +{ + my @groups; + open(GROUP,&getGlobal('FILE','group')); + while(my $group_line = <GROUP>) { + #Get the groups + if ($group_line =~ /^([^:]+):/) + { + push (@groups,$1); + } + } + return @groups; +} + + +########################################################################### +# &B_remove_suid ($file) removes the suid bit from $file if it +# is set and the file exist. If you would like to remove the suid bit +# from /bin/ping then you need to use: +# +# &B_remove_suid("/bin/ping"); +# +# &B_remove_suid respects GLOBAL_LOGONLY. +# &B_remove_suid uses &B_chmod to make the permission changes +# &B_remove_suid allows for globbing. tyler_e +# +########################################################################### + +sub B_remove_suid($) { + my $file_expr = $_[0]; + + &B_log("ACTION","Removing SUID bit from \"$file_expr\"."); + unless ($GLOBAL_LOGONLY) { + my @files = glob($file_expr); + + foreach my $file (@files) { + # check file existence + if(-e $file){ + # stat current file to get raw permissions + my $old_perm_raw = (stat $file)[2]; + # test to see if suidbit is set + my $suid_bit = (($old_perm_raw/2048) % 2); + if($suid_bit == 1){ + # new permission without the suid bit + my $new_perm = ((($old_perm_raw/512) % 8 ) - 4) . + (($old_perm_raw/64) % 8 ) . + (($old_perm_raw/8) % 8 ) . + (($old_perm_raw) % 8 ); + if(&B_chmod(oct($new_perm), $file)){ + &B_log("ACTION","Removed SUID bit from \"$file\"."); + } + else { + &B_log("ERROR","Could not remove SUID bit from \"$file\"."); + } + } # No action if SUID bit is not set + }# No action if file does not exist + }# Repeat for each file in the file glob + } # unless Global_log +} + + + +1; + diff --git a/meta-security/recipes-security/bastille/files/FileContent.pm b/meta-security/recipes-security/bastille/files/FileContent.pm new file mode 100644 index 000000000..0a5d6096c --- /dev/null +++ b/meta-security/recipes-security/bastille/files/FileContent.pm @@ -0,0 +1,1153 @@ +package Bastille::API::FileContent; +use strict; + +use Bastille::API; + +require Exporter; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw( +B_blank_file +B_insert_line_after +B_insert_line_before +B_insert_line +B_append_line +B_prepend_line +B_replace_line +B_replace_lines +B_replace_pattern +B_match_line +B_match_line_only +B_match_chunk +B_return_matched_lines +B_hash_comment_line +B_hash_uncomment_line +B_delete_line +B_chunk_replace +B_print +B_getValueFromFile +B_getValueFromString + +B_TODO +B_TODOFlags +); +our @EXPORT = @EXPORT_OK; + + + +########################################################################### +# &B_blank_file ($filename,$pattern) blanks the file $filename, unless the +# pattern $pattern is present in the file. This lets us completely redo +# a file, if it isn't the one we put in place on a previous run... +# +# B_blank_file respects $GLOBAL_LOGONLY and uses B_open_plus and B_close_plus +# so that it makes backups and only modifies files when we're not in "-v" +# mode... +# +# If the file does not exist, the function does nothing, and gives an error +# to the Error Log +# +########################################################################### + +sub B_blank_file($$) { + + my ($filename,$pattern) = @_; + my $retval; + + # If this variable is true, we won't blank the file... + + my $found_pattern=0; + + if ($retval=&B_open_plus (*BLANK_NEW,*BLANK_OLD,$filename) ) { + + my @lines; + + while (my $line = <BLANK_OLD>) { + + push @lines,$line; + if ($line =~ $pattern) { + $found_pattern=1; + } + } + + # Only copy the old file if the new one didn't match. + if ($found_pattern) { + while ( my $line = shift @lines ) { + &B_print(*BLANK_NEW,$line); + } + } + else { + &B_log("ACTION","Blanked file $filename\n"); + } + &B_close_plus(*BLANK_NEW,*BLANK_OLD,$filename); + } + else { + &B_log("ERROR","Couldn't blank file $filename since we couldn't open it or its replacement\n"); + } + + return $retval; + +} + +########################################################################### +# &B_insert_line_after ($filename,$pattern,$line_to_insert,$line_to_follow) +# modifies $filename, inserting $line_to_insert unless one or more lines +# in the file matches $pattern. The $line_to_insert will be placed +# immediately after $line_to_follow, if it exists. If said line does not +# exist, the line will not be inserted and this routine will return 0. +# +# B_insert_line uses B_open_plus and B_close_plus, so that the file +# modified is backed up... +# +# Here's examples of where you might use this: +# +# You'd like to insert a line in Apache's configuration file, in a +# particular section. +# +########################################################################### + +sub B_insert_line_after($$$$) { + + my ($filename,$pattern,$line_to_insert,$line_to_follow) = @_; + + my @lines; + my $found_pattern=0; + my $found_line_to_follow=0; + + my $retval=1; + + if ( &B_open_plus (*INSERT_NEW,*INSERT_OLD,$filename) ) { + + # Read through the file looking for a match both on the $pattern + # and the line we are supposed to be inserting after... + + my $ctr=1; + while (my $line=<INSERT_OLD>) { + push (@lines,$line); + if ($line =~ $pattern) { + $found_pattern=1; + } + if ( ($found_line_to_follow < 1) and ($line =~ $line_to_follow)) { + $found_line_to_follow=$ctr; + } + $ctr++; + } + + # Log an error if we never found the line we were to insert after + unless ($found_line_to_follow ) { + $retval=0; + &B_log("ERROR","Never found the line that we were supposed to insert after in $filename\n"); + } + + # Now print the file back out, inserting our line if we should... + + $ctr=1; + while (my $line = shift @lines) { + &B_print(*INSERT_NEW,$line); + if ( ($ctr == $found_line_to_follow) and ($found_pattern == 0) ) { + &B_print(*INSERT_NEW,$line_to_insert); + &B_log("ACTION","Inserted the following line in $filename:\n"); + &B_log("ACTION","$line_to_insert"); + } + $ctr++; + } + + &B_close_plus (*INSERT_NEW,*INSERT_OLD,$filename); + + } + else { + $retval=0; + &B_log("ERROR","Couldn't insert line to $filename, since open failed."); + } + + return $retval; + +} +########################################################################### +# &B_insert_line_before ($filename,$pattern,$line_to_insert,$line_to_preceed) +# modifies $filename, inserting $line_to_insert unless one or more lines +# in the file matches $pattern. The $line_to_insert will be placed +# immediately before $line_to_preceed, if it exists. If said line does not +# exist, the line will not be inserted and this routine will return 0. +# +# B_insert_line uses B_open_plus and B_close_plus, so that the file +# modified is backed up... +# +# Here's examples of where you might use this: +# +# You'd like to insert a line in Apache's configuration file, in a +# particular section. +# +########################################################################### + +sub B_insert_line_before($$$$) { + + my ($filename,$pattern,$line_to_insert,$line_to_preceed) = @_; + + my @lines; + my $found_pattern=0; + my $found_line_to_preceed=0; + + my $retval=1; + + if ( &B_open_plus (*INSERT_NEW,*INSERT_OLD,$filename) ) { + + # Read through the file looking for a match both on the $pattern + # and the line we are supposed to be inserting after... + + my $ctr=1; + while (my $line=<INSERT_OLD>) { + push (@lines,$line); + if ($line =~ $pattern) { + $found_pattern=1; + } + if ( ($found_line_to_preceed < 1) and ($line =~ $line_to_preceed)) { + $found_line_to_preceed=$ctr; + } + $ctr++; + } + + # Log an error if we never found the line we were to preceed + unless ($found_line_to_preceed ) { + $retval=0; + &B_log("ERROR","Never found the line that we were supposed to insert before in $filename\n"); + } + + # Now print the file back out, inserting our line if we should... + + $ctr=1; + while (my $line = shift @lines) { + if ( ($ctr == $found_line_to_preceed) and ($found_pattern == 0) ) { + &B_print(*INSERT_NEW,$line_to_insert); + &B_log("ACTION","Inserted the following line in $filename:\n"); + &B_log("ACTION","$line_to_insert"); + } + &B_print(*INSERT_NEW,$line); + $ctr++; + } + + &B_close_plus (*INSERT_NEW,*INSERT_OLD,$filename); + + } + else { + $retval=0; + &B_log("ERROR","Couldn't insert line to $filename, since open failed."); + } + + return $retval; + +} + +########################################################################### +# &B_insert_line ($filename,$pattern,$line_to_insert,$line_to_follow) +# +# has been renamed to B_insert_line_after() +# +# This name will continue to work, as a shim for code that has not been +# transitioned. +########################################################################### + +sub B_insert_line($$$$) { + + my $rtn_value = &B_insert_line_after(@_); + + return ($rtn_value); +} + + +########################################################################### +# &B_append_line ($filename,$pattern,$line_to_append) modifies $filename, +# appending $line_to_append unless one or more lines in the file matches +# $pattern. This is an enhancement to the append_line_if_no_such_line_exists +# idea. +# +# Additionally, if $pattern is set equal to "", the line is always appended. +# +# B_append_line uses B_open_plus and B_close_plus, so that the file +# modified is backed up... +# +# Here's examples of where you might use this: +# +# You'd like to add a root line to /etc/ftpusers if none exists. +# You'd like to add a Options Indexes line to Apache's config. file, +# after you delete all Options lines from said config file. +# +########################################################################### + +sub B_append_line($$$) { + + my ($filename,$pattern,$line_to_append) = @_; + + my $found_pattern=0; + my $retval=1; + + if ( &B_open_plus (*APPEND_NEW,*APPEND_OLD,$filename) ) { + while (my $line=<APPEND_OLD>) { + &B_print(*APPEND_NEW,$line); + if ($line =~ $pattern) { + $found_pattern=1; + } + } + # Changed != 0 to $pattern so that "" works instead of 0 and perl + # does not give the annoying + # Argument "XX" isn't numeric in ne at ... + if ( $pattern eq "" or ! $found_pattern ) { + &B_print(*APPEND_NEW,$line_to_append); + &B_log("ACTION","Appended the following line to $filename:\n"); + &B_log("ACTION","$line_to_append"); + } + &B_close_plus (*APPEND_NEW,*APPEND_OLD,$filename); + } + else { + $retval=0; + &B_log("ERROR","# Couldn't append line to $filename, since open failed."); + } + + return $retval; + +} + +########################################################################### +# &B_prepend_line ($filename,$pattern,$line_to_prepend) modifies $filename, +# pre-pending $line_to_prepend unless one or more lines in the file matches +# $pattern. This is an enhancement to the prepend_line_if_no_such_line_exists +# idea. +# +# B_prepend_line uses B_open_plus and B_close_plus, so that the file +# modified is backed up... +# +# Here's examples of where you might use this: +# +# You'd like to insert the line "auth required pam_deny.so" to the top +# of the PAM stack file /etc/pam.d/rsh to totally deactivate rsh. +# +########################################################################### + +sub B_prepend_line($$$) { + + my ($filename,$pattern,$line_to_prepend) = @_; + + my @lines; + my $found_pattern=0; + my $retval=1; + + if ( &B_open_plus (*PREPEND_NEW,*PREPEND_OLD,$filename) ) { + while (my $line=<PREPEND_OLD>) { + push (@lines,$line); + if ($line =~ $pattern) { + $found_pattern=1; + } + } + unless ($found_pattern) { + &B_print(*PREPEND_NEW,$line_to_prepend); + } + while (my $line = shift @lines) { + &B_print(*PREPEND_NEW,$line); + } + + &B_close_plus (*PREPEND_NEW,*PREPEND_OLD,$filename); + + # Log the action + &B_log("ACTION","Pre-pended the following line to $filename:\n"); + &B_log("ACTION","$line_to_prepend"); + } + else { + $retval=0; + &B_log("ERROR","Couldn't prepend line to $filename, since open failed.\n"); + } + + return $retval; + +} + + +########################################################################### +# &B_replace_line ($filename,$pattern,$line_to_switch_in) modifies $filename, +# replacing any lines matching $pattern with $line_to_switch_in. +# +# It returns the number of lines it replaced (or would have replaced, if +# LOGONLY mode wasn't on...) +# +# B_replace_line uses B_open_plus and B_close_plus, so that the file +# modified is backed up... +# +# Here an example of where you might use this: +# +# You'd like to replace any Options lines in Apache's config file with: +# Options Indexes FollowSymLinks +# +########################################################################### + +sub B_replace_line($$$) { + + my ($filename,$pattern,$line_to_switch_in) = @_; + my $retval=0; + + if ( &B_open_plus (*REPLACE_NEW,*REPLACE_OLD,$filename) ) { + while (my $line=<REPLACE_OLD>) { + unless ($line =~ $pattern) { + &B_print(*REPLACE_NEW,$line); + } + else { + # Don't replace the line if it's already there. + unless ($line eq $line_to_switch_in) { + &B_print(*REPLACE_NEW,$line_to_switch_in); + + $retval++; + &B_log("ACTION","File modification in $filename -- replaced line\n" . + "$line\n" . + "with:\n" . + "$line_to_switch_in"); + } + # But if it is there, make sure it stays there! (by Paul Allen) + else { + &B_print(*REPLACE_NEW,$line); + } + } + } + &B_close_plus (*REPLACE_NEW,*REPLACE_OLD,$filename); + } + else { + $retval=0; + &B_log("ERROR","Couldn't replace line(s) in $filename because open failed.\n"); + } + + return $retval; +} + +########################################################################### +# &B_replace_lines ($filename,$patterns_and_substitutes) modifies $filename, +# replacing the line matching the nth $pattern specified in $patterns_and_substitutes->[n]->[0] +# with the corresponding substitutes in $patterns_and_substitutes->[n]->-[1] +# +# It returns the number of lines it replaced (or would have replaced, if +# LOGONLY mode wasn't on...) +# +# B_replace_lines uses B_open_plus and B_close_plus, so that the file +# modified is backed up... +# +# Here an example of where you might use this: +# +# You'd like to replace /etc/opt/ssh/sshd_config file +# (^#|^)Protocol\s+(.*)\s*$ ==> Protocol 2 +# (^#|^)X11Forwarding\s+(.*)\s*$ ==> X11Forwarding yes +# (^#|^)IgnoreRhosts\s+(.*)\s*$ ==> gnoreRhosts yes +# (^#|^)RhostsAuthentication\s+(.*)\s*$ ==> RhostsAuthentication no +# (^#|^)RhostsRSAAuthentication\s+(.*)\s*$ ==> RhostsRSAAuthentication no +# (^#|^)PermitRootLogin\s+(.*)\s*$ ==> PermitRootLogin no +# (^#|^)PermitEmptyPasswords\s+(.*)\s*$ ==> PermitEmptyPasswords no +# my $patterns_and_substitutes = [ +# [ '(^#|^)Protocol\s+(.*)\s*$' => 'Protocol 2'], +# ['(^#|^)X11Forwarding\s+(.*)\s*$' => 'X11Forwarding yes'], +# ['(^#|^)IgnoreRhosts\s+(.*)\s*$' => 'gnoreRhosts yes'], +# ['(^#|^)RhostsAuthentication\s+(.*)\s*$' => 'RhostsAuthentication no'], +# ['(^#|^)RhostsRSAAuthentication\s+(.*)\s*$' => 'RhostsRSAAuthentication no'], +# ['(^#|^)PermitRootLogin\s+(.*)\s*$' => 'PermitRootLogin no'], +# ['(^#|^)PermitEmptyPasswords\s+(.*)\s*$' => 'PermitEmptyPasswords no'] +#] +# B_replaces_lines($sshd_config,$patterns_and_substitutes); +########################################################################### + +sub B_replace_lines($$){ + my ($filename, $pairs) = @_; + my $retval = 0; + if ( &B_open_plus (*REPLACE_NEW,*REPLACE_OLD,$filename) ) { + while (my $line = <REPLACE_OLD>) { + my $switch; + my $switch_before = $line; + chomp($line); + foreach my $pair (@$pairs) { + $switch = 0; + + my $pattern = $pair->[0] ; + my $replace = $pair->[1]; + my $evalstr = '$line' . "=~ s/$pattern/$replace/"; + eval $evalstr; + if ($@) { + &B_log("ERROR", "eval $evalstr failed.\n"); + } + #if ( $line =~ s/$pair->[0]/$pair->[1]/) { + # $switch = 1; + # last; + #} + } + &B_print(*REPLACE_NEW,"$line\n"); + if ($switch) { + $retval++; + B_log("ACTION","File modification in $filename -- replaced line\n" . + "$switch_before\n" . + "with:\n" . + "$line\n"); + } + } + &B_close_plus (*REPLACE_NEW,*REPLACE_OLD,$filename); + return 1; + } + else { + $retval=0; + &B_log("ERROR","Couldn't replace line(s) in $filename because open failed.\n"); + } +} + +################################################################################################ +# &B_replace_pattern ($filename,$pattern,$pattern_to_remove,$text_to_switch_in) +# modifies $filename, acting on only lines that match $pattern, replacing a +# string that matches $pattern_to_remove with $text_to_switch_in. +# +# Ex: +# B_replace_pattern('/etc/httpd.conf','^\s*Options.*\bIncludes\b','Includes','IncludesNoExec') +# +# replaces all "Includes" with "IncludesNoExec" on Apache Options lines. +# +# It returns the number of lines it altered (or would have replaced, if +# LOGONLY mode wasn't on...) +# +# B_replace_pattern uses B_open_plus and B_close_plus, so that the file +# modified is backed up... +# +################################################################################################# + +sub B_replace_pattern($$$$) { + + my ($filename,$pattern,$pattern_to_remove,$text_to_switch_in) = @_; + my $retval=0; + + if ( &B_open_plus (*REPLACE_NEW,*REPLACE_OLD,$filename) ) { + while (my $line=<REPLACE_OLD>) { + unless ($line =~ $pattern) { + &B_print(*REPLACE_NEW,$line); + } + else { + my $orig_line =$line; + $line =~ s/$pattern_to_remove/$text_to_switch_in/; + + &B_print(*REPLACE_NEW,$line); + + $retval++; + &B_log("ACTION","File modification in $filename -- replaced line\n" . + "$orig_line\n" . + "via pattern with:\n" . + "$line\n\n"); + } + } + &B_close_plus (*REPLACE_NEW,*REPLACE_OLD,$filename); + } + else { + $retval=0; + &B_log("ERROR","Couldn't pattern-replace line(s) in $filename because open failed.\n"); + } + + return $retval; +} + + +########################################################################### +# &B_match_line($file,$pattern); +# +# This subroutine will return a 1 if the pattern specified can be matched +# against the file specified. It will return a 0 otherwise. +# +# return values: +# 0: pattern not in file or the file is not readable +# 1: pattern is in file +########################################################################### +sub B_match_line($$) { + # file to be checked and pattern to check for. + my ($file,$pattern) = @_; + # if the file is readable then + if(-r $file) { + # if the file can be opened then + if(open FILE,"<$file") { + # look at each line in the file + while (my $line = <FILE>) { + # if a line matches the pattern provided then + if($line =~ $pattern) { + # return the pattern was found + B_log('DEBUG','Pattern: ' . $pattern . ' matched in file: ' . + $file . "\n"); + return 1; + } + } + } + # if the file cann't be opened then + else { + # send a note to that affect to the errorlog + &B_log("ERROR","Unable to open file for read.\n$file\n$!\n"); + } + } + B_log('DEBUG','Pattern: ' . $pattern . ' not matched in file: ' . + $file . "\n"); + # the provided pattern was not matched against a line in the file + return 0; +} + +########################################################################### +# &B_match_line_only($file,$pattern); +# +# This subroutine checks if the specified pattern can be matched and if +# it's the only content in the file. The only content means it's only but +# may have several copies in the file. +# +# return values: +# 0: pattern not in file or pattern is not the only content +# or the file is not readable +# 1: pattern is in file and it's the only content +############################################################################ +sub B_match_line_only($$) { + my ($file,$pattern) = @_; + + # if matched, set to 1 later + my $retval = 0; + + # if the file is readable then + if(-r $file) { + # if the file can be opened then + if(&B_open(*FILED, $file)) { + # pattern should be matched at least once + # pattern can not be mismatched + while (my $line = <FILED>) { + if ($line =~ $pattern) { + $retval = 1; + } + else { + &B_close(*FILED); + return 0; + } + } + } + &B_close(*FILED); + } + + return $retval; +} + +########################################################################### +# &B_return_matched_lines($file,$pattern); +# +# This subroutine returns lines in a file matching a given regular +# expression, when called in the default list mode. When called in scalar +# mode, returns the number of elements found. +########################################################################### +sub B_return_matched_lines($$) +{ + my ($filename,$pattern) = @_; + my @lines = (); + + open(READFILE, $filename); + while (<READFILE>) { + chomp; + next unless /$pattern/; + push(@lines, $_); + } + if (wantarray) + { + return @lines; + } + else + { + return scalar (@lines); + } +} + +########################################################################### +# &B_match_chunk($file,$pattern); +# +# This subroutine will return a 1 if the pattern specified can be matched +# against the file specified on a line-agnostic form. This allows for +# patterns which by necessity must match against a multi-line pattern. +# This is the natural analogue to B_replace_chunk, which was created to +# provide multi-line capability not provided by B_replace_line. +# +# return values: +# 0: pattern not in file or the file is not readable +# 1: pattern is in file +########################################################################### + +sub B_match_chunk($$) { + + my ($file,$pattern) = @_; + my @lines; + my $big_long_line; + my $retval=1; + + open CHUNK_FILE,$file; + + # Read all lines into one scalar. + @lines = <CHUNK_FILE>; + close CHUNK_FILE; + + foreach my $line ( @lines ) { + $big_long_line .= $line; + } + + # Substitution routines get weird unless last line is terminated with \n + chomp $big_long_line; + $big_long_line .= "\n"; + + # Exit if we don't find a match + unless ($big_long_line =~ $pattern) { + $retval = 0; + } + + return $retval; +} + +########################################################################### +# &B_hash_comment_line ($filename,$pattern) modifies $filename, replacing +# any lines matching $pattern with a "hash-commented" version, like this: +# +# +# finger stream tcp nowait nobody /usr/sbin/tcpd in.fingerd +# becomes: +# #finger stream tcp nowait nobody /usr/sbin/tcpd in.fingerd +# +# Also: +# tftp dgram udp wait root /usr/lbin/tftpd tftpd\ +# /opt/ignite\ +# /var/opt/ignite +# becomes: +# #tftp dgram udp wait root /usr/lbin/tftpd tftpd\ +# # /opt/ignite\ +# # /var/opt/ignite +# +# +# B_hash_comment_line uses B_open_plus and B_close_plus, so that the file +# modified is backed up... +# +########################################################################### + +sub B_hash_comment_line($$) { + + my ($filename,$pattern) = @_; + my $retval=1; + + if ( &B_open_plus (*HASH_NEW,*HASH_OLD,$filename) ) { + my $line; + while ($line=<HASH_OLD>) { + unless ( ($line =~ $pattern) and ($line !~ /^\s*\#/) ) { + &B_print(*HASH_NEW,$line); + } + else { + &B_print(*HASH_NEW,"#$line"); + &B_log("ACTION","File modification in $filename -- hash commented line\n" . + "$line\n" . + "like this:\n" . + "#$line\n\n"); + # while the line has a trailing \ then we should also comment out the line below + while($line =~ m/\\\n$/) { + if($line=<HASH_OLD>) { + &B_print(*HASH_NEW,"#$line"); + &B_log("ACTION","File modification in $filename -- hash commented line\n" . + "$line\n" . + "like this:\n" . + "#$line\n\n"); + } + else { + $line = ""; + } + } + + } + } + &B_close_plus (*HASH_NEW,*HASH_OLD,$filename); + } + else { + $retval=0; + &B_log("ERROR","Couldn't hash-comment line(s) in $filename because open failed.\n"); + } + + return $retval; +} + + +########################################################################### +# &B_hash_uncomment_line ($filename,$pattern) modifies $filename, +# removing any commenting from lines that match $pattern. +# +# #finger stream tcp nowait nobody /usr/sbin/tcpd in.fingerd +# becomes: +# finger stream tcp nowait nobody /usr/sbin/tcpd in.fingerd +# +# +# B_hash_uncomment_line uses B_open_plus and B_close_plus, so that the file +# modified is backed up... +# +########################################################################### + +sub B_hash_uncomment_line($$) { + + my ($filename,$pattern) = @_; + my $retval=1; + + if ( &B_open_plus (*HASH_NEW,*HASH_OLD,$filename) ) { + my $line; + while ($line=<HASH_OLD>) { + unless ( ($line =~ $pattern) and ($line =~ /^\s*\#/) ) { + &B_print(*HASH_NEW,$line); + } + else { + $line =~ /^\s*\#+(.*)$/; + $line = "$1\n"; + + &B_print(*HASH_NEW,"$line"); + &B_log("ACTION","File modification in $filename -- hash uncommented line\n"); + &B_log("ACTION",$line); + # while the line has a trailing \ then we should also uncomment out the line below + while($line =~ m/\\\n$/) { + if($line=<HASH_OLD>) { + $line =~ /^\s*\#+(.*)$/; + $line = "$1\n"; + &B_print(*HASH_NEW,"$line"); + &B_log("ACTION","File modification in $filename -- hash uncommented line\n"); + &B_log("ACTION","#$line"); + &B_log("ACTION","like this:\n"); + &B_log("ACTION","$line"); + } + else { + $line = ""; + } + } + } + } + &B_close_plus (*HASH_NEW,*HASH_OLD,$filename); + } + else { + $retval=0; + &B_log("ERROR","Couldn't hash-uncomment line(s) in $filename because open failed.\n"); + } + + return $retval; +} + + + +########################################################################### +# &B_delete_line ($filename,$pattern) modifies $filename, deleting any +# lines matching $pattern. It uses B_replace_line to do this. +# +# B_replace_line uses B_open_plus and B_close_plus, so that the file +# modified is backed up... +# +# Here an example of where you might use this: +# +# You'd like to remove any timeout= lines in /etc/lilo.conf, so that your +# delay=1 modification will work. + +# +########################################################################### + + +sub B_delete_line($$) { + + my ($filename,$pattern)=@_; + my $retval=&B_replace_line($filename,$pattern,""); + + return $retval; +} + + +########################################################################### +# &B_chunk_replace ($file,$pattern,$replacement) reads $file replacing the +# first occurrence of $pattern with $replacement. +# +########################################################################### + +sub B_chunk_replace($$$) { + + my ($file,$pattern,$replacement) = @_; + + my @lines; + my $big_long_line; + my $retval=1; + + &B_open (*OLDFILE,$file); + + # Read all lines into one scalar. + @lines = <OLDFILE>; + &B_close (*OLDFILE); + foreach my $line ( @lines ) { + $big_long_line .= $line; + } + + # Substitution routines get weird unless last line is terminated with \n + chomp $big_long_line; + $big_long_line .= "\n"; + + # Exit if we don't find a match + unless ($big_long_line =~ $pattern) { + return 0; + } + + $big_long_line =~ s/$pattern/$replacement/s; + + $retval=&B_open_plus (*NEWFILE,*OLDFILE,$file); + if ($retval) { + &B_print (*NEWFILE,$big_long_line); + &B_close_plus (*NEWFILE,*OLDFILE,$file); + } + + return $retval; +} + +########################################################################### +# &B_print ($handle,@list) prints the items of @list to the file handle +# $handle. It logs the action and respects the $GLOBAL_LOGONLY variable. +# +########################################################################### + +sub B_print { + my $handle=shift @_; + + my $result=1; + + unless ($GLOBAL_LOGONLY) { + $result=print $handle @_; + } + + ($handle) = "$handle" =~ /[^:]+::[^:]+::([^:]+)/; + + $result; +} + + +########################################################################## +# &B_getValueFromFile($regex,$file); +# Takes a regex with a single group "()" and returns the unique value +# on any non-commented lines +# This (and B_return_matched_lines are only used in this file, though are +# probably more generally useful. For now, leaving these here serve the following +#functions: +# a) still gets exported/associated as part of the Test_API package, and +# is still availble for a couple operations that can't be deferred to the +# main test loop, as they save values so that individual tests don't have to +# recreate (copy / paste) the logic to get them. +# +# It also avoids the circular "use" if we incldued "use Test API" at the top +# of this file (Test API "uses" this file. +# Returns the uncommented, unique values of a param=value pair. +# +# Return values: +# 'Not Defined' if the value is not present or not uniquely defined. +# $value if the value is present and unique +# +########################################################################### +sub B_getValueFromFile ($$){ + my $inputRegex=$_[0]; + my $file=$_[1]; + my ($lastvalue,$value)=''; + + my @lines=&B_return_matched_lines($file, $inputRegex); + + return &B_getValueFromString($inputRegex,join('/n',@lines)); +} + +########################################################################## +# &B_getValueFromString($param,$string); +# Takes a regex with a single group "()" and returns the unique value +# on any non-commented lines +# This (and B_return_matched_lines are only used in this file, though are +# probably more generally useful. For now, leaving these here serve the following +#functions: +# a) still gets exported/associated as part of the Test_API package, and +# is still availble for a couple operations that can't be deferred to the +# main test loop, as they save values so that individual tests don't have to +# recreate (copy / paste) the logic to get them. +# +# It also avoids the circular "use" if we incldued "use Test API" at the top +# of this file (Test API "uses" this file. +# Returns the uncommented, unique values of a param=value pair. +# +# Return values: +# 'Not Unique' if the value is not uniquely defined. +# undef if the value isn't defined at all +# $value if the value is present and unique +# +########################################################################### +sub B_getValueFromString ($$){ + my $inputRegex=$_[0]; + my $inputString=$_[1]; + my $lastValue=''; + my $value=''; + + my @lines=split(/\n/,$inputString); + + &B_log("DEBUG","B_getvaluefromstring called with regex: $inputRegex and input: " . + $inputString); + foreach my $line (grep(/$inputRegex/,@lines)) { + $line =~ /$inputRegex/; + $value=$1; + if (($lastValue eq '') and ($value ne '')) { + $lastValue = $value; + } elsif (($lastValue ne $value) and ($value ne '')) { + B_log("DEBUG","getvaluefromstring returned Not Unique"); + return 'Not Unique'; + } + } + if ((not(defined($value))) or ($value eq '')) { + &B_log("DEBUG","Could not find regex match in string"); + return undef; + } else { + &B_log("DEBUG","B_getValueFromString Found: $value ; using: $inputRegex"); + return $value; + } +} + +############################################################### +# This function adds something to the To Do List. +# Arguments: +# 1) The string you want to add to the To Do List. +# 2) Optional: Question whose TODOFlag should be set to indicate +# A pending manual action in subsequent reports. Only skip this +# If there's no security-audit relevant action you need the user to +# accomplish +# Ex: +# &B_TODO("------\nInstalling IPFilter\n----\nGo get Ipfilter","IPFilter.install_ipfilter"); +# +# +# Returns: +# 0 - If error condition +# True, if sucess, specifically: +# "appended" if the append operation was successful +# "exists" if no change was made since the entry was already present +############################################################### +sub B_TODO ($;$) { + my $text = $_[0]; + my $FlaggedQuestion = $_[1]; + my $multilineString = ""; + + # trim off any leading and trailing new lines, regexes separated for "clarity" + $text =~ s/^\n+(.*)/$1/; + $text =~ s/(.*)\n+$/$1/; + + if ( ! -e &getGlobal('BFILE',"TODO") ) { + # Make the TODO list file for HP-UX Distro + &B_create_file(&getGlobal('BFILE', "TODO")); + &B_append_line(&getGlobal('BFILE', "TODO"),'a$b', + "Please take the steps below to make your system more secure,\n". + "then delete the item from this file and record what you did along\n". + "with the date and time in your system administration log. You\n". + "will need that information in case you ever need to revert your\n". + "changes.\n\n"); + } + + + if (open(TODO,"<" . &getGlobal('BFILE', "TODO"))) { + while (my $line = <TODO>) { + # getting rid of all meta characters. + $line =~ s/(\\|\||\(|\)|\[|\]|\{|\}|\^|\$|\*|\+|\?|\.)//g; + $multilineString .= $line; + } + chomp $multilineString; + $multilineString .= "\n"; + + close(TODO); + } + else { + &B_log("ERROR","Unable to read TODO.txt file.\n" . + "The following text could not be appended to the TODO list:\n" . + $text . + "End of TODO text\n"); + return 0; #False + } + + my $textPattern = $text; + + # getting rid of all meta characters. + $textPattern =~ s/(\\|\||\(|\)|\[|\]|\{|\}|\^|\$|\*|\+|\?|\.)//g; + + if( $multilineString !~ "$textPattern") { + my $datestamp = "{" . localtime() . "}"; + unless ( &B_append_line(&getGlobal('BFILE', "TODO"), "", $datestamp . "\n" . $text . "\n\n\n") ) { + &B_log("ERROR","TODO Failed for text: " . $text ); + } + #Note that we only set the flag on the *initial* entry in the TODO File + #Not on subsequent detection. This is to avoid the case where Bastille + #complains on a subsequent Bastille run of an already-performed manual + #action that the user neglected to delete from the TODO file. + # It does, however lead to a report of "nonsecure" when the user + #asked for the TODO item, performed it, Bastille detected that and cleared the + # Item, and then the user unperformed the action. I think this is proper behavior. + # rwf 06/06 + + if (defined($FlaggedQuestion)) { + &B_TODOFlags("set",$FlaggedQuestion); + } + return "appended"; #evals to true, and also notes what happened + } else { + return "exists"; #evals to true, and also + } + +} + + +##################################################################### +# &B_TODOFlags() +# +# This is the interface to the TODO flags. Test functions set these when they +# require a TODO item to be completed to get to a "secure" state. +# The prune/reporting function checks these to ensure no flags are set before +# reporting an item "secure" +# "Methods" are load | save | isSet <Question> | set <Question> | unset <Question> +# +###################################################################### + +sub B_TODOFlags($;$) { + my $action = $_[0]; + my $module = $_[1]; + + use File::Spec; + + my $todo_flag = &getGlobal("BFILE","TODOFlag"); + + &B_log("DEBUG","B_TODOFlags action: $action , module: $module"); + + if ($action eq "load") { + if (-e $todo_flag ) { + &B_open(*TODO_FLAGS, $todo_flag); + my @lines = <TODO_FLAGS>; + foreach my $line (@lines) { + chomp($line); + $GLOBAL_CONFIG{"$line"}{"TODOFlag"}="yes"; + } + return (&B_close(*TODO_FLAGS)); #return success of final close + } else { + return 1; #No-op is okay + } + } elsif ($action eq "save") { + # Make sure the file exists, else create + #Note we use open_plus and and create file, so if Bastille is + #reverted, all the flags will self-clear (file deleted) + my $flagNumber = 0; + my $flagData = ''; + foreach my $key (keys %GLOBAL_CONFIG) { + if ($GLOBAL_CONFIG{$key}{"TODOFlag"} eq "yes") { + ++$flagNumber; + $flagData .= "$key\n"; + } + } + if (not( -e $todo_flag)) { + &B_log("DEBUG","Initializing TODO Flag file: $todo_flag"); + &B_create_file($todo_flag); # Make sure it exists + } + &B_blank_file($todo_flag, + "This will not appear in the file; ensures blanking"); + return &B_append_line($todo_flag, "", "$flagData"); #return success of save + } elsif (($action eq "isSet") and ($module ne "")) { + if ($GLOBAL_CONFIG{"$module"}{"TODOFlag"} eq "yes") { + return 1; #TRUE + } else { + return 0; #FALSE + } + } elsif (($action eq "set") and ($module ne "")) { + $GLOBAL_CONFIG{"$module"}{"TODOFlag"} = "yes"; + } elsif (($action eq "clear") and ($module ne "")) { + $GLOBAL_CONFIG{"$module"}{"TODOFlag"} = ""; + } else { + &B_log("ERROR","TODO_Flag Called with invalid parameters: $action , $module". + "audit report may be incorrect."); + return 0; #FALSE + } +} + +1; + + diff --git a/meta-security/recipes-security/bastille/files/HPSpecific.pm b/meta-security/recipes-security/bastille/files/HPSpecific.pm new file mode 100644 index 000000000..7e7d709fb --- /dev/null +++ b/meta-security/recipes-security/bastille/files/HPSpecific.pm @@ -0,0 +1,1983 @@ +package Bastille::API::HPSpecific; + +use strict; +use Bastille::API; +use Bastille::API::FileContent; + +require Exporter; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw( +getIPFLocation +getGlobalSwlist +B_check_system +B_swmodify +B_load_ipf_rules +B_Schedule +B_ch_rc +B_set_value +B_chperm +B_install_jail +B_list_processes +B_list_full_processes +B_deactivate_inetd_service +B_get_rc +B_set_rc +B_chrootHPapache +isSystemTrusted +isTrustedMigrationAvailable +checkServiceOnHPUX +B_get_path +convertToTrusted +isOKtoConvert +convertToShadow +getSupportedSettings +B_get_sec_value +secureIfNoNameService +isUsingRemoteNameService +remoteServiceCheck +remoteNISPlusServiceCheck +B_create_nsswitch_file +B_combine_service_results + +%priorBastilleNDD +%newNDD +); +our @EXPORT = @EXPORT_OK; + + + +# "Constants" for use both in testing and in lock-down +our %priorBastilleNDD = ( + "ip_forward_directed_broadcasts" =>["ip", "0"], + "ip_forward_src_routed" =>["ip", "0"], + "ip_forwarding" =>["ip", "0"], + "ip_ire_gw_probe" =>["ip", "0"], + "ip_pmtu_strategy" =>["ip", "1"], + "ip_respond_to_echo_broadcast" =>["ip", "0"], + "ip_send_redirects" =>["ip", "0"], + "ip_send_source_quench" =>["ip", "0"], + "tcp_syn_rcvd_max" =>["tcp","1000"], + "tcp_conn_request_max" =>["tcp","4096"] ); + +our %newNDD = ( + "ip_forward_directed_broadcasts" =>["ip", "0"], + "ip_forward_src_routed" =>["ip", "0"], + "ip_forwarding" =>["ip", "0"], + "ip_ire_gw_probe" =>["ip", "0"], + "ip_pmtu_strategy" =>["ip", "1"], + "ip_respond_to_echo_broadcast" =>["ip", "0"], + "ip_send_redirects" =>["ip", "0"], + "ip_send_source_quench" =>["ip", "0"], + "tcp_syn_rcvd_max" =>["tcp","4096"], + "tcp_conn_request_max" =>["tcp","4096"], + "arp_cleanup_interval" =>["arp","60000"], + "ip_respond_to_timestamp" =>["ip", "0"], + "ip_respond_to_timestamp_broadcast" => ["ip","0"] ); + + +#################################################################### +# +# This module makes up the HP-UX specific API routines. +# +#################################################################### +# +# Subroutine Listing: +# &HP_ConfigureForDistro: adds all used file names to global +# hashes and generates a global IPD +# hash for SD modification lookup. +# +# &getGlobalSwlist($): Takes a fully qualified file name +# and returns product:filset info +# for that file. returns undef if +# the file is not present in the IPD +# +# &B_check_system: Runs a series of system queries to +# determine if Bastille can be safely +# ran on the current system. +# +# &B_swmodify($): Takes a file name and runs the +# swmodify command on it so that the +# IPD is updated after changes +# +# &B_System($$): Takes a system command and the system +# command that should be used to revert +# whatever was done. Returns 1 on +# success and 0 on failure +# +# &B_Backtick($) Takes a command to run and returns its stdout +# to be used in place of the prior prevelent use +# of un-error-handled backticks +# +# &B_load_ipf_rules($): Loads a set of ipfrules into ipf, storing +# current rules for later reversion. +# +# &B_Schedule($$): Takes a pattern and a crontab line. +# Adds or replaces the crontab line to +# the crontab file, depending on if a +# line matches the pattern +# +# &B_ch_rc($$): Takes a the rc.config.d flag name and +# new value as well as the init script +# location. This will stop a services +# and set the service so that it will +# not be restarted. +# +# &B_set_value($$$): Takes a param, value, and a filename +# and sets the given value in the file. +# Uses ch_rc, but could be rewritten using +# Bastille API calls to make it work on Linux +# +# &B_TODO($): Appends the give string to the TODO.txt +# file. +# +# &B_chperm($$$$): Takes new perm owner and group of given +# file. TO BE DEPRECATED!!! +# +# &B_install_jail($$): Takes the jail name and the jail config +# script location for a give jail... +# These scripts can be found in the main +# directory e.g. jail.bind.hpux +# +##################################################################### + +############################################################################## +# +# HP-UX Bastille directory structure +# +############################################################################## +# +# /opt/sec_mgmt/bastille/bin/ -- location of Bastille binaries +# /opt/sec_mgmt/bastille/lib/ -- location of Bastille modules +# /opt/sec_mgmt/bastille/doc/ -- location of Bastille doc files +# +# /etc/opt/sec_mgmt/bastille/ -- location of Bastille config files +# +# /var/opt/sec_mgmt/bastille/log -- location of Bastille log files +# /var/opt/sec_mgmt/bastille/revert -- directory holding all Bastille- +# created revert scripts +# /var/opt/sec_mgmt/bastille/revert/backup -- directory holding the original +# files that Bastille modifies, +# with permissions intact +# +############################################################################## + +sub getIPFLocation () { # Temporary until we get defined search space support + my $ipf=&getGlobal('BIN','ipf_new'); + my $ipfstat=&getGlobal('BIN','ipfstat_new'); + if (not(-e $ipf)) { # Detect if the binaries moved + $ipf = &getGlobal('BIN','ipf'); + $ipfstat=&getGlobal('BIN','ipfstat'); + } + return ($ipf, $ipfstat); +} + +############################################## +# Given a combination of service results, provided +# in an array, this function combines the result into +# a reasonable aggregate result +############################################## + +sub B_combine_service_results(@){ + my @results = @_; + + #TODO: Consider greater sophistication wrt inconsistent, or not installed. + + foreach my $result (@results) { + if (not(($result == SECURE_CAN_CHANGE) or + ($result == SECURE_CANT_CHANGE) or + ($result == NOT_INSTALLED()))) { + return NOTSECURE_CAN_CHANGE(); + } + } + return SECURE_CANT_CHANGE(); +} + +#################################################################### +# &getGlobalSwlist ($file); +# This function returns the product and fileset information for +# a given file or directory if it exists in the IPD otherwise +# it returns undefined "undef" +# +# uses $GLOBAL_SWLIST{"$FILE"} +#################################################################### +sub getGlobalSwlist($){ + no strict; + my $file = $_[0]; + + + if(! %GLOBAL_SWLIST) { + # Generating swlist database for swmodify changes that will be required + # The database will be a hash of fully qualified file names that reference + # the files product name and fileset. These values are required to use + # swmodify... + + # Files tagged 'is_volatile' in the IPD are not entered in the swlist database + # in order to avoid invoking swmodify if the file is changed later. Attempting to + # swmodify 'volatile' files is both unneccessary and complicated since swverify will + # not evaluate volatile files anyway, and adding another value to the swlist database + # would require complex code changes. + + # temp variable to keep swlist command /usr/sbin/swlist + my $swlist = &getGlobal('BIN',"swlist"); + + # listing of each directory and file that was installed by SD on the target machine + my @fileList = `$swlist -a is_volatile -l file`; + + # listing of each patch and the patches that supersede each. + # hash which is indexed by patch.fileset on the system + my %patchSuperseded; + + my @patchList = `${swlist} -l fileset -a superseded_by *.*,c=patch 2>&1`; + # check to see if any patches are present on the system + if(($? >> 8) == 0) { + + # determining patch suppression for swmodify. + foreach my $patchState (@patchList) { + # removing empty lines and commented lines. + if($patchState !~ /^\s*\#/ && $patchState !~ /^\s*$/) { + + # removing leading white space + $patchState =~ s/^\s+//; + my @patches = split /\s+/, $patchState; + if($#patches == 0){ + # patch is not superseded + $patchSuperseded{$patches[0]} = 0; + } + else { + # patch is superseded + $patchSuperseded{$patches[0]} = 1; + } + } + } + } + else { + &B_log("DEBUG","No patches found on the system.\n"); + } + + if($#fileList >= 0){ + # foreach line of swlist output + foreach my $fileEntry ( @fileList ){ + #filter out commented portions + if( $fileEntry !~ /^\s*\#/ ){ + chomp $fileEntry; + # split the output into three fields: product.fileset, filename, flag_isvolatile + my( $productInfo, $file, $is_volatile ) = $fileEntry =~ /^\s*(\S+): (\S+)\t(\S+)/ ; + # do not register volatile files + next if ($is_volatile =~ /true/); # skip to next file entry + $productInfo =~ s/\s+//; + $file =~ s/\s+//; + # if the product is a patch + if($productInfo =~ /PH(CO|KL|NE|SS)/){ + # if the patch is not superseded by another patch + if($patchSuperseded{$productInfo} == 0){ + # add the patch to the list of owner for this file + push @{$GLOBAL_SWLIST{"$file"}}, $productInfo; + } + } + # not a patch. + else { + # add the product to the list of owners for this file + push @{$GLOBAL_SWLIST{"$file"}}, $productInfo; + } + + } + } + } + else{ + # defining GLOBAL_SWLIST in error state. + $GLOBAL_SWLIST{"ERROR"} = "ERROR"; + &B_log("ERROR","Could not execute swlist. Swmodifys will not be attempted"); + } + } + + if(exists $GLOBAL_SWLIST{"$file"}){ + return $GLOBAL_SWLIST{"$file"}; + } + else { + return undef; + } +} + +################################################################### +# &B_check_system; +# This subroutine is called to validate that bastille may be +# safely run on the current system. It will check to insure +# that there is enough file system space, mounts are rw, nfs +# mounts are not mounted noroot, and swinstall, swremove and +# swmodify are not running +# +# uses ErrorLog +# +################################################################## +sub B_check_system { + # exitFlag is one if a conflict with the successful execution + # of bastille is found. + my $exitFlag = 0; + + my $ignoreCheck = &getGlobal("BDIR","config") . "/.no_system_check"; + if( -e $ignoreCheck ) { + return $exitFlag; + } + + # first check for swinstall, swmodify, or swremove processes + my $ps = &getGlobal('BIN',"ps") . " -el"; + my @processTable = `$ps`; + foreach my $process (@processTable) { + if($process =~ /swinstall/ ) { + &B_log("ERROR","Bastille cannot run while a swinstall is in progress.\n" . + "Complete the swinstall operation and then run Bastille.\n\n"); + $exitFlag = 1; + } + + if($process =~ /swremove/ ) { + &B_log("ERROR","Bastille cannot run while a swremove is in progress.\n" . + "Complete the swremove operation and then run Bastille.\n\n"); + $exitFlag = 1; + } + + if($process =~ /swmodify/ ) { + &B_log("ERROR","Bastille cannot run while a swmodify is in progress.\n" . + "Complete the swmodify operation and then run Bastille.\n\n"); + $exitFlag = 1; + } + + } + + # check for root read only mounts for /var /etc /stand / + # Bastille is required to make changes to these file systems. + my $mount = &getGlobal('BIN',"mount"); + my $rm = &getGlobal('BIN',"rm"); + my $touch = &getGlobal('BIN',"touch"); + + my @mnttab = `$mount`; + + if(($? >> 8) != 0) { + &B_log("WARNING","Unable to use $mount to determine if needed partitions\n" . + "are root writable, based on disk mount options.\n" . + "Bastille will continue but note that disk\n" . + "mount checks were skipped.\n\n"); + } + else { + foreach my $record (@mnttab) { + my @fields = split /\s+/, $record; + if ((defined $fields[0]) && (defined $fields[2]) && (defined $fields[3])) { + my $mountPoint = $fields[0]; + my $mountType = $fields[2]; + my $mountOptions = $fields[3]; + + # checks for /stand and /var/* removed + if($mountPoint =~ /^\/$|^\/etc|^\/var$/) { + + if($mountOptions =~ /^ro,|,ro,|,ro$/) { + &B_log("ERROR","$mountPoint is mounted read-only. Bastille needs to make\n" . + "modifications to this file system. Please remount\n" . + "$mountPoint read-write and then run Bastille again.\n\n"); + $exitFlag = 1; + } + # looking for an nfs mounted file system + if($mountType =~/.+:\//){ + my $fileExisted=0; + if(-e "$mountPoint/.bastille") { + $fileExisted=1; + } + + `$touch $mountPoint/.bastille 1>/dev/null 2>&1`; + + if( (! -e "$mountPoint/.bastille") || (($? >> 8) != 0) ) { + &B_log("ERROR","$mountPoint is an nfs mounted file system that does\n" . + "not allow root to write to. Bastille needs to make\n" . + "modifications to this file system. Please remount\n" . + "$mountPoint giving root access and then run Bastille\n" . + "again.\n\n"); + + $exitFlag = 1; + } + # if the file did not exist befor the touch then remove the generated file + if(! $fileExisted) { + `$rm -f $mountPoint/.bastille 1>/dev/null 2>&1`; + } + } + } + } + else { + &B_log("WARNING","Unable to use $mount to determine if needed partitions\n" . + "are root writable, based on disk mount options.\n" . + "Bastille will continue but note that disk\n" . + "mount checks were skipped.\n\n"); + } + } + + } + + # checks for enough disk space in directories that Bastille writes to. + my $bdf = &getGlobal('BIN',"bdf"); + #directories that Bastille writes to => required space in kilobytes. + my %bastilleDirs = ( "/etc/opt/sec_mgmt/bastille" => "4", "/var/opt/sec_mgmt/bastille"=> "1000"); + for my $directory (sort keys %bastilleDirs) { + my @diskUsage = `$bdf $directory`; + + if(($? >> 8) != 0) { + &B_log("WARNING","Unable to use $bdf to determine disk usage for\n" . + "$directory\n" . + "Bastille will continue but note that disk\n" . + "usage checks were skipped.\n\n"); + + } + else { + # removing bdf header line from usage information. + shift @diskUsage; + my $usageString= ""; + + foreach my $usageRecord (@diskUsage) { + chomp $usageRecord; + $usageString .= $usageRecord; + } + + $usageString =~ s/^\s+//; + + my @fields = split /\s+/, $usageString; + if($#fields != 5) { + &B_log("WARNING","Unable to use $bdf to determine disk usage for\n" . + "$directory\n" . + "Bastille will continue but note that disk\n" . + "usage checks were skipped.\n\n"); + } + else { + + my $mountPoint = $fields[5]; + my $diskAvail = $fields[3]; + + if($diskAvail <= $bastilleDirs{"$directory"}) { + &B_log("ERROR","$mountPoint does not contain enough available space\n" . + "for Bastille to run properly. $directory needs\n" . + "at least $bastilleDirs{$directory} kilobytes of space.\n" . + "Please clear at least that amount of space from\n" . + "$mountPoint and run Bastille again.\n" . + "Current Free Space available = ${diskAvail} k\n\n"); + $exitFlag = 1; + } + } + } + } + + # check to make sure that we are in at least run level 2 before we attempt to run + my $who = &getGlobal('BIN', "who") . " -r"; + my $levelInfo = `$who`; + if(($? >> 8) != 0 ) { + &B_log("WARNING","Unable to use \"$who\" to determine system run.\n" . + "level Bastille will continue but note that the run\n" . + "level check was skipped.\n\n"); + } + else { + chomp $levelInfo; + my @runlevel = split /\s+/, $levelInfo; + if ((! defined $runlevel[3]) or ($runlevel[3] < 2)) { + &B_log("WARNING","Bastille requires a run-level of 2 or more to run properly.\n" . + "Please move your system to a higher run level and then\n" . + "run 'bastille -b'.\n\n"); + if(defined $runlevel[3]) { + &B_log("ERROR","Current run-level is '$runlevel[3]'.\n\n"); + $exitFlag=1; + } + else { + &B_log("WARNING","Unable to use \"$who\" to determine system run.\n" . + "level Bastille will continue but note that the run\n" . + "level check was skipped.\n\n"); + } + } + else { + &B_log("DEBUG","System run-level is $runlevel[3]\n"); + } + } + + if($exitFlag) { + exit(1); + } + +} + +################################################################### +# &B_swmodify($file); +# This subroutine is called after a file is modified. It will +# redefine the file in the IPD with it's new properties. If +# the file is not in the IPD it does nothing. +# +# uses B_System to make the swmodifications. +################################################################## +sub B_swmodify($){ + my $file = $_[0]; + if(defined &getGlobalSwlist($file)){ + my $swmodify = &getGlobal('BIN',"swmodify"); + my @productsInfo = @{&getGlobalSwlist($file)}; + # running swmodify on files that were altered by this function but + # were created and maintained by SD + foreach my $productInfo (@productsInfo) { + &B_System("$swmodify -x files='$file' $productInfo", + "$swmodify -x files='$file' $productInfo"); + } + } +} + +#################################################################### +# &B_load_ipf_rules($ipfruleset); +# This function enables an ipfruleset. It's a little more +# specific than most API functions, but necessary because +# ipf doesn't return correct exit codes (syntax error results +# in a 0 exit code) +# +# uses ActionLog and ErrorLog to log +# calls crontab directly (to list and to read in new jobs) +################################################################### +sub B_load_ipf_rules ($) { + my $ipfruleset=$_[0]; + + &B_log("DEBUG","# sub B_load_ipf_rules"); + + # TODO: grab ipf.conf dynamically from the rc.config.d files + my $ipfconf = &getGlobal('FILE','ipf.conf'); + + # file system changes - these are straightforward, and the API + # will take care of the revert + &B_create_file($ipfconf); + &B_blank_file($ipfconf, 'a$b'); + &B_append_line($ipfconf, 'a$b', $ipfruleset); + + # runtime changes + + # define binaries + my $grep = &getGlobal('BIN', 'grep'); + my ($ipf, $ipfstat) = &getIPFLocation; + # create backup rules + # This will exit with a non-zero exit code because of the grep + my @oldrules = `$ipfstat -io 2>&1 | $grep -v empty`; + + my @errors=`$ipf -I -Fa -f $ipfconf 2>&1`; + + if(($? >> 8) == 0) { + + &B_set_rc("IPF_START","1"); + &B_set_rc("IPF_CONF","$ipfconf"); + + # swap the rules in + &B_System("$ipf -s","$ipf -s"); + + # now create a "here" document with the previous version of + # the rules and put it into the revert-actions script + &B_revert_log("$ipf -I -Fa -f - <<EOF\n@{oldrules}EOF"); + + if (@errors) { + &B_log("ERROR","ipfilter produced the following errors when\n" . + " loading $ipfconf. You probably had an invalid\n" . + " rule in ". &getGlobal('FILE','customipfrules') ."\n". + "@errors\n"); + } + + } else { + &B_log("ERROR","Unable to run $ipf\n"); + } + +} + + + +#################################################################### +# &B_Schedule($pattern,$cronjob); +# This function schedules a cronjob. If $pattern exists in the +# crontab file, that job will be replaced. Otherwise, the job +# will be appended. +# +# uses ActionLog and ErrorLog to log +# calls crontab directly (to list and to read in new jobs) +################################################################### +sub B_Schedule ($$) { + my ($pattern,$cronjob)=@_; + $cronjob .= "\n"; + + &B_log("DEBUG","# sub B_Schedule"); + my $crontab = &getGlobal('BIN','crontab'); + + my @oldjobs = `$crontab -l 2>/dev/null`; + my @newjobs; + my $patternfound=0; + + foreach my $oldjob (@oldjobs) { + if (($oldjob =~ m/$pattern/ ) and (not($patternfound))) { + push @newjobs, $cronjob; + $patternfound=1; + &B_log("ACTION","changing existing cron job which matches $pattern with\n" . + "$cronjob"); + } elsif ($oldjob !~ m/$pattern/ ) { + &B_log("ACTION","keeping existing cron job $oldjob"); + push @newjobs, $oldjob; + } #implied: else if pattern matches, but we've + #already replaced one, then toss the others. + } + + unless ($patternfound) { + &B_log("ACTION","adding cron job\n$cronjob\n"); + push @newjobs, $cronjob; + } + + if(open(CRONTAB, "|$crontab - 2> /dev/null")) { + print CRONTAB @newjobs; + + # now create a "here" document with the previous version of + # the crontab file and put it into the revert-actions script + &B_revert_log("$crontab <<EOF\n" . "@oldjobs" . "EOF"); + close CRONTAB; + } + + # Now check to make sure it happened, since cron will exit happily + # (retval 0) with no changes if there are any syntax errors + my @editedjobs = `$crontab -l 2>/dev/null`; + + if (@editedjobs ne @newjobs) { + &B_log("ERROR","failed to add cron job:\n$cronjob\n" . + " You probably had an invalid crontab file to start with."); + } + +} + + +#This function turns off a service, given a service name defined in HP-UX.service + +sub B_ch_rc($) { + + my ($service_name)=@_; + + if (&GetDistro != "^HP-UX") { + &B_log("ERROR","Tried to call ch_rc $service_name on a non-HP-UX\n". + " system! Internal Bastille error."); + return undef; + } + my $configfile=""; + my $command = &getGlobal('BIN', 'ch_rc'); + + my $startup_script=&getGlobal('DIR','initd') . "/". $service_name; + my @rc_parameters= @{ &getGlobal('SERVICE',$service_name) }; + my @rcFiles=@{ &getGlobal('RCCONFIG',$service_name) }; + my $rcFile=''; + if (@rcFiles == 1){ + $rcFile=$rcFiles[0]; + } else { + &B_log("FATAL","Multiple RC Files not yet supported... internal error."); + } + + # if the service-related process is not run, and the control variable is stilll 1 + # there is a inconsistency. in this case we only need to change the control variable + my @psnames=@{ &getGlobal('PROCESS',$service_name)}; + my @processes; + foreach my $psname (@psnames) { + $psname .= '\b'; # avoid embedded match; anchor search pattern to trailing word boundry + my @procList = &isProcessRunning($psname); + if(@procList >= 0){ + splice @processes,$#processes+1,0,@procList; + } + } +#Actually set the rc variable + foreach my $rcVariable (@rc_parameters){ + my $orig_value = &B_get_rc($rcVariable); + if ($orig_value eq "" ) { #If variable not set, used the defined file + $configfile=&getGlobal("DIR","rc.config.d") . "/" . $rcFile; + if (not( -f $configfile )) { + &B_create_file($configfile); + } + } + &B_log("DEBUG","In B_ch_rc (no procs), setting $rcVariable to 0 in $configfile" . + ", with an original value of $orig_value with rcfile: $rcFile"); + if ( ! @processes) { # IF there are no processes we don't neet to perform a "stop" + &B_set_rc($rcVariable, "0", $configfile); + } else { + if ( $orig_value !~ "1" ) { #If param is not already 1, the "stop" script won't work + &B_set_rc($rcVariable, "1",$configfile); + } + &B_System ($startup_script . " stop", #stop service, then restart if the user runs bastille -r + $startup_script . " start"); + # set parameter, so that service will stay off after reboots + &B_set_rc($rcVariable, "0", $configfile); + } + } +} + + +# This routine sets a value in a given file +sub B_set_value($$$) { + my ($param, $value, $file)=@_; + + &B_log("DEBUG","B_set_value: $param, $value, $file"); + if (! -e $file ) { + &B_create_file("$file"); + } + + # If a value is already set to something other than $value then reset it. + #Note that though this tests for "$value ="the whole line gets replaced, so + #any pre-existing values are also replaced. + &B_replace_line($file,"^$param\\s*=\\s*","$param=$value\n"); + # If the value is not already set to something then set it. + &B_append_line($file,"^$param\\s*=\\s*$value","$param=$value\n"); + +} + + +################################################################################## +# &B_chperm($owner,$group,$mode,$filename(s)) +# This function changes ownership and mode of a list of files. Takes four +# arguments first the owner next the group and third the new mode in oct and +# last a list of files that the permissions changes should take affect on. +# +# uses: &swmodify and &B_revert_log +################################################################################## +sub B_chperm($$$$) { + my ($newown, $newgrp, $newmode, $file_expr) = @_; + my @files = glob($file_expr); + + my $return = 1; + + foreach my $file (@files){ + my @filestat = stat $file; + my $oldmode = (($filestat[2]/512) % 8) . + (($filestat[2]/64) % 8) . + (($filestat[2]/8) % 8) . + (($filestat[2]) % 8); + + if((chown $newown, $newgrp, $file) != 1 ){ + &B_log("ERROR","Could not change ownership of $file to $newown:$newgrp\n"); + $return = 0; + } + else{ + &B_log("ACTION","Changed ownership of $file to $newown:$newgrp\n"); + # swmodifying file if possible... + &B_swmodify($file); + &B_revert_log(&getGlobal('BIN',"chown") . " $filestat[4]:$filestat[5] $file\n"); + } + + my $newmode_formatted=sprintf "%5lo",$newmode; + + if((chmod $newmode, $file) != 1){ + &B_log("ERROR","Could not change mode of $file to $newmode_formatted\n"); + $return = 0; + } + else{ + &B_log("ACTION","Changed mode of $file to $newmode_formatted\n"); + &B_revert_log(&getGlobal('BIN',"chmod") . " $oldmode $file\n"); + } + + + } + return $return; +} + +############################################################################ +# &B_install_jail($jailname, $jailconfigfile); +# This function takes two arguments ( jail_name, jail_config ) +# It's purpose is to take read in config files that define a +# chroot jail and then generate it bases on that specification +############################################################################ +sub B_install_jail($$) { + + my $jailName = $_[0]; # Name of the jail e.g bind + my $jailConfig = $_[1]; # Name of the jails configuration file + # create the root directory of the jail if it does not exist + &B_create_dir( &getGlobal('BDIR','jail')); + &B_chperm(0,0,0555,&getGlobal('BDIR','jail')); + + # create the Jail dir if it does not exist + &B_create_dir( &getGlobal('BDIR','jail') . "/" . $jailName); + &B_chperm(0,0,0555,&getGlobal('BDIR','jail') . "/". $jailName); + + + my $jailPath = &getGlobal('BDIR','jail') . "/" . $jailName; + my @lines; # used to store no commented no empty config file lines + # open configuration file for desired jail and parse in commands + if(open(JAILCONFIG,"< $jailConfig")) { + while(my $line=<JAILCONFIG>){ + if($line !~ /^\s*\#|^\s*$/){ + chomp $line; + push(@lines,$line); + } + } + close JAILCONFIG; + } + else{ + &B_log("ERROR","Open Failed on filename: $jailConfig\n"); + return 0; + } + # read through commands and execute + foreach my $line (@lines){ + &B_log("ACTION","Install jail: $line\n"); + my @confCmd = split /\s+/,$line; + if($confCmd[0] =~ /dir/){ # if the command say to add a directory + if($#confCmd == 4) { # checking dir Cmd form + if(! (-d $jailPath . "/" . $confCmd[1])){ + #add a directory and change its permissions according + #to the conf file + &B_create_dir( $jailPath . "/" . $confCmd[1]); + &B_chperm((getpwnam($confCmd[3]))[2], + (getgrnam($confCmd[4]))[2], + oct($confCmd[2]), + $jailPath . "/" . $confCmd[1]); + } + } + else { + &B_log("ERROR","Badly Formed Configuration Line:\n$line\n\n"); + } + } + elsif($confCmd[0] =~ /file/) { + if($#confCmd == 5) { # checking file cmd form + if(&B_cp($confCmd[1],$jailPath . "/" . $confCmd[2])){ + # for copy command cp file and change perms + &B_chperm($confCmd[4],$confCmd[5],oct($confCmd[3]),$jailPath . "/" . $confCmd[2]); + } + else { + &B_log("ERROR","Could not complete copy on specified files:\n" . + "$line\n"); + } + } + else { + &B_log("ERROR","Badly Formed Configuration Line:\n" . + "$line\n\n"); + } + } + elsif($confCmd[0] =~ /slink/) { + if($#confCmd == 2) { # checking file cmd form + if(!(-e $jailPath . "/" . $confCmd[2])){ + #for symlink command create the symlink + &B_symlink($jailPath . "/" . $confCmd[1], $confCmd[2]); + } + } + else { + &B_log("ERROR","Badly Formed Configuration Line:\n" . + "$line\n\n"); + } + } + else { + &B_log("ERROR","Unrecognized Configuration Line:\n" . + "$line\n\n"); + } + } + return 1; +} + + + +########################################################################### +# &B_list_processes($service) # +# # +# This subroutine uses the GLOBAL_PROCESS hash to determine if a # +# service's corresponding processes are running on the system. # +# If any of the processes are found to be running then the process # +# name(s) is/are returned by this subroutine in the form of an list # +# If none of the processes that correspond to the service are running # +# then an empty list is returned. # +########################################################################### +sub B_list_processes($) { + + # service name + my $service = $_[0]; + # list of processes related to the service + my @processes=@{ &getGlobal('PROCESS',$service)}; + + # current systems process information + my $ps = &getGlobal('BIN',"ps"); + my $psTable = `$ps -elf`; + + # the list to be returned from the function + my @running_processes; + + # for every process associated with the service + foreach my $process (@processes) { + # if the process is in the process table then + if($psTable =~ m/$process/) { + # add the process to the list, which will be returned + push @running_processes, $process; + } + + } + + # return the list of running processes + return @running_processes; + +} + +############################################################################# +# &B_list_full_processes($service) # +# # +# This subroutine simply grep through the process table for those matching # +# the input argument TODO: Allow B_list process to levereage this code # +# ... Not done this cycle to avoid release risk (late in cycle) # +############################################################################# +sub B_list_full_processes($) { + + # service name + my $procName = $_[0]; + my $ps = &getGlobal('BIN',"ps"); + my @psTable = split(/\n/,`$ps -elf`); + + # for every process associated with the service + my @runningProcessLines = grep(/$procName/ , @psTable); + # return the list of running processes + return @runningProcessLines; +} + +################################################################################ +# &B_deactivate_inetd_service($service); # +# # +# This subroutine will disable all inetd services associated with the input # +# service name. Service name must be a reference to the following hashes # +# GLOBAL_SERVICE GLOBAL_SERVTYPE and GLOBAL_PROCESSES. If processes are left # +# running it will note these services in the TODO list as well as instruct the# +# user in how they remaining processes can be disabled. # +################################################################################ +sub B_deactivate_inetd_service($) { + my $service = $_[0]; + my $servtype = &getGlobal('SERVTYPE',"$service"); + my $inetd_conf = &getGlobal('FILE',"inetd.conf"); + + # check the service type to ensure that it can be configured by this subroutine. + if($servtype ne 'inet') { + &B_log("ACTION","The service \"$service\" is not an inet service so it cannot be\n" . + "configured by this subroutine\n"); + return 0; + } + + # check for the inetd configuration files existence so it may be configured by + # this subroutine. + if(! -e $inetd_conf ) { + &B_log("ACTION","The file \"$inetd_conf\" cannot be located.\n" . + "Unable to configure inetd\n"); + return 0; + } + + # list of service identifiers present in inetd.conf file. + my @inetd_entries = @{ &getGlobal('SERVICE',"$service") }; + + foreach my $inetd_entry (@inetd_entries) { + &B_hash_comment_line($inetd_conf, "^\\s*$inetd_entry"); + } + + # list of processes associated with this service which are still running + # on the system + my @running_processes = &B_list_processes($service); + + if($#running_processes >= 0) { + my $todoString = "\n" . + "---------------------------------------\n" . + "Deactivating Inetd Service: $service\n" . + "---------------------------------------\n" . + "The following process(es) are associated with the inetd service \"$service\".\n" . + "They are most likely associated with a session which was initiated prior to\n" . + "running Bastille. To disable a process see \"kill(1)\" man pages or reboot\n" . + "the system\n" . + "Active Processes:\n" . + "###################################\n"; + foreach my $running_process (@running_processes) { + $todoString .= "\t$running_process\n"; + } + $todoString .= "###################################\n"; + + &B_TODO($todoString); + } + +} + + +################################################################################ +# B_get_rc($key); # +# # +# This subroutine will use the ch_rc binary to get rc.config.d variables # +# values properly escaped and quoted. # +################################################################################ +sub B_get_rc($) { + + my $key=$_[0]; + my $ch_rc = &getGlobal('BIN',"ch_rc"); + + # get the current value of the given parameter. + my $currentValue=`$ch_rc -l -p $key`; + chomp $currentValue; + + if(($? >> 8) == 0 ) { + # escape all meta characters. + # $currentValue =~ s/([\"\`\$\\])/\\$1/g; + # $currentValue = '"' . $currentValue . '"'; + } + else { + return undef; + } + + return $currentValue; +} + + + +################################################################################ +# B_set_rc($key,$value); # +# # +# This subroutine will use the ch_rc binary to set rc.config.d variables. As # +# well as setting the variable this subroutine will set revert strings. # +# # +################################################################################ +sub B_set_rc($$;$) { + + my ($key,$value,$configfile)=@_; + my $ch_rc = &getGlobal('BIN',"ch_rc"); + + # get the current value of the given parameter. + my $currentValue=&B_get_rc($key); + if(defined $currentValue ) { + if ($currentValue =~ /^\"(.*)\"$/ ) { + $currentValue = '"\"' . $1 . '\""'; + } + if ($value =~ /^\"(.*)\"$/ ) { + $value = '"\"' . $1 . '\""'; + } + if ( &B_System("$ch_rc -a -p $key=$value $configfile", + "$ch_rc -a -p $key=$currentValue $configfile") ) { + #ch_rc success + return 1; + } + else { + #ch_rc failure. + return 0; + } + } + else { + &B_log("ERROR","ch_rc was unable to lookup $key\n"); + return 0; + } + +} + + +################################################################################ +# &ChrootHPApache($chrootScript,$httpd_conf,$httpd_bin, +# $apachectl,$apacheJailDir,$serverString); +# +# This subroutine given an chroot script, supplied by the vendor, a +# httpd.conf file, the binary location of httpd, the control script, +# the jail directory, and the servers identification string, descriptive +# string for TODO etc. It makes modifications to httpd.conf so that when +# Apache starts it will chroot itself into the jail that the above +# mentions script creates. +# +# uses B_replace_line B_create_dir B_System B_TODO +# +############################################################################### +sub B_chrootHPapache($$$$$$) { + + my ($chrootScript,$httpd_conf,$httpd_bin,$apachectl,$apacheJailDir,$serverString)= @_; + + my $exportpath = "export PATH=/usr/bin;"; + my $ps = &getGlobal('BIN',"ps"); + my $isRunning = 0; + my $todo_header = 0; + + # checking for a 2.0 version of the apache chroot script. + if(-e $chrootScript ) { + + if(open HTTPD, $httpd_conf) { + while (my $line = <HTTPD>){ + if($line =~ /^\s*Chroot/) { + &B_log("DEBUG","Apache is already running in a chroot as specified by the following line:\n$line\n" . + "which appears in the httpd.conf file. No Apache Chroot action was taken.\n"); + return; + } + } + close(HTTPD); + } + + if(`$ps -ef` =~ $httpd_bin ) { + $isRunning=1; + &B_System("$exportpath " . $apachectl . " stop","$exportpath " . $apachectl . " start"); + } + &B_replace_line($httpd_conf, '^\s*#\s*Chroot' , + "Chroot " . $apacheJailDir); + if(-d &getGlobal('BDIR',"jail")){ + &B_log("DEBUG","Jail directory already exists. No action taken.\n"); + } + else{ + &B_log("ACTION","Jail directory was created.\n"); + &B_create_dir( &getGlobal('BDIR','jail')); + } + + if(-d $apacheJailDir){ + &B_log("DEBUG","$serverString jail already exists. No action taken.\n"); + } + else{ + &B_System(&getGlobal('BIN',"umask") . " 022; $exportpath " . $chrootScript, + &getGlobal('BIN',"echo") . " \"Your $serverString is now running outside of it's\\n" . + "chroot jail. You must manually migrate your web applications\\n" . + "back to your Apache server's httpd.conf defined location(s).\\n". + "After you have completed this, feel free to remove the jail directories\\n" . + "from your machine. Your apache jail directory is located in\\n" . + &getGlobal('BDIR',"jail") . "\\n\" >> " . &getGlobal('BFILE',"TOREVERT")); + + } + if($isRunning){ + &B_System("$exportpath " . $apachectl . " start","$exportpath " . $apachectl . " stop"); + &B_log("ACTION","$serverString is now running in an chroot jail.\n"); + } + + &B_log("ACTION","The jail is located in " . $apacheJailDir . "\n"); + + if ($todo_header !=1){ + &B_TODO("\n---------------------------------\nApache Chroot:\n" . + "---------------------------------\n"); + } + &B_TODO("$serverString Chroot Jail:\n" . + "httpd.conf contains the Apache dependencies. You should\n" . + "review this file to ensure that the dependencies made it\n" . + "into the jail. Otherwise, you run a risk of your Apache server\n" . + "not having access to all its modules and functionality.\n"); + + + } + +} + + +sub isSystemTrusted { + my $getprdef = &getGlobal('BIN',"getprdef"); + my $definition = &B_Backtick("$getprdef -t 2>&1"); + if($definition =~ "System is not trusted.") { + return 0; + } else { + return 1; + } +} + + +sub isTrustedMigrationAvailable { + my $distroVersion=''; + + if (&GetDistro =~ '^HP-UX11.(\d*)') { + $distroVersion=$1; + if ($distroVersion < 23) { # Not available before 11.23 + return 0; #FALSE + } elsif ($distroVersion >= 31) { #Bundled with 11.31 and after + &B_log('DEBUG','isTrustedMigrationAvailable: HP-UX 11.31 always has trusted mode extensions'); + return 1; + } elsif ($distroVersion == 23) { # Optional on 11.23 if filesets installed + if ( -x &getGlobal('BIN',"userdbget") ) { + &B_log('DEBUG','isTrustedMigrationAvailable: Trusted Extensions Installed'); + return 1; + } else { + &B_log('DEBUG','isTrustedMigrationAvailable: Trusted Extensions Not Installed'); + return 0; #FALSE + } + } else { + &B_log('DEBUG','isTrustedMigrationAvailable: ' . &GetDistro . + ' not currently supported for trusted extentions.'); + return 0; #FALSE + } + } else { + &B_log('WARNING','isTrustedMigrationAvailable: HP-UX routine called on Linux system'); + return 0; #FALSE + } +} + + + +########################################################################### +# &checkServiceOnHPUX($service); +# +# Checks if the given service is running on an HP/UX system. This is +# called by B_is_Service_Off(), which is the function that Bastille +# modules should call. +# +# Return values: +# NOTSECURE_CAN_CHANGE() if the service is on +# SECURE_CANT_CHANGE() if the service is off +# INCONSISTENT() if the state of the service cannot be determined +# NOT_INSTALLED() if the s/w isn't insalled +# +########################################################################### +sub checkServiceOnHPUX($) { + my $service=$_[0]; + + # get the list of parameters which could be used to initiate the service + # (could be in /etc/rc.config.d, /etc/inetd.conf, or /etc/inittab, so we + # check all of them) + my @params= @{ &getGlobal('SERVICE',$service) }; + my $grep =&getGlobal('BIN', 'grep'); + my $inetd=&getGlobal('FILE', 'inetd.conf'); + my $inittab=&getGlobal('FILE', 'inittab'); + my $retVals; + my $startup=&getGlobal('DIR','initd') ; + my @inet_bins= @{ &getGlobal('PROCESS',$service) }; + + my $entry_found = 0; + + &B_log("DEBUG","CheckHPUXservice: $service"); + my $full_initd_path = $startup . "/" . $service; + if ($GLOBAL_SERVTYPE{$service} eq "rc") { # look for the init script in /sbin/init.d + if (not(-e $full_initd_path )) { + return NOT_INSTALLED(); + } + } else { #inet-based service, so look for inetd.conf entries. + &B_log("DEBUG","Checking inet service $service"); + my @inet_entries= @{ &getGlobal('SERVICE',$service) }; + foreach my $service (@inet_entries) { + &B_log('DEBUG',"Checking for inetd.conf entry of $service in checkService on HPUX"); + my $service_regex = '^[#\s]*' . $service . '\s+'; + if ( &B_match_line($inetd, $service_regex) ) { # inet entry search + &B_log('DEBUG',"$service present, entry exists"); + $entry_found = 1 ; + } + } + if ($entry_found == 0 ) { + return NOT_INSTALLED(); + } + } + + foreach my $param (@params) { + &B_log("DEBUG","Checking to see if service $service is off.\n"); + if (&getGlobal('SERVTYPE', $service) =~ /rc/) { + my $ch_rc=&getGlobal('BIN', 'ch_rc'); + my $on=&B_Backtick("$ch_rc -l -p $param"); + + $on =~ s/\s*\#.*$//; # remove end-of-line comments + $on =~ s/^\s*\"(.+)\"\s*$/$1/; # remove surrounding double quotes + $on =~ s/^\s*\'(.+)\'\s*$/$1/; # remove surrounding single quotes + $on =~ s/^\s*\"(.+)\"\s*$/$1/; # just in case someone did '"blah blah"' + + chomp $on; + &B_log("DEBUG","ch_rc returned: $param=$on in checkServiceOnHPUX"); + + if ($on =~ /^\d+$/ && $on != 0) { + # service is on + &B_log("DEBUG","CheckService found $param service is set to \'on\' in scripts."); + return NOTSECURE_CAN_CHANGE(); + } + elsif($on =~ /^\s*$/) { + # if the value returned is an empty string return + # INCONSISTENT(), since we don't know what the hard-coded default is. + return INCONSISTENT(); + } + } else { + # those files which rely on comments to determine what gets + # turned on, such as inetd.conf and inittab + my $inettabs=&B_Backtick("$grep -e '^[[:space:]]*$param' $inetd $inittab"); + if ($inettabs =~ /.+/) { # . matches anything except newlines + # service is not off + &B_log("DEBUG","Checking inetd.conf and inittab; found $inettabs"); + ########################### BREAK out, don't skip question + return NOTSECURE_CAN_CHANGE(); + } + } + } # foreach $param + + # boot-time parameters are not set; check processes + # checkprocs for services returns INCONSISTENT() if a service is found + # since a found-service is inconsistent with the above checks. + B_log("DEBUG","Boot-Parameters not set, checking processes."); + if (&runlevel < 2) { # Below runlevel 2, it is unlikely that + #services will be running, so just check "on-disk" state + &B_log("NOTE","Running during boot sequence, so skipping process checks"); + return SECURE_CANT_CHANGE(); + } else { + return &checkProcsForService($service); + } +} + +sub runlevel { + my $who = &getGlobal("BIN", "who"); + my $runlevel = &B_Backtick("$who -r"); + if ($runlevel =~ s/.* run-level (\S).*/$1/) { + &B_log("DEBUG","Runlevel is: $runlevel"); + return $runlevel; + } else { + &B_log("WARNING","Can not determine runlevel, assuming runlevel 3"); + &B_log("DEBUG","Runlevel command output: $runlevel"); + return "3"; #safer since the who command didn't work, we'll assume + # runlevel 3 since that provides more checks. + } +} + +# +# given a profile file, it will return a PATH array set by the file. +# +sub B_get_path($) { + my $file = $_[0]; + my $sh = &getGlobal("BIN", "sh"); + # use (``)[0] is becuase, signal 0 maybe trapped which will produce some stdout + my $path = (`$sh -c '. $file 1>/dev/null 2>&1 < /dev/null ; echo \$PATH'`)[0]; + my @path_arr = split(":", $path); + my %tmp_path; + my %path; + for my $tmpdir (@path_arr) { + chomp $tmpdir; + if ($tmpdir ne "" && ! $tmp_path{$tmpdir}) { + $tmp_path{$tmpdir}++; + } + } + return keys %tmp_path; +} + +# Convert to trusted mode if it's not already +sub convertToTrusted { + &B_log("DEBUG","# sub convertToTrusted \n"); + if( ! &isSystemTrusted) { + + my ($ok, $message) = &isOKtoConvert; + + my $ts_header="\n---------------------------------\nTrusted Systems:\n" . + "---------------------------------\n"; + + if ($ok) { + # actually do the conversion + if(&B_System(&getGlobal('BIN','tsconvert'), &getGlobal('BIN','tsconvert') . " -r")){ + # adjust change times for user passwords to keep them valid + # default is to expire them when converting to a trusted system, + # which can be problematic, especially since some older versions of + # SecureShell do not allow the user to change the password + &B_System(&getGlobal('BIN','modprpw') . " -V", ""); + + my $getprdef = &getGlobal('BIN','getprdef'); + my $oldsettings = &B_Backtick("$getprdef -m lftm,exptm,mintm,expwarn,umaxlntr"); + $oldsettings =~ s/ //g; + + # remove password lifetime and increasing login tries so they + # don't lock themselves out of the system entirely. + # set default expiration time and the like. + my $newsettings="lftm=0,exptm=0,mintm=0,expwarn=0,umaxlntr=10"; + + &B_System(&getGlobal('BIN','modprdef') . " -m $newsettings", + &getGlobal('BIN','modprdef') . " -m $oldsettings"); + + &B_TODO($ts_header . + "Your system has been converted to a trusted system.\n" . + "You should review the security settings available on a trusted system.\n". + "$message"); + + # to get rid of "Cron: Your job did not contain a valid audit ID." + # error, we re-read the crontab file after converting to trusted mode + # Nothing is necessary in "revert" since we won't be in trusted mode + # at that time. + # crontab's errors can be spurious, and this will report an 'error' + # of the crontab file is missing, so we send stderr to the bit bucket + my $crontab = &getGlobal('BIN',"crontab"); + &B_System("$crontab -l 2>/dev/null | $crontab",""); + } + + } else { + &B_TODO($ts_header . $message); + return 0; # not ok to convert, so we didn't + } + } + else { + &B_log("DEBUG","System is already in trusted mode, no action taken.\n"); + return 1; + } + + # just to make sure + if( &isSystemTrusted ) { + return 1; + } else { + &B_log("ERROR","Trusted system conversion was unsuccessful for an unknown reason.\n" . + " You may try using SAM/SMH to do the conversion instead of Bastille.\n"); + return 0; + } +} + +# isOKtoConvert - check for conflicts between current system state and trusted +# mode +# +# Return values +# 0 - conflict found, see message for details +# 1 - no conflicts, see message for further instructions +# +sub isOKtoConvert { + &B_log("DEBUG","# sub isOKtoConvert \n"); + # initialize text for TODO instructions + my $specialinstructions=" - convert to trusted mode\n"; + + # These are somewhat out-of-place, but only affect the text of the message. + # Each of these messages is repeated in a separate TODO item in the + # appropriate subroutine. + if (&getGlobalConfig("AccountSecurity","single_user_password") eq "Y") { + if (&GetDistro =~ "^HP-UX11.(.*)" and $1<23 ) { + $specialinstructions .= " - set a single user password\n"; + } + } + + if (&getGlobalConfig("AccountSecurity","passwordpolicies") eq "Y") { + $specialinstructions .= " - set trusted mode password policies\n"; + } + + if (&getGlobalConfig("AccountSecurity", "PASSWORD_HISTORY_DEPTHyn") eq "Y") { + $specialinstructions .= " - set a password history depth\n"; + } + + if (&getGlobalConfig("AccountSecurity","system_auditing") eq "Y") { + $specialinstructions .= " - enable auditing\n"; + } + + my $saminstructions= + "The security settings can be modified by running SAM as follows:\n" . + "# sam\n" . + "Next, go to the \"Auditing and Security Area\" and review\n" . + "each sub-section. Make sure that you review all of your\n" . + "settings, as some policies may seem restrictive.\n\n" . + "On systems using the System Management Homepage, you can\n". + "change your settings via the Tools:Security Attributes Configuration\n". + "section. On some systems, you may also have the option of using SMH.\n\n"; + + # First, check for possible conflicts and corner cases + + # check nsswitch for possible conflicts + my $nsswitch = &getGlobal('FILE', 'nsswitch.conf'); + if ( -e $nsswitch) { + open(FILE, $nsswitch); + while (<FILE>) { + if (/nis/ or /compat/ or /ldap/) { + my $message = "Bastille found a possible conflict between trusted mode and\n" . + "$nsswitch. Please remove all references to\n" . + "\"compat\", \"nis\" and \"ldap\" in $nsswitch\n" . + "and rerun Bastille, or use SAM/SMH to\n" . + "$specialinstructions\n". + "$saminstructions"; + close(FILE); + return (0,$message); + } + } + close(FILE); + } + + # check the namesvrs config file for possible NIS conflicts + #Changed to unless "Y AND Y" since question can be skipped when nis is off + # but corner cases can still exist, so check then too. + unless ( &getGlobalConfig('MiscellaneousDaemons','nis_client') eq "Y" and + &getGlobalConfig('MiscellaneousDaemons','nis_server') eq "Y" ) { + my $namesvrs = &getGlobal('FILE', 'namesvrs'); + if (open(FILE, $namesvrs)) { + while (<FILE>) { + if (/^NIS.*=["]?1["]?$/) { + my $message= "Possible conflict between trusted mode and NIS found.\n". + "Please use SAM/SMH to\n" . + " - turn off NIS\n" . + "$specialinstructions\n". + "$saminstructions"; + close(FILE); + return (0,$message); + } + } + close(FILE); + } else { + &B_log("ERROR","Unable to open $namesvrs for reading."); + my $message= "Possible conflict between trusted mode and NIS found.\n". + "Please use SAM/SMH to\n" . + " - turn off NIS\n" . + "$specialinstructions\n". + "$saminstructions"; + return (0,$message); + } + if ( &B_match_line (&getGlobal("FILE","passwd"),"^\+:.*")) { + my $message= '"+" entry found in passwd file. These are not\n' . + "compatible with Trusted Mode. Either remove the entries\n" . + "and re-run Bastille, or re-run Bastille, and direct it to\n" . + "disable NIS client and server.\n"; + return (0,$message); + } + + } + + + # check for conflicts with DCE integrated login + my $authcmd = &getGlobal('BIN','auth.adm'); + if ( -e $authcmd ) { + my $retval = system("PATH=/usr/bin $authcmd -q 1>/dev/null 2>&1"); + if ($retval != 0 and $retval != 1) { + my $message="It appears that DCE integrated login is configured on this system.\n" . + "DCE integrated login is incompatible with trusted systems and\n" . + "auditing. Bastille is unable to\n" . + "$specialinstructions" . + "You will need to configure auditing and password policies using DCE.\n\n"; + return (0,$message); + } + } + + if ( -e &getGlobal('FILE','shadow') ) { + my $message="This system has already been converted to shadow passwords.\n" . + "Shadow passwords are incompatible with trusted mode.\n" . + "Bastille is unable to\n" . + "$specialinstructions" . + "If you desire these features, you should use\n". + "\'pwunconv\' to change back to standard passwords,\n". + "and then rerun Bastille.\n\n"; + return (0,$message); + } + + return (1,$saminstructions); +} + +# This routine allows Bastille to determine trusted-mode extension availability + +sub convertToShadow { + + if (&isSystemTrusted) { + # This is an internal error...Bastille should not call this routine + # in this case. Error is here for robustness against future changes. + &B_log("ERROR","This system is already converted to trusted mode.\n" . + " Converting to shadow passwords will not be attempted.\n"); + return 0; + } + + # configuration files on which shadowed passwords depend + my $nsswitch_conf = &getGlobal('FILE',"nsswitch.conf"); + + # binaries used to convert to a shadowed password + my $pwconv = &getGlobal('BIN',"pwconv"); + my $echo = &getGlobal('BIN','echo'); # the echo is used to pipe a yes into the pwconv program as + # pwconv requires user interaction. + + # the binary used in a system revert. + my $pwunconv = &getGlobal('BIN',"pwunconv"); + #check the password file for nis usage and if the nis client + #or server is running. + if(-e $nsswitch_conf) { + # check the file for nis, nis+, compat, or dce usage. + if(&B_match_line($nsswitch_conf, '^\s*passwd:.+(nis|nisplus|dce|compat)')) { + my $shadowTODO = "\n---------------------------------\nHide encrypted passwords:\n" . + "---------------------------------\n" . + "This version of password shadowing does not support any repository other\n" . + "than files. In order to convert your password database to shadowed passwords\n" . + "there can be no mention of nis, nisplus, compat, or dce in the passwd\n" . + "field of the \"$nsswitch_conf\" file. Please make the necessary edits to\n" . + "the $nsswitch_conf file and run Bastille again using the command:\n" . + "\"bastille -b\"\n"; + # Adding the shadowTODO comment to the TODO list. + &B_TODO("$shadowTODO"); + # Notifing the user that the shadowed password coversion has failed. + &B_log("ERROR","Password Shadowing Conversion Failed\n" . + "$shadowTODO"); + # exiting the subroutine. + return 0; + } + + } + + # convert the password file to a shadowed repository. + if (( -e $pwconv ) and ( -e $pwunconv ) and + ( &B_System("$echo \"yes\" | $pwconv","$pwunconv") ) ){ + &B_TODO( "\n---------------------------------\nShadowing Password File:\n" . + "---------------------------------\n" . + "Your password file has been converted to use password shadowing.\n" . + "This version of password shadowing does not support any repository other\n" . + "than files. There can be no mention of nis, nisplus, compat, or dce\n" . + "in the passwd field of the \"$nsswitch_conf\" file.\n\n" ); + } else { + &B_log("ERROR","Conversion to shadow mode failed. The system may require ". + "a patch to be capable of switching to shadow mode, or the ". + "system my be in a state where conversion is not possible."); + } +} + + + +########################################################################## +# &getSupportedSettings(); +# Manipulates %trustedParameter and %isSupportedSetting, file-scoped variables +# +# Reads the password policy support matrix, which in-turn gives Bastille the +# places it should look for a given password policy setting. + +# Note the file was created like this so if could be maintained in an Excel(tm) +# spreadsheet, to optimize reviewability. TODO: consider other formats + +# File Format: +# HEADERS:<comment>,[<OS Version> <Mode> <Extensions>,]... +# [ +# :<label>:<trusted equivalent>,,,,,,,,,,,,<comment> +# <action> (comment), [<test value>,]... +# ] ... +# Example; +# HEADERS:Information Source (trusted equiv),11.11 Standard no-SMSE,11.11 Trusted no-SMSE,11.11 Shadow no-SMSE,11.23 Standard no-SMSE,11.23 Trusted no-SMSE,11.23 Shadow no-SMSE,11.23 Standard SMSE,11.23 Shadow SMSE,11.23 Trusted SMSE,11.31 Trusted SMSE,11.31 Shadow SMSE,11.31 Standard SMSE,Other Exceptions +#:ABORT_LOGIN_ON_MISSING_HOMEDIR,,,,,,,,,,,,,root +#/etc/security.dsc (search),x,,xx,x,x,x,!,!,!,!,!,!, +#/etc/default/security(search),y,y,y,y,y,y,y,y,y,y,y,y, +#getprdef (execute with <Trusted Equiv> argument),x,x,x,x,x,x,x,x,x,x,x,x, + +########################################################################### +our %trustedParameter = (); +our %isSupportedSetting = (); + +sub getSupportedSettings() { + + my $line; # For a config file line + my $linecount = 0; + my $currentsetting = ""; + my @fields; # Fields in a given line + my @columns; #Column Definitions + + + &B_open(*SETTINGSFILE,&getGlobal('BFILE','AccountSecSupport')); + my @settingLines=<SETTINGSFILE>; + &B_close(*SETTINGSFILE); + + #Remove blank-lines and comments + @settingLines = grep(!/^#/,@settingLines); + @settingLines = grep(!/^(\s*,+)*$/,@settingLines); + + foreach $line (@settingLines) { + ++$linecount; + @fields = split(/,/,$line); + if ($line =~ /^Information Source:/) { #Sets up colums + my $fieldcount = 1; #Skipping first field + while ((defined($fields[$fieldcount])) and + ($fields[$fieldcount] =~ /\d+\.\d+/)){ + my @subfields = split(/ /,$fields[$fieldcount]); + my $fieldsCount = @subfields; + if ($fieldsCount != 3){ + &B_log("ERROR","Invalid subfield count: $fieldsCount in:". + &getGlobal('BFILE','AccountSecSupport') . + " line: $linecount and field: $fieldcount"); + } + $columns[$fieldcount] = {OSVersion => $subfields[0], + Mode => $subfields[1], + Extension => $subfields[2] }; + &B_log("DEBUG","Found Header Column, $columns[$fieldcount]{'OSVersion'}, ". + $columns[$fieldcount]{'Mode'} ." , " . + $columns[$fieldcount]{'Extension'}); + ++$fieldcount; + } # New Account Seting ex: + } elsif ($line =~ /^:([^,:]+)(?::([^,]+))?/) { # :PASSWORD_WARNDAYS:expwarn,,,,,,,,,,,, + $currentsetting = $1; + if (defined($2)) { + $trustedParameter{"$currentsetting"}=$2; + } + &B_log("DEBUG","Found Current Setting: ". $currentsetting . + "/" . $trustedParameter{"$currentsetting"}); + } elsif (($line =~ /(^[^, :\)\(]+)[^,]*,((?:(?:[!y?nx]|!!),)+)/) and #normal line w/ in setting ex: + ($currentsetting ne "")){ # security.dsc (search),x,x,x,x,x,!,!!,!,!,!,!, + my $placeToLook = $1; + my $fieldcount = 1; #Skip the first one, which we used in last line + while (defined($fields[$fieldcount])) { + &B_log("DEBUG","Setting $currentsetting : $columns[$fieldcount]{OSVersion} , ". + "$columns[$fieldcount]{Mode} , ". + "$columns[$fieldcount]{Extension} , ". + "$placeToLook, to $fields[$fieldcount]"); + $isSupportedSetting{"$currentsetting"} + {"$columns[$fieldcount]{OSVersion}"} + {"$columns[$fieldcount]{Mode}"} + {"$columns[$fieldcount]{Extension}"} + {"$placeToLook"} = + $fields[$fieldcount]; + ++$fieldcount; + } + } else { + if ($line !~ /^,*/) { + &B_log("ERROR","Incorrectly Formatted Line at ". + &getGlobal('BFILE','AccountSecSupport') . ": $linecount"); + } + } + } +} + +########################################################################## +# &B_get_sec_value($param); +# This subroutine finds the value for a given user policy parameter. +# Specifically, it supports the parameters listed in the internal data structure + +# Return values: +# 'Not Defined' if the value is not present or not uniquely defined. +# $value if the value is present and unique +# +########################################################################### +sub B_get_sec_value($) { + my $param=$_[0]; + + my $os_version; + if (&GetDistro =~ /^HP-UX\D*(\d+\.\d+)/ ){ + $os_version=$1; + } else { + &B_log("ERROR","B_get_sec_value only supported on HP-UX"); + return undef; + } +# my $sec_dsc = &getGlobal('FILE', 'security.dsc'); + my $sec_file = &getGlobal('FILE', 'security'); + my $getprdef = &getGlobal('BIN','getprdef'); + my $getprpw = &getGlobal('BIN','getprpw'); + my $userdbget = &getGlobal('BIN','userdbget'); + my $passwd = &getGlobal('BIN','passwd'); + + my $sec_flags = ""; + my @sec_settings=(); + my $user_sec_setting=""; + + my $security_mode="Standard"; + my $security_extension="no-SMSE"; + + &B_log("DEBUG","Entering get_sec_value for: $param"); + + sub isok ($) { # Locally-scoped subroutine, takes supported-matrix entry as argument + my $supportedMatrixEntry = $_[0]; + + if ($supportedMatrixEntry =~ /!/) { #Matrix Entry for "Documented and/or tested" + &B_log("DEBUG","isOk TRUE: $supportedMatrixEntry"); + return 1; + } else { + &B_log("DEBUG","isOk FALSE: $supportedMatrixEntry"); + return 0; #FALSE + } + } #end local subroutine + + #Get Top Array item non-destructively + sub getTop (@) { + my @incomingArray = @_; + my $topval = pop(@incomingArray); + push(@incomingArray,$topval); #Probably redundant, but left in just in case. + return $topval; + } + + sub ifExistsPushOnSecSettings($$) { + my $sec_settings = $_[0]; + my $pushval = $_[1]; + + if ($pushval ne ""){ + push (@$sec_settings, $pushval); + } + } + + #prpw and prdef both use "YES" instead of "1" like the other settings. + sub normalizePolicy($){ + my $setting = $_[0]; + + $setting =~ s/YES/1/; + $setting =~ s/NO/1/; + + return $setting; + } + + + + if ((%trustedParameter == ()) or (%isSupportedSetting == ())) { + # Manipulates %trustedParameter and %isSupportedSetting + &getSupportedSettings; + } + + #First determine the security mode + my $shadowFile = &getGlobal("FILE","shadow"); + my $passwdFile = &getGlobal("FILE","passwd"); + + if (&isSystemTrusted) { + $security_mode = 'Trusted'; + } elsif ((-e $shadowFile) and #check file exist, and that passwd has no non-"locked" accounts + (not(&B_match_line($passwdFile,'^[^\:]+:[^:]*[^:*x]')))) { + $security_mode = 'Shadow'; + } else { + $security_mode = 'Standard'; + } + if (&isTrustedMigrationAvailable) { + $security_extension = 'SMSE'; + } else { + $security_extension = 'no-SMSE'; + } + &B_log("DEBUG","Security mode: $security_mode extension: $security_extension"); + # Now look up the value from each applicable database, from highest precedence + # to lowest: + &B_log("DEBUG","Checking $param in userdbget"); + if (&isok($isSupportedSetting{$param}{$os_version}{$security_mode} + {$security_extension}{"userdbget_-a"})) { + &ifExistsPushOnSecSettings(\@sec_settings, + &B_getValueFromString('\w+\s+\w+=(\S+)', + &B_Backtick("$userdbget -a $param"))); + &B_log("DEBUG", $param . ":userdbget setting: ". &getTop(@sec_settings)); + } + &B_log("DEBUG","Checking $param in passwd"); + if (&isok($isSupportedSetting{$param}{$os_version}{$security_mode} + {$security_extension}{"passwd_-sa"})) { + if ($param eq "PASSWORD_MINDAYS") { + &ifExistsPushOnSecSettings(\@sec_settings, + &B_getValueFromString('(?:\w+\s+){2}[\d\/]+\s+(\d+)\s+\d+', + &B_Backtick("$passwd -s -a"))); + } elsif ($param eq "PASSWORD_MAXDAYS") { + &ifExistsPushOnSecSettings(\@sec_settings, + &B_getValueFromString('(?:\w+\s+){2}[\d\/]+\s+\d+\s+(\d+)', + &B_Backtick("$passwd -s -a"))); + } elsif ($param eq "PASSWORD_WARNDAYS") { + &ifExistsPushOnSecSettings(\@sec_settings, + &B_getValueFromString('(?:\w+\s+){2}[\d\/]+(?:\s+\d+){2}\s+(\d+)', + &B_Backtick("$passwd -s -a"))); + } + &B_log("DEBUG", $param . ":passwd -sa setting: ". &getTop(@sec_settings)); + } + &B_log("DEBUG","Checking $param in get prpw"); + if (&isok($isSupportedSetting{$param}{$os_version}{$security_mode} + {$security_extension}{"getprpw"})) { + my $logins = &getGlobal("BIN","logins"); + my @userArray = split(/\n/,`$logins`); + my $userParamVals = ''; + foreach my $rawuser (@userArray) { + $rawuser =~ /^(\S+)/; + my $user = $1; + my $nextParamVal=&B_Backtick("$getprpw -l -m $trustedParameter{$param} $user"); + $nextParamVal =~ s/\w*=(-*[\w\d]*)/$1/; + if ($nextParamVal != -1) { #Don't count users for which the local DB is undefined + $userParamVals .= $user . "::::" . $nextParamVal ."\n"; + } + } #Note getValueFromStrings deals with duplicates, returning "Not Unigue" + my $policySetting = &B_getValueFromString('::::(\S+)',"$userParamVals"); + &ifExistsPushOnSecSettings (\@sec_settings, &normalizePolicy($policySetting)); + &B_log("DEBUG", $param . ":prpw setting: ". &getTop(@sec_settings)); + } + &B_log("DEBUG","Checking $param in get prdef"); + if (&isok($isSupportedSetting{$param}{$os_version}{$security_mode} + {$security_extension}{"getprdef"})) { + $_ = &B_Backtick ("$getprdef -m " . $trustedParameter{$param}); + /\S+=(\S+)/; + my $policySetting = $1; + &ifExistsPushOnSecSettings(\@sec_settings, &normalizePolicy($policySetting)); + &B_log("DEBUG", $param . ":prdef setting: ". &getTop(@sec_settings)); + + } + &B_log("DEBUG","Checking $param in default security"); + if (&isok($isSupportedSetting{$param}{$os_version}{$security_mode} + {$security_extension}{"/etc/default/security"})) { + &ifExistsPushOnSecSettings(\@sec_settings,&B_getValueFromFile('^\s*'. $param . + '\s*=\s*([^\s#]+)\s*$', $sec_file)); + &B_log("DEBUG", $param . ":default setting: ". &getTop(@sec_settings)); + } + #Commented below code in 3.0 release to avoid implication that bastille + #had ever set these values explicitly, and the implications to runnable + #config files where Bastille would then apply the defaults as actual policy + #with possible conversion to shadow or similar side-effect. + +# &B_log("DEBUG","Checking $param in security.dsc"); + #security.dsc, only added in if valid for OS/mode/Extension, and nothing else + #is defined (ie: @sec_settings=0) +# if ((&isok($isSupportedSetting{$param}{$os_version}{$security_mode} +# {$security_extension}{"/etc/security.dsc"})) and (@sec_settings == 0)) { +# &ifExistsPushOnSecSettings(\@sec_settings, &B_getValueFromFile('^' . $param . +# ';(?:[-\w/]*;){2}([-\w/]+);', $sec_dsc)); +# &B_log("DEBUG", $param . ":security.dsc: ". &getTop(@sec_settings)); +# } + + # Return what we found + my $last_setting=undef; + my $current_setting=undef; + while (@sec_settings > 0) { + $current_setting = pop(@sec_settings); + &B_log("DEBUG","Comparing $param configuration for identity: " . + $current_setting); + if ((defined($current_setting)) and ($current_setting ne '')) { + if (not(defined($last_setting))){ + $last_setting=$current_setting; + } elsif (($last_setting ne $current_setting) or + ($current_setting eq 'Not Unique')){ + &B_log("DEBUG","$param setting not unique."); + return 'Not Unique'; # Inconsistent state found, return 'Not Unique' + } + } + } + if ((not(defined($last_setting))) or ($last_setting eq '')) { + return undef; + } else { + return $last_setting; + } + +} #End B_get_sec_value + +sub secureIfNoNameService($){ + my $retval = $_[0]; + + if (&isUsingRemoteNameService) { + return MANUAL(); + } else { + return $retval; + } +} + +#Specifically for cleartext protocols like NIS, which are not "secure" +sub isUsingRemoteNameService(){ + + if (&remoteServiceCheck('nis|nisplus|dce') == SECURE_CAN_CHANGE()){ + return 0; #false + } else { + return 1; + } +} + + + +########################################### +## This is a wrapper for two functions that +## test the existence of nis-like configurations +## It is used by both the front end test and the back-end run +############################################## +sub remoteServiceCheck($){ + my $regex = $_[0]; + + my $nsswitch_conf = &getGlobal('FILE',"nsswitch.conf"); + my $passwd = &getGlobal('FILE',"passwd"); + + # check the file for nis usage. + if (-e $nsswitch_conf) { + if (&B_match_line($nsswitch_conf, '^\s*passwd:.*('. $regex . ')')) { + return NOTSECURE_CAN_CHANGE(); + } elsif ((&B_match_line($nsswitch_conf, '^\s*passwd:.*(compat)')) and + (&B_match_line($passwd, '^\s*\+'))) { + return NOTSECURE_CAN_CHANGE(); # true + } + } elsif ((&B_match_line($passwd, '^\s*\+'))) { + return NOTSECURE_CAN_CHANGE(); + } + + my $oldnisdomain=&B_get_rc("NIS_DOMAIN"); + if ((($oldnisdomain eq "") or ($oldnisdomain eq '""')) and (&checkServiceOnHPUX('nis.client'))){ + return SECURE_CAN_CHANGE(); + } + return NOTSECURE_CAN_CHANGE(); +} + +############################################# +# remoteNISPlusServiceCheck +# test the existence of nis+ configuration +############################################# +sub remoteNISPlusServiceCheck () { + + my $nsswitch_conf = &getGlobal('FILE',"nsswitch.conf"); + + # check the file for nis+ usage. + if (-e $nsswitch_conf) { + if (&B_match_line($nsswitch_conf, 'nisplus')) { + return NOTSECURE_CAN_CHANGE(); + } + } + + return &checkServiceOnHPUX('nisp.client'); +} + + +########################################################################## +# This subroutine creates nsswitch.conf file if the file not exists, +# and then append serveral services into the file if the service not +# exists in the file. +########################################################################## +sub B_create_nsswitch_file ($) { + my $regex = $_[0]; + + my $nsswitch = &getGlobal('FILE',"nsswitch.conf"); + + if( ! -f $nsswitch ) { + &B_create_file($nsswitch); + # we don't need to revert the permissions change because we just + # created the file + chmod(0444, $nsswitch); + + &B_append_line($nsswitch,'\s*passwd:', "passwd: $regex\n"); + &B_append_line($nsswitch,'\s*group:', "group: $regex\n"); + &B_append_line($nsswitch,'\s*hosts:', "hosts: $regex\n"); + &B_append_line($nsswitch,'\s*networks:', "networks: $regex\n"); + &B_append_line($nsswitch,'\s*protocols:', "protocols: $regex\n"); + &B_append_line($nsswitch,'\s*rpc:', "rpc: $regex\n"); + &B_append_line($nsswitch,'\s*publickey:', "publickey: $regex\n"); + &B_append_line($nsswitch,'\s*netgroup:', "netgroup: $regex\n"); + &B_append_line($nsswitch,'\s*automount:', "automount: $regex\n"); + &B_append_line($nsswitch,'\s*aliases:', "aliases: $regex\n"); + &B_append_line($nsswitch,'\s*services:', "services: $regex\n"); + } +} + +1; + diff --git a/meta-security/recipes-security/bastille/files/Miscellaneous.pm b/meta-security/recipes-security/bastille/files/Miscellaneous.pm new file mode 100644 index 000000000..b3bdf10cd --- /dev/null +++ b/meta-security/recipes-security/bastille/files/Miscellaneous.pm @@ -0,0 +1,166 @@ +package Bastille::API::Miscellaneous; +use strict; + +use File::Path; +use Bastille::API; +use Bastille::API::HPSpecific; +use Bastille::API::FileContent; + +require Exporter; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw( +PrepareToRun +B_is_package_installed +); +our @EXPORT = @EXPORT_OK; + + +########################################################################### +# +# PrepareToRun sets up Bastille to run. It checks the ARGV array for +# special options and runs ConfigureForDistro to set necessary file +# locations and other global variables. +# +########################################################################### + +sub PrepareToRun { + + # Make sure we're root! + if ( $> != 0 ) { + &B_log("ERROR","Bastille must run as root!\n"); + exit(1); + } + + + # Make any directories that don't exist... + foreach my $dir (keys %GLOBAL_BDIR) { + my $BdirPath = $GLOBAL_BDIR{$dir}; + if ( $BdirPath =~ /^\s*\// ) { #Don't make relative directories + mkpath ($BdirPath,0,0700); + } + } + + if(&GetDistro =~ "^HP-UX") { + &B_check_system; + } + + &B_log("ACTION","\n########################################################\n" . + "# Begin Bastille Run #\n" . + "########################################################\n\n"); + + #read sum file if it exists. + &B_read_sums; + + +# No longer necessary as flags are no longer in sum file, and sums are +# are now checked "real time" + + # check the integrity of the files listed +# for my $file (sort keys %GLOBAL_SUM) { +# &B_check_sum($file); +# } + # write out the newly flagged sums +# &B_write_sums; + + +} + + + +########################################################################### +# &B_is_package_installed($package); +# +# This function checks for the existence of the package named. +# +# TODO: Allow $package to be an expression. +# TODO: Allow optional $version, $release, $epoch arguments so we can +# make sure that the given package is at least as recent as some +# given version number. +# +# scalar return values: +# 0: $package is not installed +# 1: $package is installed +########################################################################### + +sub B_is_package_installed($) { + no strict; + my $package = $_[0]; +# Create a "global" variable with values scoped to this function +# We do this to avoid having to repeatedly swlist/rpm +# when we run B_is_package_installed +local %INSTALLED_PACKAGE_LIST; + + my $distro = &GetDistro; + if ($distro =~ /^HP-UX/) { + if (&checkProcsForService('swagent','ignore_warning') == SECURE_CANT_CHANGE()) { + &B_log("WARNING","Software Distributor Agent(swagent) is not running. Can not tell ". + "if package: $package is installed or not. Bastille will assume not. ". + "If the package is actually installed, Bastille may report or configure incorrectly.". + "To use Bastille-results as-is, please check to ensure $package is not installed, ". + "or re-run with the swagent running to get correct results."); + return 0; #FALSE + } + my $swlist=&getGlobal('BIN','swlist'); + if (%INSTALLED_PACKAGE_LIST == () ) { # re-use prior results + if (open(SWLIST, "$swlist -a state -l fileset |")) { + while (my $line = <SWLIST>){ + if ($line =~ /^ {2}\S+\.(\S+)\s*(\w+)/) { + $INSTALLED_PACKAGE_LIST{$1} = $2; + } + } + close SWLIST; + } else { + &B_log("ERROR","B_is_package_installed was unable to run the swlist command: $swlist,\n"); + return FALSE; + } + } + # Now find the entry + if ($INSTALLED_PACKAGE_LIST{$package} == 'configured') { + return TRUE; + } else { + return FALSE; + } + } #End HP-UX Section + # This routine only works on RPM-based distros: Red Hat, Fedora, Mandrake and SuSE + elsif ( ($distro !~ /^RH/) and ($distro !~ /^MN/) and($distro !~ /^SE/) ) { + return 0; + } else { #This is a RPM-based distro + # Run an rpm command -- librpm is extremely messy, dynamic and not + # so much a perl thing. It's actually barely a C/C++ thing... + if (open RPM,"rpm -q $package") { + # We should get only one line back, but let's parse a few + # just in case. + my @lines = <RPM>; + close RPM; + # + # This is what we're trying to parse: + # $ rpm -q jay + # package jay is not installed + # $ rpm -q bash + # bash-2.05b-305.1 + # + + foreach $line (@lines) { + if ($line =~ /^package\s$package\sis\snot\sinstalled/) { + return 0; + } + elsif ($line =~ /^$package\-/) { + return 1; + } + } + + # If we've read every line without finding one of these, then + # our parsing is broken + &B_log("ERROR","B_is_package_installed was unable to find a definitive RPM present or not present line.\n"); + return 0; + } else { + &B_log("ERROR","B_is_package_installed was unable to run the RPM command,\n"); + return 0; + } + } +} + + + +1; + diff --git a/meta-security/recipes-security/bastille/files/ServiceAdmin.pm b/meta-security/recipes-security/bastille/files/ServiceAdmin.pm new file mode 100644 index 000000000..879223a53 --- /dev/null +++ b/meta-security/recipes-security/bastille/files/ServiceAdmin.pm @@ -0,0 +1,690 @@ +package Bastille::API::ServiceAdmin; +use strict; + +use Bastille::API; + +use Bastille::API::HPSpecific; +use Bastille::API::FileContent; + +require Exporter; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw( +B_chkconfig_on +B_chkconfig_off +B_service_start +B_service_stop +B_service_restart +B_is_service_off +checkServiceOnLinux +remoteServiceCheck +remoteNISPlusServiceCheck +B_create_nsswitch_file +); +our @EXPORT = @EXPORT_OK; + + +####### +# &B_chkconfig_on and &B_chkconfig_off() are great for systems that didn't use +# a more modern init system. This is a bit of a problem on Fedora, though, +# which used upstart from Fedora 9 to Fedora 14, then switched to a new +# Red Hat-created system called systemd for Fedora 15 and 16 (so far). +# OpenSUSE also moved to systemd, starting with 12.1. Version 11.4 did not +# use systemd. +# It is also a problem on Ubuntu, starting at version 6.10, where they also +# used upstart. +##### + + + + +########################################################################### +# &B_chkconfig_on ($daemon_name) creates the symbolic links that are +# named in the "# chkconfig: ___ _ _ " portion of the init.d files. We +# need this utility, in place of the distro's chkconfig, because of both +# our need to add revert functionality and our need to harden distros that +# are not mounted on /. +# +# It uses the following global variables to find the links and the init +# scripts, respectively: +# +# &getGlobal('DIR', "rcd") -- directory where the rc_.d subdirs can be found +# &getGlobal('DIR', "initd") -- directory the rc_.d directories link to +# +# Here an example of where you might use this: +# +# You'd like to tell the system to run the firewall at boot: +# B_chkconfig_on("bastille-firewall") +# +########################################################################### + +# PW: Blech. Copied B_chkconfig_off() and changed a few things, +# then changed a few more things.... + +sub B_chkconfig_on { + + my $startup_script=$_[0]; + my $retval=1; + + my $chkconfig_line; + my ($runlevelinfo,@runlevels); + my ($start_order,$stop_order,$filetolink); + + &B_log("ACTION","# chkconfig_on enabling $startup_script\n"); + + # In Debian system there is no chkconfig script, run levels are checked + # one by one (jfs) + if (&GetDistro =~/^DB.*/) { + $filetolink = &getGlobal('DIR', "initd") . "/$startup_script"; + if (-x $filetolink) + { + foreach my $level ("0","1","2","3","4","5","6" ) { + my $link = ''; + $link = &getGlobal('DIR', "rcd") . "/rc" . "$level" . ".d/K50" . "$startup_script"; + $retval=symlink($filetolink,$link); + } + } + return $retval; + } + # + # On SUSE, chkconfig-based rc scripts have been replaced with a whole different + # system. chkconfig on SUSE is actually a shell script that does some stuff and then + # calls insserv, their replacement. + # + + if (&GetDistro =~ /^SE/) { + # only try to chkconfig on if init script is found + if ( -e (&getGlobal('DIR', "initd") . "/$startup_script") ) { + $chkconfig_line=&getGlobal('BIN','chkconfig'); + &B_System("$chkconfig_line $startup_script on", "$chkconfig_line $startup_script off"); + # chkconfig doesn't take affect until reboot, need to restart service also + B_service_restart("$startup_script"); + return 1; #success + } + return 0; #failure + } + + # + # Run through the init script looking for the chkconfig line... + # + $retval = open CHKCONFIG,&getGlobal('DIR', "initd") . "/$startup_script"; + unless ($retval) { + &B_log("ACTION","# Didn't chkconfig_on $startup_script because we couldn't open " . &getGlobal('DIR', "initd") . "/$startup_script\n"); + } + else { + + READ_LOOP: + while (my $line=<CHKCONFIG>) { + + # We're looking for lines like this one: + # # chkconfig: 2345 10 90 + # OR this + # # chkconfig: - 10 90 + + if ($line =~ /^#\s*chkconfig:\s*([-\d]+)\s*(\d+)\s*(\d+)/ ) { + $runlevelinfo = $1; + $start_order = $2; + $stop_order = $3; + # handle a run levels arg of '-' + if ( $runlevelinfo eq '-' ) { + &B_log("ACTION","chkconfig_on saw '-' for run levels for \"$startup_script\", is defaulting to levels 3,4,5\n"); + $runlevelinfo = '345'; + } + @runlevels = split(//,$runlevelinfo); + # make sure the orders have 2 digits + $start_order =~ s/^(\d)$/0$1/; + $stop_order =~ s/^(\d)$/0$1/; + last READ_LOOP; + } + } + close CHKCONFIG; + + # Do we have what we need? + if ( (scalar(@runlevels) < 1) || (! $start_order =~ /^\d{2}$/) || (! $stop_order =~ /^\d{2}$/) ) { + # problem + &B_log("ERROR","# B_chkconfig_on $startup_script failed -- no valid run level/start/stop info found\n"); + return(-1); + } + + # Now, run through creating symlinks... + &B_log("ACTION","# chkconfig_on will use run levels ".join(",",@runlevels)." for \"$startup_script\" with S order $start_order and K order $stop_order\n"); + + $retval=0; + # BUG: we really ought to readdir() on &getGlobal('DIR', "rcd") to get all levels + foreach my $level ( "0","1","2","3","4","5","6" ) { + my $link = ''; + # we make K links in run levels not specified in the chkconfig line + $link = &getGlobal('DIR', "rcd") . "/rc" . $level . ".d/K$stop_order" . $startup_script; + my $klink = $link; + # now we see if this is a specified run level; if so, make an S link + foreach my $markedlevel ( @runlevels ) { + if ( $level == $markedlevel) { + $link = &getGlobal('DIR', "rcd") . "/rc" . $level . ".d/S$start_order" . $startup_script; + } + } + my $target = &getGlobal('DIR', "initd") ."/" . $startup_script; + my $local_return; + + if ( (-e "$klink") && ($klink ne $link) ) { + # there's a K link, but this level needs an S link + unless ($GLOBAL_LOGONLY) { + $local_return = unlink("$klink"); + if ( ! $local_return ) { + # unlinking old, bad $klink failed + &B_log("ERROR","Unlinking $klink failed\n"); + } else { + &B_log("ACTION","Removed link $klink\n"); + # If we removed the link, add a link command to the revert file + &B_revert_log (&getGlobal('BIN','ln') . " -s $target $klink\n"); + } # close what to do if unlink works + } # if not GLOBAL_LOGONLY + } # if $klink exists and ne $link + + # OK, we've disposed of any old K links, make what we need + if ( (! ( -e "$link" )) && ($link ne '') ) { + # link doesn't exist and the start/stop number is OK; make it + unless ($GLOBAL_LOGONLY) { + # create the link + $local_return = &B_symlink($target,$link); + if ($local_return) { + $retval++; + &B_log("ACTION","Created link $link\n"); + } else { + &B_log("ERROR","Couldn't create $link when trying to chkconfig on $startup_script\n"); + } + } + + } # link doesn't exist + } # foreach level + + } + + if ($retval < @runlevels) { + $retval=0; + } + + $retval; + +} + + +########################################################################### +# &B_chkconfig_off ($daemon_name) deletes the symbolic links that are +# named in the "# chkconfig: ___ _ _ " portion of the init.d files. We +# need this utility, in place of the distro's chkconfig, because of both +# our need to add revert functionality and our need to harden distros that +# are not mounted on /. +# +# chkconfig allows for a REVERT of its work by writing to an executable +# file &getGlobal('BFILE', "removed-symlinks"). +# +# It uses the following global variables to find the links and the init +# scripts, respectively: +# +# &getGlobal('DIR', "rcd") -- directory where the rc_.d subdirs can be found +# &getGlobal('DIR', "initd") -- directory the rc_.d directories link to +# +# Here an example of where you might use this: +# +# You'd like to tell stop running sendmail in daemon mode on boot: +# B_chkconfig_off("sendmail") +# +########################################################################### + + + +sub B_chkconfig_off { + + my $startup_script=$_[0]; + my $retval=1; + + my $chkconfig_line; + my @runlevels; + my ($start_order,$stop_order,$filetolink); + + if (&GetDistro =~/^DB.*/) { + $filetolink = &getGlobal('DIR', "initd") . "/$startup_script"; + if (-x $filetolink) + { + # Three ways to do this in Debian: + # 1.- have the initd script set to 600 mode + # 2.- Remove the links in rcd (re-installing the package + # will break it) + # 3.- Use update-rc.d --remove (same as 2.) + # (jfs) + &B_chmod(0600,$filetolink); + $retval=6; + + # The second option + #foreach my $level ("0","1","2","3","4","5","6" ) { + #my $link = ''; + #$link = &getGlobal('DIR', "rcd") . "/rc" . "$level" . ".d/K50" . "$startup_script"; + #unlink($link); + #} + } + } + + # + # On SUSE, chkconfig-based rc scripts have been replaced with a whole different + # system. chkconfig on SUSE is actually a shell script that does some stuff and then + # calls insserv, their replacement. + # + elsif (&GetDistro =~ /^SE/) { + # only try to chkconfig off if init script is found + if ( -e (&getGlobal('DIR', "initd") . "/$startup_script") ) { + $chkconfig_line=&getGlobal('BIN','chkconfig'); + &B_System("$chkconfig_line $startup_script on", "$chkconfig_line $startup_script off"); + # chkconfig doesn't take affect until reboot, need to stop service + # since expectation is that the daemons are disabled even without a reboot + B_service_stop("$startup_script"); + return 1; #success + } + return 0; #failure + } + else { + + # Run through the init script looking for the chkconfig line... + + + $retval = open CHKCONFIG,&getGlobal('DIR', "initd") . "/$startup_script"; + unless ($retval) { + &B_log("ACTION","Didn't chkconfig_off $startup_script because we couldn't open " . &getGlobal('DIR', "initd") . "/$startup_script\n"); + } + else { + + READ_LOOP: + while (my $line=<CHKCONFIG>) { + + # We're looking for lines like this one: + # # chkconfig: 2345 10 90 + + if ($line =~ /^#\s*chkconfig:\s*([-\d]+)\s*(\d+)\s*(\d+)/ ) { + @runlevels=split //,$1; + $start_order=$2; + $stop_order=$3; + + + # Change single digit run levels to double digit -- otherwise, + # the alphabetic ordering chkconfig depends on fails. + if ($start_order =~ /^\d$/ ) { + $start_order = "0" . $start_order; + &B_log("ACTION","chkconfig_off converted start order to $start_order\n"); + } + if ($stop_order =~ /^\d$/ ) { + $stop_order = "0" . $stop_order; + &B_log("ACTION","chkconfig_off converted stop order to $stop_order\n"); + } + + last READ_LOOP; + } + } + close CHKCONFIG; + + # If we never found a chkconfig line, can we just run through all 5 + # rcX.d dirs from 1 to 5...? + + # unless ( $start_order and $stop_order ) { + # @runlevels=("1","2","3","4","5"); + # $start_order = "*"; $stop_order="*"; + # } + + # Now, run through removing symlinks... + + + + $retval=0; + + # Handle the special case that the run level specified is solely "-" + if ($runlevels[0] =~ /-/) { + @runlevels = ( "0","1","2","3","4","5","6" ); + } + + foreach my $level ( @runlevels ) { + my $link = &getGlobal('DIR', "rcd") . "/rc" . $level . ".d/S$start_order" . $startup_script; + my $new_link = &getGlobal('DIR', "rcd") . "/rc" . $level . ".d/K$stop_order" . $startup_script; + my $target = &getGlobal('DIR', "initd") ."/" . $startup_script; + my $local_return; + + + # Replace the S__ link in this level with a K__ link. + if ( -e $link ) { + unless ($GLOBAL_LOGONLY) { + $local_return=unlink $link; + if ($local_return) { + $local_return=symlink $target,$new_link; + unless ($local_return) { + &B_log("ERROR","Linking $target to $new_link failed.\n"); + } + } + else { # unlinking failed + &B_log("ERROR","Unlinking $link failed\n"); + } + + } + if ($local_return) { + $retval++; + &B_log("ACTION","Removed link $link\n"); + + # + # If we removed the link, add a link command to the revert file + # Write out the revert information for recreating the S__ + # symlink and deleting the K__ symlink. + &B_revert_log(&getGlobal('BIN',"ln") . " -s $target $link\n"); + &B_revert_log(&getGlobal('BIN',"rm") . " -f $new_link\n"); + } + else { + &B_log("ERROR","B_chkconfig_off $startup_script failed\n"); + } + + } + } # foreach + + } # else-unless + + } # else-DB + if ($retval < @runlevels) { + $retval=0; + } + + $retval; + +} + + +########################################################################### +# &B_service_start ($daemon_name) +# Starts service on RedHat/SUSE-based Linux distributions which have the +# service command: +# +# service $daemon_name start +# +# Other Linux distros that also support this method of starting +# services can be added to use this function. +# +# Here an example of where you might use this: +# +# You'd like to tell the system to start the vsftpd daemon: +# &B_service_start("vsftpd") +# +# Uses &B_System in HP_API.pm +# To match how the &B_System command works this method: +# returns 1 on success +# returns 0 on failure +########################################################################### + +sub B_service_start { + + my $daemon=$_[0]; + + if ( (&GetDistro !~ /^SE/) and (&GetDistro !~ /^RH/) and + (&GetDistro !~ /^RHFC/) and (&GetDistro !~ /^MN/) ) { + &B_log("ERROR","Tried to call service_start on a system lacking a service command! Internal Bastille error."); + return undef; + } + + # only start service if init script is found + if ( -e (&getGlobal('DIR', 'initd') . "/$daemon") ) { + &B_log("ACTION","# service_start enabling $daemon\n"); + + my $service_cmd=&getGlobal('BIN', 'service'); + if ($service_cmd) { + # Start the service, + # Also provide &B_System revert command + + return (&B_System("$service_cmd $daemon start", + "$service_cmd $daemon stop")); + } + } + + # init script not found, do not try to start, return failure + return 0; +} + +########################################################################### +# &B_service_stop ($daemon_name) +# Stops service on RedHat/SUSE-based Linux distributions which have the +# service command: +# +# service $daemon_name stop +# +# Other Linux distros that also support this method of starting +# services can be added to use this function. +# Stops service. +# +# +# Here an example of where you might use this: +# +# You'd like to tell the system to stop the vsftpd daemon: +# &B_service_stop("vsftpd") +# +# Uses &B_System in HP_API.pm +# To match how the &B_System command works this method: +# returns 1 on success +# returns 0 on failure +########################################################################### + +sub B_service_stop { + + my $daemon=$_[0]; + + if ( (&GetDistro !~ /^SE/) and (&GetDistro !~ /^RH/) and + (&GetDistro !~ /^RHFC/) and (&GetDistro !~ /^MN/) ) { + &B_log("ERROR","Tried to call service_stop on a system lacking a service command! Internal Bastille error."); + return undef; + } + + # only stop service if init script is found + if ( -e (&getGlobal('DIR', 'initd') . "/$daemon") ) { + &B_log("ACTION","# service_stop disabling $daemon\n"); + + my $service_cmd=&getGlobal('BIN', 'service'); + if ($service_cmd) { + + # Stop the service, + # Also provide &B_System revert command + + return (&B_System("$service_cmd $daemon stop", + "$service_cmd $daemon start")); + } + } + + # init script not found, do not try to stop, return failure + return 0; +} + + +########################################################################### +# &B_service_restart ($daemon_name) +# Restarts service on RedHat/SUSE-based Linux distributions which have the +# service command: +# +# service $daemon_name restart +# +# Other Linux distros that also support this method of starting +# services can be added to use this function. +# +# Here an example of where you might use this: +# +# You'd like to tell the system to restart the vsftpd daemon: +# &B_service_restart("vsftpd") +# +# Uses &B_System in HP_API.pm +# To match how the &B_System command works this method: +# returns 1 on success +# returns 0 on failure +########################################################################### + +sub B_service_restart { + + my $daemon=$_[0]; + + if ( (&GetDistro !~ /^SE/) and (&GetDistro !~ /^RH/) and + (&GetDistro !~ /^RHFC/) and (&GetDistro !~ /^MN/) ) { + &B_log("ERROR","Tried to call service_restart on a system lacking a service command! Internal Bastille error."); + return undef; + } + + # only restart service if init script is found + if ( -e (&getGlobal('DIR', 'initd') . "/$daemon") ) { + &B_log("ACTION","# service_restart re-enabling $daemon\n"); + + my $service_cmd=&getGlobal('BIN', 'service'); + if ($service_cmd) { + + # Restart the service + return (&B_System("$service_cmd $daemon restart", + "$service_cmd $daemon restart")); + } + } + + # init script not found, do not try to restart, return failure + return 0; +} + +########################################################################### +# &B_is_service_off($;$) +# +# Runs the specified test to determine whether or not the question should +# be answered. +# +# return values: +# NOTSECURE_CAN_CHANGE()/0: service is on +# SECURE_CANT_CHANGE()/1: service is off +# undef: test is not defined +########################################################################### + +sub B_is_service_off ($){ + my $service=$_[0]; + + if(&GetDistro =~ "^HP-UX"){ + #die "Why do I think I'm on HPUX?!\n"; + return &checkServiceOnHPUX($service); + } + elsif ( (&GetDistro =~ "^RH") || (&GetDistro =~ "^SE") ) { + return &checkServiceOnLinux($service); + } + else { + &B_log("DEBUG","B_is_service off called for unsupported OS"); + # not yet implemented for other distributions of Linux + # when GLOBAL_SERVICE, GLOBAL_SERVTYPE and GLOBAL_PROCESS are filled + # in for Linux, then + # at least inetd and inittab services should be similar to the above, + # whereas chkconfig would be used on some Linux distros to determine + # if non-inetd/inittab services are running at boot time. Looking at + # processes should be similar. + return undef; + } +} + +########################################################################### +# &checkServiceOnLinux($service); +# +# Checks if the given service is running on a Linux system. This is +# called by B_is_Service_Off(), which is the function that Bastille +# modules should call. +# +# Return values: +# NOTSECURE_CAN_CHANGE() if the service is on +# SECURE_CANT_CHANGE() if the service is off +# undef if the state of the service cannot be determined +# +########################################################################### +sub checkServiceOnLinux($) { + my $service=$_[0]; + + # get the list of parameters which could be used to initiate the service + # (could be in /etc/rc.d/rc?.d, /etc/inetd.conf, or /etc/inittab, so we + # check all of them) + + my @params = @{ &getGlobal('SERVICE', $service) }; + my $chkconfig = &getGlobal('BIN', 'chkconfig'); + my $grep = &getGlobal('BIN', 'grep'); + my $inittab = &getGlobal('FILE', 'inittab'); + my $serviceType = &getGlobal('SERVTYPE', $service);; + + # A kludge to get things running because &getGlobal('SERVICE' doesn't + # return the expected values. + @params = (); + push (@params, $service); + + foreach my $param (@params) { + &B_log("DEBUG","Checking to see if service $service is off.\n"); + + if ($serviceType =~ /rc/) { + my $on = &B_Backtick("$chkconfig --list $param 2>&1"); + if ($on =~ /^$param:\s+unknown/) { + # This service isn't installed on the system + return NOT_INSTALLED(); + } + if ($on =~ /^error reading information on service $param: No such file or directory/) { + # This service isn't installed on the system + return NOT_INSTALLED(); + } + if ($on =~ /^error/) { + # This probably + &B_log("DEBUG","chkconfig returned: $param=$on\n"); + return undef; + } + $on =~ s/^$param\s+//; # remove the service name and spaces + $on =~ s/[0-6]:off\s*//g; # remove any runlevel:off entries + $on =~ s/:on\s*//g; # remove the :on from the runlevels + # what remains is a list of runlevels in which the service is on, + # or a null string if it is never turned on + chomp $on; # newline should be gone already (\s) + &B_log("DEBUG","chkconfig returned: $param=$on\n"); + + if ($on =~ /^\d+$/) { + # service is not off + ########################### BREAK out, don't skip question + return NOTSECURE_CAN_CHANGE(); + } + } + elsif ($serviceType =~ /inet/) { + my $on = &B_Backtick("$chkconfig --list $param 2>&1"); + if ($on =~ /^$param:\s+unknown/) { + # This service isn't installed on the system + return NOT_INSTALLED(); + } + if ($on =~ /^error reading information on service $param: No such file or directory/) { + # This service isn't installed on the system + return NOT_INSTALLED(); + } + if ($on =~ /^error/ ) { + # Something else is wrong? + # return undef + return undef; + } + if ($on =~ tr/\n// > 1) { + $on =~ s/^xinetd.+\n//; + } + $on =~ s/^\s*$param:?\s+//; # remove the service name and spaces + chomp $on; # newline should be gone already (\s) + &B_log("DEBUG","chkconfig returned: $param=$on\n"); + + if ($on =~ /^on$/) { + # service is not off + ########################### BREAK out, don't skip question + return NOTSECURE_CAN_CHANGE(); + } + } + else { + # perhaps the service is started by inittab + my $inittabline = &B_Backtick("$grep -E '^[^#].{0,3}:.*:.+:.*$param' $inittab"); + if ($inittabline =~ /.+/) { # . matches anything except newlines + # service is not off + &B_log("DEBUG","Checking inittab; found $inittabline\n"); + ########################### BREAK out, don't skip question + return NOTSECURE_CAN_CHANGE(); + } + } + } # foreach my $param + + + # boot-time parameters are not set; check processes + # Note the checkProcsforService returns INCONSISTENT() if a process is found + # assuming the checks above + return &checkProcsForService($service); +} + +1; + + diff --git a/meta-security/recipes-security/bastille/files/accept_os_flag_in_backend.patch b/meta-security/recipes-security/bastille/files/accept_os_flag_in_backend.patch new file mode 100644 index 000000000..4a438e49f --- /dev/null +++ b/meta-security/recipes-security/bastille/files/accept_os_flag_in_backend.patch @@ -0,0 +1,34 @@ +Upstream Status: Inappropriate [No upstream maintenance] + +Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> + +--- + +Index: Bastille/BastilleBackEnd +=================================================================== +--- Bastille.orig/BastilleBackEnd 2013-08-21 12:40:54.000000000 -0400 ++++ Bastille/BastilleBackEnd 2013-08-21 12:43:21.895950001 -0400 +@@ -52,11 +52,13 @@ + my $force = 0; + my $debug = 0; + my $alternate_config=undef; ++my $os_version=undef; + + if( Getopt::Long::GetOptions( "n" => \$nodisclaim, + "v" => \$verbose, + "force" => \$force, + "f=s" => \$alternate_config, ++ "os=s" => \$os_version, + "debug" => \$debug) ) { + $error = 0; # no parse error + +@@ -66,7 +68,8 @@ + + &setOptions( + debug => $debug, +- verbose => $verbose); ++ verbose => $verbose, ++ os => $os_version); + &ConfigureForDistro; + + if ( $error ) { # GetOptions couldn't parse all of the args diff --git a/meta-security/recipes-security/bastille/files/allow_os_with_assess.patch b/meta-security/recipes-security/bastille/files/allow_os_with_assess.patch new file mode 100644 index 000000000..e112f907b --- /dev/null +++ b/meta-security/recipes-security/bastille/files/allow_os_with_assess.patch @@ -0,0 +1,43 @@ +Upstream Status: Inappropriate [No upstream maintenance] + +Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> + +--- + +Index: Bastille/bin/bastille +=================================================================== +--- Bastille.orig/bin/bastille 2013-08-21 08:59:06.647950000 -0400 ++++ Bastille/bin/bastille 2013-08-21 15:55:53.193631711 -0400 +@@ -195,7 +195,6 @@ + systemFileLocations + + isAssessing='no' +-nonXArg='no' + + if [ $PERL_V_MAJ -eq $MIN_V_MAJ -a $PERL_V_MIN -lt $MIN_V_MIN -o $PERL_V_MAJ -lt $MIN_V_MAJ ]; then # invalid Perl + printErr +@@ -316,12 +315,10 @@ + '--os') + options_left="$options_left --os" + optarg='yes' +- nonXArg='yes' + ;; + '-f') + options_left="$options_left -f" + optarg='yes' +- nonXArg='yes' + ;; + # Non-exclusive (undocumented and unsupported) options follow: + # There is no validity/combination checking done with these. +@@ -345,11 +342,6 @@ + fi + done + +-#Detect case where -f or --os attempted use with --assess +- if [ \( x$nonXArg = xyes \) -a \( x$isAssessing = xyes \) ]; then +- printUsage +- exit 2 +- fi + + # We have a valid version of perl! Verify that all the required + # modules can be found. diff --git a/meta-security/recipes-security/bastille/files/call_output_config.patch b/meta-security/recipes-security/bastille/files/call_output_config.patch new file mode 100644 index 000000000..1e898b148 --- /dev/null +++ b/meta-security/recipes-security/bastille/files/call_output_config.patch @@ -0,0 +1,19 @@ +Upstream Status: Inappropriate [No upstream maintenance] + +Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> + +--- + +Index: Bastille/Bastille_Curses.pm +=================================================================== +--- Bastille.orig/Bastille_Curses.pm 2013-08-21 08:58:53.899950000 -0400 ++++ Bastille/Bastille_Curses.pm 2013-08-21 09:20:20.295950005 -0400 +@@ -84,7 +84,7 @@ + } + + # Output answers to the script and display +- &checkAndSaveConfig(&getGlobal('BFILE', "config")); ++ &outputConfig; + + # Run Bastille + diff --git a/meta-security/recipes-security/bastille/files/config b/meta-security/recipes-security/bastille/files/config new file mode 100755 index 000000000..9e5e20658 --- /dev/null +++ b/meta-security/recipes-security/bastille/files/config @@ -0,0 +1,106 @@ +# Q: Would you like to enforce password aging? [Y] +AccountSecurity.passwdage="Y" +# Q: Should Bastille disable clear-text r-protocols that use IP-based authentication? [Y] +AccountSecurity.protectrhost="Y" +# Q: Should we disallow root login on tty's 1-6? [N] +AccountSecurity.rootttylogins="Y" +# Q: What umask would you like to set for users on the system? [077] +AccountSecurity.umask="077" +# Q: Do you want to set the default umask? [Y] +AccountSecurity.umaskyn="Y" +# Q: Would you like to deactivate the Apache web server? [Y] +Apache.apacheoff="Y" +# Q: Would you like to password protect single-user mode? [Y] +BootSecurity.passsum="Y" +# Q: Should we restrict console access to a small group of user accounts? [N] +ConfigureMiscPAM.consolelogin="Y" +# Q: Which accounts should be able to login at console? [root] +ConfigureMiscPAM.consolelogin_accounts="root" +# Q: Would you like to put limits on system resource usage? [N] +ConfigureMiscPAM.limitsconf="Y" +# Q: Would you like to set more restrictive permissions on the administration utilities? [N] +FilePermissions.generalperms_1_1="Y" +# Q: Would you like to disable SUID status for mount/umount? +FilePermissions.suidmount="Y" +# Q: Would you like to disable SUID status for ping? [Y] +FilePermissions.suidping="Y" +# Q: Would you like to disable SUID status for traceroute? [Y] +FilePermissions.suidtrace="Y" +# Q: Do you need the advanced networking options? +Firewall.ip_advnetwork="Y" +# Q: Should Bastille run the firewall and enable it at boot time? [N] +Firewall.ip_enable_firewall="Y" +# Q: Would you like to run the packet filtering script? [N] +Firewall.ip_intro="Y" +# Q: Interfaces for DHCP queries: [ ] +Firewall.ip_s_dhcpiface=" " +# Q: DNS servers: [0.0.0.0/0] +Firewall.ip_s_dns="10.184.9.1" +# Q: ICMP allowed types: [destination-unreachable echo-reply time-exceeded] +Firewall.ip_s_icmpallowed="destination-unreachable echo-reply time-exceeded" +# Q: ICMP services to audit: [ ] +Firewall.ip_s_icmpaudit=" " +# Q: ICMP types to disallow outbound: [destination-unreachable time-exceeded] +Firewall.ip_s_icmpout="destination-unreachable time-exceeded" +# Q: Internal interfaces: [ ] +Firewall.ip_s_internaliface=" " +# Q: TCP service names or port numbers to allow on private interfaces: [ ] +Firewall.ip_s_internaltcp=" " +# Q: UDP service names or port numbers to allow on private interfaces: [ ] +Firewall.ip_s_internaludp=" " +# Q: Masqueraded networks: [ ] +Firewall.ip_s_ipmasq=" " +# Q: Kernel modules to masquerade: [ftp raudio vdolive] +Firewall.ip_s_kernelmasq="ftp raudio vdolive" +# Q: NTP servers to query: [ ] +Firewall.ip_s_ntpsrv=" " +# Q: Force passive mode? [N] +Firewall.ip_s_passiveftp="N" +# Q: Public interfaces: [eth+ ppp+ slip+] +Firewall.ip_s_publiciface="eth+ ppp+ slip+" +# Q: TCP service names or port numbers to allow on public interfaces:[ ] +Firewall.ip_s_publictcp=" " +# Q: UDP service names or port numbers to allow on public interfaces:[ ] +Firewall.ip_s_publicudp=" " +# Q: Reject method: [DENY] +Firewall.ip_s_rejectmethod="DENY" +# Q: Enable source address verification? [Y] +Firewall.ip_s_srcaddr="Y" +# Q: TCP services to audit: [telnet ftp imap pop3 finger sunrpc exec login linuxconf ssh] +Firewall.ip_s_tcpaudit="telnet ftp imap pop3 finger sunrpc exec login linuxconf ssh" +# Q: TCP services to block: [2049 2065:2090 6000:6020 7100] +Firewall.ip_s_tcpblock="2049 2065:2090 6000:6020 7100" +# Q: Trusted interface names: [lo] +Firewall.ip_s_trustiface="lo" +# Q: UDP services to audit: [31337] +Firewall.ip_s_udpaudit="31337" +# Q: UDP services to block: [2049 6770] +Firewall.ip_s_udpblock="2049 6770" +# Q: Would you like to add additional logging? [Y] +Logging.morelogging="Y" +# Q: Would you like to set up process accounting? [N] +Logging.pacct="N" +# Q: Do you have a remote logging host? [N] +Logging.remotelog="N" +# Q: Would you like to disable acpid and/or apmd? [Y] +MiscellaneousDaemons.apmd="Y" +# Q: Would you like to deactivate NFS and Samba? [Y] +MiscellaneousDaemons.remotefs="Y" +# Q: Would you like to disable printing? [N] +Printing.printing="Y" +# Q: Would you like to disable printing? [N] +Printing.printing_cups="Y" +# Q: Would you like to display "Authorized Use" messages at log-in time? [Y] +SecureInetd.banners="Y" +# Q: Should Bastille ensure inetd's FTP service does not run on this system? [y] +SecureInetd.deactivate_ftp="Y" +# Q: Should Bastille ensure the telnet service does not run on this system? [y] +SecureInetd.deactivate_telnet="Y" +# Q: Who is responsible for granting authorization to use this machine? +SecureInetd.owner="its owner" +# Q: Would you like to set a default-deny on TCP Wrappers and xinetd? [N] +SecureInetd.tcpd_default_deny="Y" +# Q: Do you want to stop sendmail from running in daemon mode? [Y] +Sendmail.sendmaildaemon="Y" +# Q: Would you like to install TMPDIR/TMP scripts? [N] +TMPDIR.tmpdir="N" diff --git a/meta-security/recipes-security/bastille/files/do_not_apply_config.patch b/meta-security/recipes-security/bastille/files/do_not_apply_config.patch new file mode 100644 index 000000000..574aa9803 --- /dev/null +++ b/meta-security/recipes-security/bastille/files/do_not_apply_config.patch @@ -0,0 +1,40 @@ +Upstream Status: Inappropriate [No upstream maintenance] + +Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> + +--- + +Index: Bastille/Bastille_Curses.pm +=================================================================== +--- Bastille.orig/Bastille_Curses.pm 2013-08-27 16:43:39.130959000 -0400 ++++ Bastille/Bastille_Curses.pm 2013-08-27 16:43:39.794959000 -0400 +@@ -83,11 +83,6 @@ + # Output answers to the script and display + &outputConfig; + +- # Run Bastille +- +- &Run_Bastille_with_Config; +- +- + # Display Credits + + open CREDITS,"/usr/share/Bastille/Credits"; +Index: Bastille/InteractiveBastille +=================================================================== +--- Bastille.orig/InteractiveBastille 2013-08-27 16:43:39.434959000 -0400 ++++ Bastille/InteractiveBastille 2013-08-27 17:18:55.758959000 -0400 +@@ -531,10 +531,10 @@ + " Please address bug reports and suggestions to jay\@bastille-linux.org\n" . + "\n"; + +- $InterfaceEndScreenDescription = "We will now implement the choices you have made here.\n\n" . ++ $InterfaceEndScreenDescription = "We will now record the choices you have made here.\n\n" . + "Answer NO if you want to go back and make changes!\n"; +- $InterfaceEndScreenQuestion = "Are you finished answering the questions, i.e. may we make the changes?"; +- $InterfaceEndScreenNoEpilogue = "Please use Back/Next buttons to move among the questions you wish to\nchange.\n\nChoose YES on this question later to implement your choices.\n"; ++ $InterfaceEndScreenQuestion = "Are you finished answering the questions, i.e. may we record the answers and exit?"; ++ $InterfaceEndScreenNoEpilogue = "Please use Back/Next buttons to move among the questions you wish to\nchange.\n\nChoose YES on this question later to record your choices.\n"; + require Bastille_Curses; + } elsif ($GLOBAL_AUDITONLY) { + diff --git a/meta-security/recipes-security/bastille/files/edit_usage_message.patch b/meta-security/recipes-security/bastille/files/edit_usage_message.patch new file mode 100644 index 000000000..72cdc2ff9 --- /dev/null +++ b/meta-security/recipes-security/bastille/files/edit_usage_message.patch @@ -0,0 +1,32 @@ +Upstream Status: Inappropriate [No upstream maintenance] + +Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> + +--- + +Index: Bastille/bin/bastille +=================================================================== +--- Bastille.orig/bin/bastille 2013-08-25 14:16:35.614779001 -0400 ++++ Bastille/bin/bastille 2013-08-25 14:16:38.674779000 -0400 +@@ -60,7 +60,7 @@ + printUsage () { + cat >&2 << EOF + $ERRSPACES Usage: bastille [ -b | -c | -x ] [ --os <version>] [ -f <alternate config> ] +-$ERRSPACES bastille [-r | -l | -h | --assess | --assessnobrowser ] ++$ERRSPACES bastille [-r | -l | -h | --assess | --assessnobrowser ] [ --os <version> ] + $ERRSPACES -b : use a saved config file to apply changes + $ERRSPACES directly to system + $ERRSPACES -c : use the Curses (non-X11) GUI, not available on HP-UX +Index: Bastille/Bastille/API.pm +=================================================================== +--- Bastille.orig/Bastille/API.pm 2013-08-25 08:15:40.266779002 -0400 ++++ Bastille/Bastille/API.pm 2013-08-25 14:18:22.750778811 -0400 +@@ -206,7 +206,7 @@ + #options before interactive or Bastille runs, so this check is often redundant + $GLOBAL_ERROR{"usage"}="\n". + "$spc Usage: bastille [ -b | -c | -x ] [ --os <version> ] [ -f <alternate config> ]\n". +- "$spc bastille [ -r | --assess | --assessnobowser ]\n\n". ++ "$spc bastille [ -r | --assess | --assessnobowser ] [ --os <version> ]\n\n". + "$spc --assess : check status of system and report in browser\n". + "$spc --assessnobrowser : check status of system and list report locations\n". + "$spc -b : use a saved config file to apply changes\n". diff --git a/meta-security/recipes-security/bastille/files/find_existing_config.patch b/meta-security/recipes-security/bastille/files/find_existing_config.patch new file mode 100644 index 000000000..c0758752b --- /dev/null +++ b/meta-security/recipes-security/bastille/files/find_existing_config.patch @@ -0,0 +1,64 @@ +Upstream Status: Inappropriate [No upstream maintenance] + +Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> + +--- + +Index: Bastille/bin/bastille +=================================================================== +--- Bastille.orig/bin/bastille 2013-06-20 14:58:01.065796000 -0400 ++++ Bastille/bin/bastille 2013-08-20 15:16:18.472378000 -0400 +@@ -102,8 +102,9 @@ + # defines OS specific file locations based on uname + systemFileLocations + ++ config_files=`find $config_repository -type f -name \*config 2>/dev/null` ++ + if [ -f $last_config ]; then +- config_files=`find $config_repository -type f -name \*config 2>/dev/null` + for config_cursor in `echo $config_files` + do + if /usr/bin/diff $last_config $config_cursor >/dev/null 2>&1 +@@ -112,8 +113,8 @@ + fi + done + if [ -n "$match" ]; then +- echo "The last bastille run corresponds to the following profiles:" +- echo "$match" ++ printf "The last Bastille run corresponds to the following profiles:\n" ++ printf "$match" + else + cat >&2 << EOF + NOTE: The last config file applied, +@@ -122,18 +123,28 @@ + $ERRSPACES $config_repository. + $ERRSPACES This probably means that Bastille was last run interactively and + $ERRSPACES changes were made to the config file, but they have not yet been +-$ERRSPACES applied, or that the source config file was moved. If you do have pending ++$ERRSPACES applied, or that the source config file was moved. If you do have pending + $ERRSPACES changes in a config file, you can apply them by running + $ERRSPACES 'bastille -b -f <config file>.' + EOF + + fi + else +- echo "NOTE: The system is in its pre-bastilled state.\n" ++ for config_cursor in `echo $config_files` ++ do ++ match="$match $config_cursor\n" ++ done ++ if [ -n "$match" ]; then ++ printf "The following Bastille profiles were located:\n" ++ printf "$match" ++ else ++ printf "No Bastille profiles were located.\n" ++ fi ++ printf "No log files of profiles from previous executions of Bastille have been found. It is likely that Bastille has not been run on this machine.\n" + fi +- + } + ++ + # First, make sure we're root + if [ `PATH="/usr/bin:/bin"; id -u` -ne 0 ]; then + echo "ERROR: Bastille must be run as root user" >&2 diff --git a/meta-security/recipes-security/bastille/files/fix_missing_use_directives.patch b/meta-security/recipes-security/bastille/files/fix_missing_use_directives.patch new file mode 100644 index 000000000..05f145a3e --- /dev/null +++ b/meta-security/recipes-security/bastille/files/fix_missing_use_directives.patch @@ -0,0 +1,54 @@ +Upstream Status: Inappropriate [No upstream maintenance] + +Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> + +--- + +Index: Bastille/Bastille/Firewall.pm +=================================================================== +--- Bastille.orig/Bastille/Firewall.pm 2008-09-14 19:56:54.000000000 -0400 ++++ Bastille/Bastille/Firewall.pm 2013-08-20 16:28:44.588378000 -0400 +@@ -21,6 +21,7 @@ + package Bastille::Firewall; + + use Bastille::API; ++use Bastille::API::AccountPermission; + use Bastille::API::FileContent; + use Bastille::API::ServiceAdmin; + +Index: Bastille/Bastille/SecureInetd.pm +=================================================================== +--- Bastille.orig/Bastille/SecureInetd.pm 2008-09-14 19:56:58.000000000 -0400 ++++ Bastille/Bastille/SecureInetd.pm 2013-08-20 16:45:02.252378001 -0400 +@@ -12,6 +12,7 @@ + use lib "/usr/lib"; + + use Bastille::API; ++use Bastille::API::AccountPermission; + use Bastille::API::HPSpecific; + use Bastille::API::ServiceAdmin; + use Bastille::API::FileContent; +Index: Bastille/Bastille/ConfigureMiscPAM.pm +=================================================================== +--- Bastille.orig/Bastille/ConfigureMiscPAM.pm 2005-09-12 23:47:28.000000000 -0400 ++++ Bastille/Bastille/ConfigureMiscPAM.pm 2013-08-20 18:36:07.340378001 -0400 +@@ -5,6 +5,7 @@ + use lib "/usr/lib"; + + use Bastille::API; ++use Bastille::API::FileContent; + + # To DO: + # +Index: Bastille/Bastille/Printing.pm +=================================================================== +--- Bastille.orig/Bastille/Printing.pm 2008-09-14 19:56:58.000000000 -0400 ++++ Bastille/Bastille/Printing.pm 2013-08-20 19:05:01.532378002 -0400 +@@ -5,6 +5,7 @@ + use lib "/usr/lib"; + + use Bastille::API; ++use Bastille::API::AccountPermission; + use Bastille::API::HPSpecific; + use Bastille::API::ServiceAdmin; + use Bastille::API::FileContent; diff --git a/meta-security/recipes-security/bastille/files/fix_number_of_modules.patch b/meta-security/recipes-security/bastille/files/fix_number_of_modules.patch new file mode 100644 index 000000000..743e54920 --- /dev/null +++ b/meta-security/recipes-security/bastille/files/fix_number_of_modules.patch @@ -0,0 +1,38 @@ +Upstream Status: Inappropriate [No upstream maintenance] + +Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> + +--- + +Index: Bastille/Bastille_Curses.pm +=================================================================== +--- Bastille.orig/Bastille_Curses.pm 2013-08-24 18:21:54.445288000 -0400 ++++ Bastille/Bastille_Curses.pm 2013-08-24 18:29:16.981288000 -0400 +@@ -36,9 +36,6 @@ + use Curses; + use Curses::Widgets; + +- # Number_Modules is the number of modules loaded in by Load_Questions +- $Number_Modules=0; +- + # + # Highlighted button is the button currently chosen in the button bar + # We preserve this from question to question... +@@ -397,7 +394,7 @@ + my $title; + + if ($module) { +- $title=$module . " of $Number_Modules"; ++ $title=$module; + } + + txt_field( 'window' => $window, +@@ -488,7 +485,7 @@ + my $title; + + if ($module) { +- $title=$module . " of $Number_Modules"; ++ $title=$module; + } + + noecho; diff --git a/meta-security/recipes-security/bastille/files/fix_version_parse.patch b/meta-security/recipes-security/bastille/files/fix_version_parse.patch new file mode 100644 index 000000000..5923c0408 --- /dev/null +++ b/meta-security/recipes-security/bastille/files/fix_version_parse.patch @@ -0,0 +1,27 @@ +Upstream Status: Inappropriate [No upstream maintenance] + +Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> + +--- + +Index: Bastille/bin/bastille +=================================================================== +--- Bastille.orig/bin/bastille ++++ Bastille/bin/bastille +@@ -162,11 +162,12 @@ fi + # We check that the version is at least the minimum + + PERL_VERSION=`${CURRENT_PERL_PATH}/perl -version | +- head -2 | # the second line contains the version ++ head -n 2 | # the second line contains the version + tr " " "\n" | # split words into separate lines +- sed -e "s/^v//" | # to get rid of the v in v5.6.0 +- grep "^[1-9]\." | # find a "word" that starts with number dot +- sed -e "s/_/./"` # substitute _patchlevel with .patchlevel ++ grep "^(v" | # find a "word" that starts with '(v' ++ sed -e "s/^(v//" -e "s/)//" -e "s/_/./"` ++ # to get rid of the (v in v5.6.0 ++ # substitute _patchlevel with .patchlevel + # (used in 5.005_03 and prior) + + # everything before the first . diff --git a/meta-security/recipes-security/bastille/files/fixed_defined_warnings.patch b/meta-security/recipes-security/bastille/files/fixed_defined_warnings.patch new file mode 100644 index 000000000..e7996e380 --- /dev/null +++ b/meta-security/recipes-security/bastille/files/fixed_defined_warnings.patch @@ -0,0 +1,65 @@ +From c59b84ca3bda8e4244d47901b6966f28dd675434 Mon Sep 17 00:00:00 2001 +From: Andrei Dinu <andrei.adrianx.dinu@intel.com> +Date: Thu, 23 May 2013 15:12:23 +0300 +Subject: [PATCH] added yocto-standard to bastille + +In order to make Bastille functional and avoid errors +regarding distros, if not any given distro is identified, +yocto-standard distro is added to the distro variable +in Bastille. + +Fixed also some warnings regarding defined statements +in API.pm. + +Upstream Status: Inappropriate [No upstream maintenance] + +Signed-off-by: Andrei Dinu <andrei.adrianx.dinu@intel.com> + +Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> + +--- + Bastille/API.pm | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +Index: Bastille/Bastille/API.pm +=================================================================== +--- Bastille.orig/Bastille/API.pm 2008-09-14 19:56:53.000000000 -0400 ++++ Bastille/Bastille/API.pm 2013-08-21 08:55:26.715950001 -0400 +@@ -445,8 +445,8 @@ + $release=`/usr/bin/uname -sr`; + } + else { +- print STDERR "$err Could not determine operating system version!\n"; +- $distro="unknown"; ++ print STDERR "$err Could not determine operating system version!\n"; ++ $distro="unknown" + } + + # Figure out what kind of system we're on. +@@ -1284,7 +1284,7 @@ + + my $sumFile = &getGlobal('BFILE',"sum.csv"); + +- if ( defined %GLOBAL_SUM ) { ++ if ( %GLOBAL_SUM ) { + + open( SUM, "> $sumFile") or &B_log("ERROR","Unable to open $sumFile for write.\n$!\n"); + +@@ -1318,7 +1318,7 @@ + my $file = $_[0]; + my $cksum = &getGlobal('BIN',"cksum"); + +- if (not(defined(%GLOBAL_SUM))) { ++ if (not(%GLOBAL_SUM)) { + &B_read_sums; + } + +@@ -1375,7 +1375,7 @@ + sub B_isFileinSumDB($) { + my $file = $_[0]; + +- if (not(defined(%GLOBAL_SUM))) { ++ if (not(%GLOBAL_SUM)) { + &B_log("DEBUG","Reading in DB from B_isFileinSumDB"); + &B_read_sums; + } diff --git a/meta-security/recipes-security/bastille/files/organize_distro_discovery.patch b/meta-security/recipes-security/bastille/files/organize_distro_discovery.patch new file mode 100644 index 000000000..d64d1e26e --- /dev/null +++ b/meta-security/recipes-security/bastille/files/organize_distro_discovery.patch @@ -0,0 +1,476 @@ +Upstream Status: Inappropriate [No upstream maintenance] + +Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> + +--- + +Index: Bastille/Bastille/API.pm +=================================================================== +--- Bastille.orig/Bastille/API.pm 2013-08-22 04:32:38.269968002 -0400 ++++ Bastille/Bastille/API.pm 2013-08-22 11:29:53.137968002 -0400 +@@ -141,7 +141,7 @@ + checkProcsForService + + +- $GLOBAL_OS $GLOBAL_ACTUAL_OS $CLI ++ $CLI + $GLOBAL_LOGONLY $GLOBAL_VERBOSE $GLOBAL_DEBUG $GLOBAL_AUDITONLY $GLOBAL_AUDIT_NO_BROWSER $errorFlag + %GLOBAL_BIN %GLOBAL_DIR %GLOBAL_FILE + %GLOBAL_BDIR %GLOBAL_BFILE +@@ -198,7 +198,7 @@ + my $err ="ERROR: "; + my $spc =" "; + my $GLOBAL_OS="None"; +-my $GLOBAL_ACTUAL_OS="None"; ++my $GLOBAL_INFERRED_OS="None"; + my %GLOBAL_SUMS=(); + my $CLI=''; + +@@ -306,7 +306,7 @@ + + ########################################################################### + # +-# GetDistro checks to see if the target is a known distribution and reports ++# InferDistro checks to see if the target is a known distribution and reports + # said distribution. + # + # This is used throughout the script, but also by ConfigureForDistro. +@@ -314,205 +314,194 @@ + # + ########################################################################### + +-sub GetDistro() { ++sub InferDistro() { + + my ($release,$distro); + +- # Only read files for the distro once. +- # if the --os option was used then +- if ($GLOBAL_OS eq "None") { +- if ( -e "/etc/mandrake-release" ) { +- open(MANDRAKE_RELEASE,"/etc/mandrake-release"); +- $release=<MANDRAKE_RELEASE>; +- +- if ( ($release =~ /^Mandrake Linux release (\d+\.\d+\w*)/) or ($release =~ /^Linux Mandrake release (\d+\.\d+\w*)/) ) { +- $distro="MN$1"; +- } +- elsif ( $release =~ /^Mandrakelinux release (\d+\.\d+)\b/ ) { +- $distro="MN$1"; +- } +- else { +- print STDERR "$err Couldn't determine Mandrake/Mandriva version! Setting to 10.1!\n"; +- $distro="MN10.1"; +- } +- +- close(MANDRAKE_RELEASE); +- } +- elsif ( -e "/etc/immunix-release" ) { +- open(IMMUNIX_RELEASE,"/etc/immunix-release"); +- $release=<IMMUNIX_RELEASE>; +- unless ($release =~ /^Immunix Linux release (\d+\.\d+\w*)/) { +- print STDERR "$err Couldn't determine Immunix version! Setting to 6.2!\n"; +- $distro="RH6.2"; +- } +- else { +- $distro="RH$1"; +- } +- close(*IMMUNIX_RELEASE); +- } +- elsif ( -e '/etc/fedora-release' ) { +- open(FEDORA_RELEASE,'/etc/fedora-release'); +- $release=<FEDORA_RELEASE>; +- close FEDORA_RELEASE; +- if ($release =~ /^Fedora Core release (\d+\.?\d*)/) { +- $distro = "RHFC$1"; +- } +- elsif ($release =~ /^Fedora release (\d+\.?\d*)/) { +- $distro = "RHFC$1"; +- } +- else { +- print STDERR "$err Could not determine Fedora version! Setting to Fedora Core 8\n"; +- $distro='RHFC8'; +- } ++ if ( -e "/etc/mandrake-release" ) { ++ open(MANDRAKE_RELEASE,"/etc/mandrake-release"); ++ $release=<MANDRAKE_RELEASE>; ++ ++ if ( ($release =~ /^Mandrake Linux release (\d+\.\d+\w*)/) or ($release =~ /^Linux Mandrake release (\d+\.\d+\w*)/) ) { ++ $distro="MN$1"; ++ } ++ elsif ( $release =~ /^Mandrakelinux release (\d+\.\d+)\b/ ) { ++ $distro="MN$1"; ++ } ++ else { ++ print STDERR "$err Could not infer Mandrake/Mandriva version! Setting to 10.1!\n"; ++ $distro="MN10.1"; ++ } ++ ++ close(MANDRAKE_RELEASE); ++ } ++ elsif ( -e "/etc/immunix-release" ) { ++ open(IMMUNIX_RELEASE,"/etc/immunix-release"); ++ $release=<IMMUNIX_RELEASE>; ++ unless ($release =~ /^Immunix Linux release (\d+\.\d+\w*)/) { ++ print STDERR "$err Could not infer Immunix version! Setting to 6.2!\n"; ++ $distro="RH6.2"; ++ } ++ else { ++ $distro="RH$1"; + } +- elsif ( -e "/etc/redhat-release" ) { +- open(*REDHAT_RELEASE,"/etc/redhat-release"); +- $release=<REDHAT_RELEASE>; +- if ($release =~ /^Red Hat Linux release (\d+\.?\d*\w*)/) { +- $distro="RH$1"; +- } +- elsif ($release =~ /^Red Hat Linux .+ release (\d+)\.?\d*([AEW]S)/) { +- $distro="RHEL$1$2"; +- } +- elsif ($release =~ /^Red Hat Enterprise Linux ([AEW]S) release (\d+)/) { +- $distro="RHEL$2$1"; ++ close(*IMMUNIX_RELEASE); ++ } ++ elsif ( -e '/etc/fedora-release' ) { ++ open(FEDORA_RELEASE,'/etc/fedora-release'); ++ $release=<FEDORA_RELEASE>; ++ close FEDORA_RELEASE; ++ if ($release =~ /^Fedora Core release (\d+\.?\d*)/) { ++ $distro = "RHFC$1"; ++ } ++ elsif ($release =~ /^Fedora release (\d+\.?\d*)/) { ++ $distro = "RHFC$1"; ++ } ++ else { ++ print STDERR "$err Could not infer Fedora version! Setting to Fedora Core 8\n"; ++ $distro='RHFC8'; ++ } ++ } ++ elsif ( -e "/etc/redhat-release" ) { ++ open(*REDHAT_RELEASE,"/etc/redhat-release"); ++ $release=<REDHAT_RELEASE>; ++ if ($release =~ /^Red Hat Linux release (\d+\.?\d*\w*)/) { ++ $distro="RH$1"; ++ } ++ elsif ($release =~ /^Red Hat Linux .+ release (\d+)\.?\d*([AEW]S)/) { ++ $distro="RHEL$1$2"; ++ } ++ elsif ($release =~ /^Red Hat Enterprise Linux ([AEW]S) release (\d+)/) { ++ $distro="RHEL$2$1"; ++ } ++ elsif ($release =~ /^CentOS release (\d+\.\d+)/) { ++ my $version = $1; ++ if ($version =~ /^4\./) { ++ $distro='RHEL4AS'; + } +- elsif ($release =~ /^CentOS release (\d+\.\d+)/) { +- my $version = $1; +- if ($version =~ /^4\./) { +- $distro='RHEL4AS'; +- } +- elsif ($version =~ /^3\./) { +- $distro='RHEL3AS'; +- } +- else { +- print STDERR "$err Could not determine CentOS version! Setting to Red Hat Enterprise 4 AS.\n"; +- $distro='RHEL4AS'; +- } +- } +- else { +- # JJB/HP - Should this be B_log? +- print STDERR "$err Couldn't determine Red Hat version! Setting to 9!\n"; +- $distro="RH9"; +- } +- close(REDHAT_RELEASE); +- +- } +- elsif ( -e "/etc/debian_version" ) { +- $stable="3.1"; #Change this when Debian stable changes +- open(*DEBIAN_RELEASE,"/etc/debian_version"); +- $release=<DEBIAN_RELEASE>; +- unless ($release =~ /^(\d+\.\d+\w*)/) { +- print STDERR "$err System is not running a stable Debian GNU/Linux version. Setting to $stable.\n"; +- $distro="DB$stable"; ++ elsif ($version =~ /^3\./) { ++ $distro='RHEL3AS'; + } + else { +- $distro="DB$1"; +- } +- close(DEBIAN_RELEASE); +- } +- elsif ( -e "/etc/SuSE-release" ) { +- open(*SUSE_RELEASE,"/etc/SuSE-release"); +- $release=<SUSE_RELEASE>; +- if ($release =~ /^SuSE Linux (\d+\.\d+\w*)/i) { +- $distro="SE$1"; +- } +- elsif ($release =~ /^SUSE LINUX Enterprise Server (\d+\.?\d?\w*)/i) { +- $distro="SESLES$1"; +- } +- elsif ($release =~ /^SUSE Linux Enterprise Server (\d+\.?\d?\w*)/i) { +- $distro="SESLES$1"; +- } +- elsif ($release =~ /^openSuSE (\d+\.\d+\w*)/i) { +- $distro="SE$1"; ++ print STDERR "$err Could not infer CentOS version! Setting to Red Hat Enterprise 4 AS.\n"; ++ $distro='RHEL4AS'; + } +- else { +- print STDERR "$err Couldn't determine SuSE version! Setting to 10.3!\n"; +- $distro="SE10.3"; +- } +- close(SUSE_RELEASE); +- } +- elsif ( -e "/etc/turbolinux-release") { +- open(*TURBOLINUX_RELEASE,"/etc/turbolinux-release"); +- $release=<TURBOLINUX_RELEASE>; +- unless ($release =~ /^Turbolinux Workstation (\d+\.\d+\w*)/) { +- print STDERR "$err Couldn't determine TurboLinux version! Setting to 7.0!\n"; +- $distro="TB7.0"; +- } +- else { +- $distro="TB$1"; +- } +- close(TURBOLINUX_RELEASE); ++ } ++ else { ++ # JJB/HP - Should this be B_log? ++ print STDERR "$err Could not infer Red Hat version! Setting to 9!\n"; ++ $distro="RH9"; ++ } ++ close(REDHAT_RELEASE); ++ ++ } ++ elsif ( -e "/etc/debian_version" ) { ++ $stable="3.1"; #Change this when Debian stable changes ++ open(*DEBIAN_RELEASE,"/etc/debian_version"); ++ $release=<DEBIAN_RELEASE>; ++ unless ($release =~ /^(\d+\.\d+\w*)/) { ++ print STDERR "$err System is not running a stable Debian GNU/Linux version. Setting to $stable.\n"; ++ $distro="DB$stable"; ++ } ++ else { ++ $distro="DB$1"; ++ } ++ close(DEBIAN_RELEASE); ++ } ++ elsif ( -e "/etc/SuSE-release" ) { ++ open(*SUSE_RELEASE,"/etc/SuSE-release"); ++ $release=<SUSE_RELEASE>; ++ if ($release =~ /^SuSE Linux (\d+\.\d+\w*)/i) { ++ $distro="SE$1"; ++ } ++ elsif ($release =~ /^SUSE LINUX Enterprise Server (\d+\.?\d?\w*)/i) { ++ $distro="SESLES$1"; ++ } ++ elsif ($release =~ /^SUSE Linux Enterprise Server (\d+\.?\d?\w*)/i) { ++ $distro="SESLES$1"; ++ } ++ elsif ($release =~ /^openSuSE (\d+\.\d+\w*)/i) { ++ $distro="SE$1"; ++ } ++ else { ++ print STDERR "$err Could not infer SuSE version! Setting to 10.3!\n"; ++ $distro="SE10.3"; + } ++ close(SUSE_RELEASE); ++ } ++ elsif ( -e "/etc/turbolinux-release") { ++ open(*TURBOLINUX_RELEASE,"/etc/turbolinux-release"); ++ $release=<TURBOLINUX_RELEASE>; ++ unless ($release =~ /^Turbolinux Workstation (\d+\.\d+\w*)/) { ++ print STDERR "$err Could not infer TurboLinux version! Setting to 7.0!\n"; ++ $distro="TB7.0"; ++ } + else { +- # We're either on Mac OS X, HP-UX or an unsupported O/S. +- if ( -x '/usr/bin/uname') { ++ $distro="TB$1"; ++ } ++ close(TURBOLINUX_RELEASE); ++ } ++ else { ++ # We're either on Mac OS X, HP-UX or an unsupported O/S. ++ if ( -x '/usr/bin/uname') { + # uname is in /usr/bin on Mac OS X and HP-UX +- $release=`/usr/bin/uname -sr`; +- } +- else { +- print STDERR "$err Could not determine operating system version!\n"; +- $distro="unknown" +- } +- +- # Figure out what kind of system we're on. +- if ($release ne "") { +- if ($release =~ /^Darwin\s+(\d+)\.(\d+)/) { +- if ($1 == 6 ) { +- $distro = "OSX10.2"; +- } +- elsif ($1 == 7) { +- $distro = "OSX10.3"; +- } +- elsif ($1 == 8) { +- $distro = "OSX10.3"; +- } +- else { +- $distro = "unknown"; +- } ++ $release=`/usr/bin/uname -sr`; ++ } ++ else { ++ print STDERR "$err Could not infer operating system version from filesystem context. Setting inferred distro to 'unknown'.\n"; ++ $distro="unknown"; ++ } ++ ++ # Figure out what kind of system we're on. ++ if ($release ne "") { ++ if ($release =~ /^Darwin\s+(\d+)\.(\d+)/) { ++ if ($1 == 6 ) { ++ $distro = "OSX10.2"; + } +- elsif ( $release =~ /(^HP-UX)\s*B\.(\d+\.\d+)/ ) { +- $distro="$1$2"; ++ elsif ($1 == 7) { ++ $distro = "OSX10.3"; + } ++ elsif ($1 == 8) { ++ $distro = "OSX10.3"; ++ } + else { +- print STDERR "$err Could not determine operating system version!\n"; +- $distro="unknown"; ++ print STDERR "$err Could not infer operating system version from filesystem context. Setting inferred distro to 'unknown'.\n"; ++ $distro = "unknown"; + } + } ++ elsif ( $release =~ /(^HP-UX)\s*B\.(\d+\.\d+)/ ) { ++ $distro="$1$2"; ++ } ++ else { ++ print STDERR "$err Could not infer operating system version from filesystem context. Setting inferred distro to 'unknown'.\n"; ++ $distro="unknown"; ++ } + } +- +- $GLOBAL_OS=$distro; +- } elsif (not (defined $GLOBAL_OS)) { +- print "ERROR: GLOBAL OS Scoping Issue\n"; +- } else { +- $distro = $GLOBAL_OS; + } +- + return $distro; + } + + ################################################################################### +-# &getActualDistro; # ++# &getInferredDistro; # + # # + # This subroutine returns the actual os version in which is running on. This # + # os version is independent of the --os switch feed to bastille. # + # # + ################################################################################### +-sub getActualDistro { +- # set local variable to $GLOBAL_OS ++sub getInferredDistro { ++ if ($GLOBAL_INFERRED_OS eq "None") { ++ $GLOBAL_INFERRED_OS = &InferDistro; ++ } ++ return $GLOBAL_INFERRED_OS; ++} + +- if ($GLOBAL_ACTUAL_OS eq "None") { +- my $os = $GLOBAL_OS; +- # undef GLOBAL_OS so that the GetDistro routine will return +- # the actualDistro, it might otherwise return the distro set +- # by the --os switch. +- $GLOBAL_OS = "None"; +- $GLOBAL_ACTUAL_OS = &GetDistro; +- # reset the GLOBAL_OS variable +- $GLOBAL_OS = $os; ++sub GetDistro { ++ if ($GLOBAL_OS eq "None") { ++ return &getInferredDistro; + } +- return $GLOBAL_ACTUAL_OS; ++ return $GLOBAL_OS; + } ++ + # These are helper routines which used to be included inside GetDistro + sub is_OS_supported($) { + my $os=$_[0]; +@@ -556,7 +545,8 @@ + "SE7.2","SE7.3", "SE8.0","SE8.1","SE9.0","SE9.1", + "SE9.2","SE9.3","SE10.0","SE10.1","SE10.2","SE10.3", + "SESLES8","SESLES9","SESLES10", +- "TB7.0" ++ "TB7.0", ++ "Yocto" + ], + + "HP-UX" => [ +@@ -882,23 +872,19 @@ + ########################################################################### + sub ConfigureForDistro { + +- my $retval=1; +- +- # checking to see if the os version given is in fact supported + my $distro = &GetDistro; + +- # checking to see if the actual os version is in fact supported +- my $actualDistro = &getActualDistro; ++ my $inferredDistro = &getInferredDistro; ++ ++ if (! ($inferredDistro eq $distro) ) { ++ print STDERR "WARNING: Inferred distro $inferredDistro is not the same as specified distro $distro. Using specified distro.\n"; ++ } ++ + $ENV{'LOCALE'}=''; # So that test cases checking for english results work ok. +- if ((! &is_OS_supported($distro)) or (! &is_OS_supported($actualDistro)) ) { +- # if either is not supported then print out a list of supported versions +- if (! &is_OS_supported($distro)) { +- print STDERR "$err '$distro' is not a supported operating system.\n"; +- } +- else { +- print STDERR "$err Bastille is unable to operate correctly on this\n"; +- print STDERR "$spc $distro operating system.\n"; +- } ++ ++ if (! &is_OS_supported($distro)) { ++ print STDERR "$err '$distro' is not a supported operating system.\n"; ++ + my %supportedOSHash = &getSupportedOSHash; + print STDERR "$spc Valid operating system versions are as follows:\n"; + +@@ -930,7 +916,7 @@ + # intend via setting the Perl umask + umask(077); + +- &getFileAndServiceInfo($distro,$actualDistro); ++ &getFileAndServiceInfo($distro,$distro); + + # &dumpFileInfo; # great for debuging file location issues + # &dumpServiceInfo; # great for debuging service information issues +@@ -942,7 +928,7 @@ + "$spc You must use Bastille\'s -n flag (for example:\n" . + "$spc bastille -f -n) or \'touch $nodisclaim_file \'\n"; + +- return $retval; ++ return 1; + } + + +Index: Bastille/Bastille/LogAPI.pm +=================================================================== +--- Bastille.orig/Bastille/LogAPI.pm 2013-08-22 04:32:38.269968002 -0400 ++++ Bastille/Bastille/LogAPI.pm 2013-08-22 04:32:47.509968002 -0400 +@@ -111,7 +111,7 @@ + # do this here to prevent bootstrapping problem, where we need to + # write an error that the errorlog location isn't defined. + my $logdir="/var/log/Bastille"; +- if(&getActualDistro =~ "^HP-UX"){ ++ if(&getInferredDistro =~ "^HP-UX"){ + $logdir = "/var/opt/sec_mgmt/bastille/log/"; + } + diff --git a/meta-security/recipes-security/bastille/files/remove_questions_text_file_references.patch b/meta-security/recipes-security/bastille/files/remove_questions_text_file_references.patch new file mode 100644 index 000000000..bd094ee25 --- /dev/null +++ b/meta-security/recipes-security/bastille/files/remove_questions_text_file_references.patch @@ -0,0 +1,30 @@ +Upstream Status: Inappropriate [No upstream maintenance] + +Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> + +--- + +Index: Bastille/OSMap/LINUX.bastille +=================================================================== +--- Bastille.orig/OSMap/LINUX.bastille 2008-01-25 18:31:35.000000000 -0500 ++++ Bastille/OSMap/LINUX.bastille 2013-08-22 04:48:32.677968002 -0400 +@@ -12,7 +12,6 @@ + + bfile,InteractiveBastille,'/usr/sbin/InteractiveBastille' + bfile,BastilleBackEnd,'/usr/sbin/BastilleBackEnd' +-bfile,Questions,'/usr/share/Bastille/Questions.txt' + bfile,QuestionsModules,'/usr/share/Bastille/Modules.txt' + bfile,TODO,'/var/log/Bastille/TODO' + bfile,TODOFlag,'/var/log/Bastille/TODOFlag.txt' +Index: Bastille/OSMap/OSX.bastille +=================================================================== +--- Bastille.orig/OSMap/OSX.bastille 2007-09-11 18:09:26.000000000 -0400 ++++ Bastille/OSMap/OSX.bastille 2013-08-22 04:48:47.245968001 -0400 +@@ -10,7 +10,6 @@ + bdir,share,'/usr/share/Bastille' + + bfile,BastilleBackEnd,'/var/root/Bastille/BastilleBackEnd' +-bfile,Questions,'/usr/share/Bastille/Questions.txt' + bfile,QuestionsModules,'/usr/share/Bastille/Modules.txt' + bfile,TODO,'/var/log/Bastille/TODO' + bfile,TODOFlag,'/var/log/Bastille/TODOFlag.txt' diff --git a/meta-security/recipes-security/bastille/files/set_required_questions.py b/meta-security/recipes-security/bastille/files/set_required_questions.py new file mode 100755 index 000000000..4a28358c3 --- /dev/null +++ b/meta-security/recipes-security/bastille/files/set_required_questions.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python + +#Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> + +import argparse, os, shutil, sys, tempfile, traceback +from os import path + + + +def get_config(lines): + """ + From a sequence of lines retrieve the question file name, question identifier + pairs. + """ + for l in lines: + if not l.startswith("#"): + try: + (coord, value) = l.split("=") + try: + (fname, ident) = coord.split(".") + yield fname, ident + except ValueError as e: + raise ValueError("Badly formatted coordinates %s in line %s." % (coord, l.strip())) + except ValueError as e: + raise ValueError("Skipping badly formatted line %s, %s" % (l.strip(), e)) + + + +def check_contains(line, name): + """ + Check if the value field for REQUIRE_DISTRO contains the given name. + @param name line The REQUIRE_DISTRO line + @param name name The name to look for in the value field of the line. + """ + try: + (label, distros) = line.split(":") + return name in distros.split() + except ValueError as e: + raise ValueError("Error splitting REQUIRE_DISTRO line: %s" % e) + + + +def add_requires(the_ident, distro, lines): + + """ + Yield a sequence of lines the same as lines except that where + the_ident matches a question identifier change the REQUIRE_DISTRO so that + it includes the specified distro. + + @param name the_ident The question identifier to be matched. + @param name distro The distribution to added to the questions REQUIRE_DISTRO + field. + @param lines The sequence to be processed. + """ + for l in lines: + yield l + if l.startswith("LABEL:"): + try: + (label, ident) = l.split(":") + if ident.strip() == the_ident: + break + except ValueError as e: + raise ValueError("Unexpected line %s in questions file." % l.strip()) + for l in lines: + if l.startswith("REQUIRE_DISTRO"): + if not check_contains(l, distro): + yield l.rstrip() + " " + distro + "\n" + else: + yield l + break; + else: + yield l + for l in lines: + yield l + + + +def xform_file(qfile, distro, qlabel): + """ + Transform a Questions file. + @param name qfile The designated questions file. + @param name distro The distribution to add to the required distributions. + @param name qlabel The question label for which the distro is to be added. + """ + questions_in = open(qfile) + questions_out = tempfile.NamedTemporaryFile(delete=False) + for l in add_requires(qlabel, distro, questions_in): + questions_out.write(l) + questions_out.close() + questions_in.close() + shutil.copystat(qfile, questions_out.name) + os.remove(qfile) + shutil.move(questions_out.name, qfile) + + + +def handle_args(parser): + parser.add_argument('config_file', + help = "Configuration file path.") + parser.add_argument('questions_dir', + help = "Directory containing Questions files.") + parser.add_argument('--distro', '-d', + help = "The distribution, the default is Yocto.", + default = "Yocto") + parser.add_argument('--debug', '-b', + help = "Print debug information.", + action = 'store_true') + return parser.parse_args() + + + +def check_args(args): + args.config_file = os.path.abspath(args.config_file) + args.questions_dir = os.path.abspath(args.questions_dir) + + if not os.path.isdir(args.questions_dir): + raise ValueError("Specified Questions directory %s does not exist or is not a directory." % args.questions_dir) + + if not os.path.isfile(args.config_file): + raise ValueError("Specified configuration file %s not found." % args.config_file) + + + +def main(): + opts = handle_args(argparse.ArgumentParser(description="A simple script that sets required questions based on the question/answer pairs in a configuration file.")) + + try: + check_args(opts) + except ValueError as e: + if opts.debug: + traceback.print_exc() + else: + sys.exit("Fatal error:\n%s" % e) + + + try: + config_in = open(opts.config_file) + for qfile, qlabel in get_config(config_in): + questions_file = os.path.join(opts.questions_dir, qfile + ".txt") + xform_file(questions_file, opts.distro, qlabel) + config_in.close() + + except IOError as e: + if opts.debug: + traceback.print_exc() + else: + sys.exit("Fatal error reading or writing file:\n%s" % e) + except ValueError as e: + if opts.debug: + traceback.print_exc() + else: + sys.exit("Fatal error:\n%s" % e) + + + +if __name__ == "__main__": + main() diff --git a/meta-security/recipes-security/bastille/files/simplify_B_place.patch b/meta-security/recipes-security/bastille/files/simplify_B_place.patch new file mode 100644 index 000000000..307fdcab0 --- /dev/null +++ b/meta-security/recipes-security/bastille/files/simplify_B_place.patch @@ -0,0 +1,40 @@ +Upstream Status: Inappropriate [No upstream maintenance] + +Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> + +--- + +Index: Bastille/Bastille/API.pm +=================================================================== +--- Bastille.orig/Bastille/API.pm 2013-08-21 08:59:17.939950001 -0400 ++++ Bastille/Bastille/API.pm 2013-08-21 08:59:30.983950001 -0400 +@@ -1679,24 +1679,22 @@ + + use File::Copy; + +- my $original_source=$source; + $source = &getGlobal('BDIR', "share") . $source; +- my $original_target=$target; + + if ( -e $target and -f $target ) { +- &B_backup_file($original_target); +- &B_log("ACTION","About to copy $original_source to $original_target -- had to backup target\n"); ++ &B_backup_file($target); ++ &B_log("ACTION","About to copy $source to $target -- had to backup target\n"); + $had_to_backup_target=1; + } + $retval=copy($source,$target); + if ($retval) { +- &B_log("ACTION","placed file $original_source as $original_target\n"); ++ &B_log("ACTION","placed file $source as $target\n"); + # + # We want to add a line to the &getGlobal('BFILE', "created-files") so that the + # file we just put at $original_target gets deleted. +- &B_revert_log(&getGlobal('BIN',"rm") . " $original_target\n"); ++ &B_revert_log(&getGlobal('BIN',"rm") . " $target\n"); + } else { +- &B_log("ERROR","Failed to place $original_source as $original_target\n"); ++ &B_log("ERROR","Failed to place $source as $target\n"); + } + + # We add the file to the GLOBAL_SUMS hash if it is not already present diff --git a/meta-security/recipes-security/bastille/files/upgrade_options_processing.patch b/meta-security/recipes-security/bastille/files/upgrade_options_processing.patch new file mode 100644 index 000000000..4093867e9 --- /dev/null +++ b/meta-security/recipes-security/bastille/files/upgrade_options_processing.patch @@ -0,0 +1,91 @@ +Upstream Status: Inappropriate [No upstream maintenance] + +Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> + +--- + +Index: Bastille/Bastille/API.pm +=================================================================== +--- Bastille.orig/Bastille/API.pm 2013-08-21 11:41:09.235950000 -0400 ++++ Bastille/Bastille/API.pm 2013-08-21 11:41:16.183950000 -0400 +@@ -271,9 +271,15 @@ + # setOptions takes six arguments, $GLOBAL_DEBUG, $GLOBAL_LOGONLY, + # $GLOBAL_VERBOSE, $GLOBAL_AUDITONLY, $GLOBAL_AUDIT_NO_BROWSER, and GLOBAL_OS; + ########################################################################### +-sub setOptions($$$$$$) { +- ($GLOBAL_DEBUG,$GLOBAL_LOGONLY,$GLOBAL_VERBOSE,$GLOBAL_AUDITONLY, +- $GLOBAL_AUDIT_NO_BROWSER,$GLOBAL_OS) = @_; ++sub setOptions { ++ my %opts = @_; ++ ++ $GLOBAL_DEBUG = $opts{debug}; ++ $GLOBAL_LOGONLY = $opts{logonly}; ++ $GLOBAL_VERBOSE = $opts{verbose}; ++ $GLOBAL_AUDITONLY = $opts{auditonly}; ++ $GLOBAL_AUDIT_NO_BROWSER = $opts{audit_no_browser}; ++ $GLOBAL_OS = $opts{os}; + if ($GLOBAL_AUDIT_NO_BROWSER) { + $GLOBAL_AUDITONLY = 1; + } +Index: Bastille/BastilleBackEnd +=================================================================== +--- Bastille.orig/BastilleBackEnd 2013-08-21 11:41:09.235950000 -0400 ++++ Bastille/BastilleBackEnd 2013-08-21 12:40:54.055950001 -0400 +@@ -50,15 +50,13 @@ + my $nodisclaim = 0; + my $verbose = 0; + my $force = 0; +-my $log_only = 0; + my $debug = 0; + my $alternate_config=undef; + + if( Getopt::Long::GetOptions( "n" => \$nodisclaim, + "v" => \$verbose, + "force" => \$force, +-# "log" => \$log_only, # broken +- "f:s" => \$alternate_config, ++ "f=s" => \$alternate_config, + "debug" => \$debug) ) { + $error = 0; # no parse error + +@@ -66,7 +64,9 @@ + $error = 1; # parse error + } + +-&setOptions($debug,$log_only,$verbose); ++&setOptions( ++ debug => $debug, ++ verbose => $verbose); + &ConfigureForDistro; + + if ( $error ) { # GetOptions couldn't parse all of the args +Index: Bastille/InteractiveBastille +=================================================================== +--- Bastille.orig/InteractiveBastille 2013-08-21 11:41:09.235950000 -0400 ++++ Bastille/InteractiveBastille 2013-08-21 12:40:30.531950001 -0400 +@@ -234,8 +234,8 @@ + "a" => \$audit, + "force" => \$force, + "log" => \$log_only, +- "os:s" => \$os_version, +- "f:s" => \$alternate_config, ++ "os=s" => \$os_version, ++ "f=s" => \$alternate_config, + "debug" => \$debug) ) { + $error = 0; # no parse error + } else { +@@ -293,7 +293,13 @@ + $UseRequiresRules = 'N'; + } + +-&setOptions($debug,$log_only,$verbose,$audit,$auditnobrowser,$os_version); ++&setOptions( ++ debug => $debug, ++ logonly => $log_only, ++ verbose => $verbose, ++ auditonly => $audit, ++ audit_no_browser => $auditnobrowser, ++ os => $os_version); + &ConfigureForDistro; + + # ensuring mutually exclusive options are exclusive diff --git a/meta-security/recipes-security/buck-security/buck-security_0.7.bb b/meta-security/recipes-security/buck-security/buck-security_0.7.bb new file mode 100644 index 000000000..3733c88ba --- /dev/null +++ b/meta-security/recipes-security/buck-security/buck-security_0.7.bb @@ -0,0 +1,63 @@ +SUMMARY = "Linux security scanner" +DESCRIPTION = "Buck-Security is a security scanner for Debian and Ubuntu Linux. It runs a couple of important checks and helps you to harden your Linux \ +system. This enables you to quickly overview the security status of your Linux system." +SECTION = "security" +LICENSE = "GPL-2.0" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6" +RDEPENDS_${PN} = "coreutils \ + gnupg \ + net-tools \ + perl \ + perl-module-data-dumper \ + perl-module-file-basename \ + perl-module-file-spec \ + perl-module-getopt-long \ + perl-module-lib \ + perl-module-posix \ + perl-module-term-ansicolor \ + perl-module-time-localtime \ + pinentry \ + " + +RDEPENDS_${PN}_class-native = "coreutils \ + net-tools \ + perl \ + perl-module-data-dumper \ + perl-module-file-basename \ + perl-module-file-spec \ + perl-module-getopt-long \ + perl-module-lib \ + perl-module-posix \ + perl-module-term-ansicolor \ + perl-module-time-localtime \ + " + +SRC_URI = "http://sourceforge.net/projects/buck-security/files/buck-security/buck-security_${PV}/${BPN}_${PV}.tar.gz" + +SRC_URI[md5sum] = "611a3e9bb7ed8a8270aa15216c321c53" +SRC_URI[sha256sum] = "c533c6631ec3554dd8d39d2d1c3ed44badbbf50810ebb75469c74639fa294b01" + +S = "${WORKDIR}/${BPN}_${PV}" + +do_configure() { + : +} + +do_compile() { + : +} + +do_install() { + install -d ${D}${bindir}/buck + cp -r ${S}/* ${D}${bindir}/buck + cp -r ${S}/buck-security ${D}${bindir} + sed -i 's!use lib "checks"!use lib File::Spec->catfile(dirname(File::Spec->rel2abs(__FILE__)), "buck/checks")!' ${D}${bindir}/buck-security + sed -i 's!use lib "checks/lib"!use lib File::Spec->catfile(dirname(File::Spec->rel2abs(__FILE__)), "buck/checks/lib")!' ${D}${bindir}/buck-security + sed -i 's!use lib "lib"!use lib File::Spec->catfile(dirname(File::Spec->rel2abs(__FILE__)), "buck/lib")!' ${D}${bindir}/buck-security + sed -i 's!my $buck_root = "."!my $buck_root = File::Spec->catfile(dirname(File::Spec->rel2abs(__FILE__)), "buck")!' ${D}${bindir}/buck-security + +} + +FILES_${PN} = "${bindir}/*" + +BBCLASSEXTEND = "native" diff --git a/meta-security/recipes-security/ccs-tools/README b/meta-security/recipes-security/ccs-tools/README new file mode 100644 index 000000000..4a4faa715 --- /dev/null +++ b/meta-security/recipes-security/ccs-tools/README @@ -0,0 +1,12 @@ +Documentation: +http://tomoyo.sourceforge.jp/1.8/index.html.en + + +To start via command line add: + +" security=tomoyo TOMOYO_trigger=/usr/lib/systemd/systemd" + +To initialize: +/usr/lib/ccs/init_policy + +DISTRO_FEATURES_append = " tomoyo" diff --git a/meta-security/recipes-security/ccs-tools/ccs-tools_1.8.4.bb b/meta-security/recipes-security/ccs-tools/ccs-tools_1.8.4.bb new file mode 100644 index 000000000..189504a55 --- /dev/null +++ b/meta-security/recipes-security/ccs-tools/ccs-tools_1.8.4.bb @@ -0,0 +1,50 @@ +SUMMARY = "Tomoyo" +DESCRIPTION = "TOMOYO Linux is a Mandatory Access Control (MAC) implementation for Linux that can be used to increase the security of a system, while also being useful purely as a system analysis tool. \nTo start via command line add: \nsecurity=tomoyo TOMOYO_trigger=/usr/lib/systemd/systemd \nTo initialize: \n/usr/lib/ccs/init_policy" + +SECTION = "security" +LICENSE = "GPL-2.0" +LIC_FILES_CHKSUM = "file://COPYING.ccs;md5=751419260aa954499f7abaabaa882bbe" + +DEPENDS = "ncurses" + +DS = "20150505" +SRC_URI = "http://osdn.dl.sourceforge.jp/tomoyo/49693/${BPN}-${PV}-${DS}.tar.gz" + +SRC_URI[md5sum] = "eeee8eb96a7680bfa9c8f6de55502c44" +SRC_URI[sha256sum] = "c358b80a2ea77a9dda79dc2a056dae3acaf3a72fcb8481cfb1cd1f16746324b4" + +S = "${WORKDIR}/${PN}" + +inherit distro_features_check + +do_make(){ + oe_runmake USRLIBDIR=${libdir} all + cd ${S}/kernel_test + oe_runmake all +} + +do_install(){ + oe_runmake INSTALLDIR=${D} USRLIBDIR=${libdir} install +} + +PACKAGE="${PN} ${PN}-dbg ${PN}-doc" + +FILES_${PN} = "\ + ${sbindir}/* \ + ${base_sbindir}/* \ + ${libdir}/* \ +" + +FILES_${PN}-doc = "\ + ${mandir}/man8/* \ +" + +FILES_${PN}-dbg = "\ + ${base_sbindir}/.debug/* \ + ${sbindir}/.debug/* \ + ${libdir}/.debug/* \ + ${libdir}/ccs/.debug/* \ + /usr/src/debug/* \ +" + +REQUIRED_DISTRO_FEATURES ?=" tomoyo" diff --git a/meta-security/recipes-security/checksec/checksec_1.5.bb b/meta-security/recipes-security/checksec/checksec_1.5.bb new file mode 100644 index 000000000..07f0f7c79 --- /dev/null +++ b/meta-security/recipes-security/checksec/checksec_1.5.bb @@ -0,0 +1,18 @@ +SUMMARY = "Program radominization" +DESCRIPTION = "The checksec.sh script is designed to test what standard Linux OS and PaX security features are being used." +SECTION = "security" +LICENSE = "BSD" +HOMEPAGE="http://www.trapkit.de/tools/checksec.html" + +LIC_FILES_CHKSUM = "file://checksec.sh;md5=075996be339ab16ad7b94d6de3ee07bd" + +SRC_URI = "file://checksec.sh" + +S = "${WORKDIR}" + +do_install() { + install -d ${D}${bindir} + install -m 0755 ${WORKDIR}/checksec.sh ${D}${bindir} +} + +RDEPENDS_${PN} = "bash" diff --git a/meta-security/recipes-security/checksec/files/checksec.sh b/meta-security/recipes-security/checksec/files/checksec.sh new file mode 100644 index 000000000..dd1f72e54 --- /dev/null +++ b/meta-security/recipes-security/checksec/files/checksec.sh @@ -0,0 +1,882 @@ +#!/bin/bash +# +# The BSD License (http://www.opensource.org/licenses/bsd-license.php) +# specifies the terms and conditions of use for checksec.sh: +# +# Copyright (c) 2009-2011, Tobias Klein. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Tobias Klein nor the name of trapkit.de may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +# DAMAGE. +# +# Name : checksec.sh +# Version : 1.5 +# Author : Tobias Klein +# Date : November 2011 +# Download: http://www.trapkit.de/tools/checksec.html +# Changes : http://www.trapkit.de/tools/checksec_changes.txt +# +# Description: +# +# Modern Linux distributions offer some mitigation techniques to make it +# harder to exploit software vulnerabilities reliably. Mitigations such +# as RELRO, NoExecute (NX), Stack Canaries, Address Space Layout +# Randomization (ASLR) and Position Independent Executables (PIE) have +# made reliably exploiting any vulnerabilities that do exist far more +# challenging. The checksec.sh script is designed to test what *standard* +# Linux OS and PaX (http://pax.grsecurity.net/) security features are being +# used. +# +# As of version 1.3 the script also lists the status of various Linux kernel +# protection mechanisms. +# +# Credits: +# +# Thanks to Brad Spengler (grsecurity.net) for the PaX support. +# Thanks to Jon Oberheide (jon.oberheide.org) for the kernel support. +# Thanks to Ollie Whitehouse (Research In Motion) for rpath/runpath support. +# +# Others that contributed to checksec.sh (in no particular order): +# +# Simon Ruderich, Denis Scherbakov, Stefan Kuttler, Radoslaw Madej, +# Anthony G. Basile, Martin Vaeth and Brian Davis. +# + +# global vars +have_readelf=1 +verbose=false + +# FORTIFY_SOURCE vars +FS_end=_chk +FS_cnt_total=0 +FS_cnt_checked=0 +FS_cnt_unchecked=0 +FS_chk_func_libc=0 +FS_functions=0 +FS_libc=0 + +# version information +version() { + echo "checksec v1.5, Tobias Klein, www.trapkit.de, November 2011" + echo +} + +# help +help() { + echo "Usage: checksec [OPTION]" + echo + echo "Options:" + echo + echo " --file <executable-file>" + echo " --dir <directory> [-v]" + echo " --proc <process name>" + echo " --proc-all" + echo " --proc-libs <process ID>" + echo " --kernel" + echo " --fortify-file <executable-file>" + echo " --fortify-proc <process ID>" + echo " --version" + echo " --help" + echo + echo "For more information, see:" + echo " http://www.trapkit.de/tools/checksec.html" + echo +} + +# check if command exists +command_exists () { + type $1 > /dev/null 2>&1; +} + +# check if directory exists +dir_exists () { + if [ -d $1 ] ; then + return 0 + else + return 1 + fi +} + +# check user privileges +root_privs () { + if [ $(/usr/bin/id -u) -eq 0 ] ; then + return 0 + else + return 1 + fi +} + +# check if input is numeric +isNumeric () { + echo "$@" | grep -q -v "[^0-9]" +} + +# check if input is a string +isString () { + echo "$@" | grep -q -v "[^A-Za-z]" +} + +# check file(s) +filecheck() { + # check for RELRO support + if readelf -l $1 2>/dev/null | grep -q 'GNU_RELRO'; then + if readelf -d $1 2>/dev/null | grep -q 'BIND_NOW'; then + echo -n -e '\033[32mFull RELRO \033[m ' + else + echo -n -e '\033[33mPartial RELRO\033[m ' + fi + else + echo -n -e '\033[31mNo RELRO \033[m ' + fi + + # check for stack canary support + if readelf -s $1 2>/dev/null | grep -q '__stack_chk_fail'; then + echo -n -e '\033[32mCanary found \033[m ' + else + echo -n -e '\033[31mNo canary found\033[m ' + fi + + # check for NX support + if readelf -W -l $1 2>/dev/null | grep 'GNU_STACK' | grep -q 'RWE'; then + echo -n -e '\033[31mNX disabled\033[m ' + else + echo -n -e '\033[32mNX enabled \033[m ' + fi + + # check for PIE support + if readelf -h $1 2>/dev/null | grep -q 'Type:[[:space:]]*EXEC'; then + echo -n -e '\033[31mNo PIE \033[m ' + elif readelf -h $1 2>/dev/null | grep -q 'Type:[[:space:]]*DYN'; then + if readelf -d $1 2>/dev/null | grep -q '(DEBUG)'; then + echo -n -e '\033[32mPIE enabled \033[m ' + else + echo -n -e '\033[33mDSO \033[m ' + fi + else + echo -n -e '\033[33mNot an ELF file\033[m ' + fi + + # check for rpath / run path + if readelf -d $1 2>/dev/null | grep -q 'rpath'; then + echo -n -e '\033[31mRPATH \033[m ' + else + echo -n -e '\033[32mNo RPATH \033[m ' + fi + + if readelf -d $1 2>/dev/null | grep -q 'runpath'; then + echo -n -e '\033[31mRUNPATH \033[m ' + else + echo -n -e '\033[32mNo RUNPATH \033[m ' + fi +} + +# check process(es) +proccheck() { + # check for RELRO support + if readelf -l $1/exe 2>/dev/null | grep -q 'Program Headers'; then + if readelf -l $1/exe 2>/dev/null | grep -q 'GNU_RELRO'; then + if readelf -d $1/exe 2>/dev/null | grep -q 'BIND_NOW'; then + echo -n -e '\033[32mFull RELRO \033[m ' + else + echo -n -e '\033[33mPartial RELRO \033[m ' + fi + else + echo -n -e '\033[31mNo RELRO \033[m ' + fi + else + echo -n -e '\033[31mPermission denied (please run as root)\033[m\n' + exit 1 + fi + + # check for stack canary support + if readelf -s $1/exe 2>/dev/null | grep -q 'Symbol table'; then + if readelf -s $1/exe 2>/dev/null | grep -q '__stack_chk_fail'; then + echo -n -e '\033[32mCanary found \033[m ' + else + echo -n -e '\033[31mNo canary found \033[m ' + fi + else + if [ "$1" != "1" ] ; then + echo -n -e '\033[33mPermission denied \033[m ' + else + echo -n -e '\033[33mNo symbol table found\033[m ' + fi + fi + + # first check for PaX support + if cat $1/status 2> /dev/null | grep -q 'PaX:'; then + pageexec=( $(cat $1/status 2> /dev/null | grep 'PaX:' | cut -b6) ) + segmexec=( $(cat $1/status 2> /dev/null | grep 'PaX:' | cut -b10) ) + mprotect=( $(cat $1/status 2> /dev/null | grep 'PaX:' | cut -b8) ) + randmmap=( $(cat $1/status 2> /dev/null | grep 'PaX:' | cut -b9) ) + if [[ "$pageexec" = "P" || "$segmexec" = "S" ]] && [[ "$mprotect" = "M" && "$randmmap" = "R" ]] ; then + echo -n -e '\033[32mPaX enabled\033[m ' + elif [[ "$pageexec" = "p" && "$segmexec" = "s" && "$randmmap" = "R" ]] ; then + echo -n -e '\033[33mPaX ASLR only\033[m ' + elif [[ "$pageexec" = "P" || "$segmexec" = "S" ]] && [[ "$mprotect" = "m" && "$randmmap" = "R" ]] ; then + echo -n -e '\033[33mPaX mprot off \033[m' + elif [[ "$pageexec" = "P" || "$segmexec" = "S" ]] && [[ "$mprotect" = "M" && "$randmmap" = "r" ]] ; then + echo -n -e '\033[33mPaX ASLR off\033[m ' + elif [[ "$pageexec" = "P" || "$segmexec" = "S" ]] && [[ "$mprotect" = "m" && "$randmmap" = "r" ]] ; then + echo -n -e '\033[33mPaX NX only\033[m ' + else + echo -n -e '\033[31mPaX disabled\033[m ' + fi + # fallback check for NX support + elif readelf -W -l $1/exe 2>/dev/null | grep 'GNU_STACK' | grep -q 'RWE'; then + echo -n -e '\033[31mNX disabled\033[m ' + else + echo -n -e '\033[32mNX enabled \033[m ' + fi + + # check for PIE support + if readelf -h $1/exe 2>/dev/null | grep -q 'Type:[[:space:]]*EXEC'; then + echo -n -e '\033[31mNo PIE \033[m ' + elif readelf -h $1/exe 2>/dev/null | grep -q 'Type:[[:space:]]*DYN'; then + if readelf -d $1/exe 2>/dev/null | grep -q '(DEBUG)'; then + echo -n -e '\033[32mPIE enabled \033[m ' + else + echo -n -e '\033[33mDynamic Shared Object\033[m ' + fi + else + echo -n -e '\033[33mNot an ELF file \033[m ' + fi +} + +# check mapped libraries +libcheck() { + libs=( $(awk '{ print $6 }' /proc/$1/maps | grep '/' | sort -u | xargs file | grep ELF | awk '{ print $1 }' | sed 's/:/ /') ) + + printf "\n* Loaded libraries (file information, # of mapped files: ${#libs[@]}):\n\n" + + for element in $(seq 0 $((${#libs[@]} - 1))) + do + echo " ${libs[$element]}:" + echo -n " " + filecheck ${libs[$element]} + printf "\n\n" + done +} + +# check for system-wide ASLR support +aslrcheck() { + # PaX ASLR support + if !(cat /proc/1/status 2> /dev/null | grep -q 'Name:') ; then + echo -n -e ':\033[33m insufficient privileges for PaX ASLR checks\033[m\n' + echo -n -e ' Fallback to standard Linux ASLR check' + fi + + if cat /proc/1/status 2> /dev/null | grep -q 'PaX:'; then + printf ": " + if cat /proc/1/status 2> /dev/null | grep 'PaX:' | grep -q 'R'; then + echo -n -e '\033[32mPaX ASLR enabled\033[m\n\n' + else + echo -n -e '\033[31mPaX ASLR disabled\033[m\n\n' + fi + else + # standard Linux 'kernel.randomize_va_space' ASLR support + # (see the kernel file 'Documentation/sysctl/kernel.txt' for a detailed description) + printf " (kernel.randomize_va_space): " + if /sbin/sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 1'; then + echo -n -e '\033[33mOn (Setting: 1)\033[m\n\n' + printf " Description - Make the addresses of mmap base, stack and VDSO page randomized.\n" + printf " This, among other things, implies that shared libraries will be loaded to \n" + printf " random addresses. Also for PIE-linked binaries, the location of code start\n" + printf " is randomized. Heap addresses are *not* randomized.\n\n" + elif /sbin/sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 2'; then + echo -n -e '\033[32mOn (Setting: 2)\033[m\n\n' + printf " Description - Make the addresses of mmap base, heap, stack and VDSO page randomized.\n" + printf " This, among other things, implies that shared libraries will be loaded to random \n" + printf " addresses. Also for PIE-linked binaries, the location of code start is randomized.\n\n" + elif /sbin/sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 0'; then + echo -n -e '\033[31mOff (Setting: 0)\033[m\n' + else + echo -n -e '\033[31mNot supported\033[m\n' + fi + printf " See the kernel file 'Documentation/sysctl/kernel.txt' for more details.\n\n" + fi +} + +# check cpu nx flag +nxcheck() { + if grep -q nx /proc/cpuinfo; then + echo -n -e '\033[32mYes\033[m\n\n' + else + echo -n -e '\033[31mNo\033[m\n\n' + fi +} + +# check for kernel protection mechanisms +kernelcheck() { + printf " Description - List the status of kernel protection mechanisms. Rather than\n" + printf " inspect kernel mechanisms that may aid in the prevention of exploitation of\n" + printf " userspace processes, this option lists the status of kernel configuration\n" + printf " options that harden the kernel itself against attack.\n\n" + printf " Kernel config: " + + if [ -f /proc/config.gz ] ; then + kconfig="zcat /proc/config.gz" + printf "\033[32m/proc/config.gz\033[m\n\n" + elif [ -f /boot/config-`uname -r` ] ; then + kconfig="cat /boot/config-`uname -r`" + printf "\033[33m/boot/config-`uname -r`\033[m\n\n" + printf " Warning: The config on disk may not represent running kernel config!\n\n"; + elif [ -f "${KBUILD_OUTPUT:-/usr/src/linux}"/.config ] ; then + kconfig="cat ${KBUILD_OUTPUT:-/usr/src/linux}/.config" + printf "\033[33m%s\033[m\n\n" "${KBUILD_OUTPUT:-/usr/src/linux}/.config" + printf " Warning: The config on disk may not represent running kernel config!\n\n"; + else + printf "\033[31mNOT FOUND\033[m\n\n" + exit 0 + fi + + printf " GCC stack protector support: " + if $kconfig | grep -qi 'CONFIG_CC_STACKPROTECTOR=y'; then + printf "\033[32mEnabled\033[m\n" + else + printf "\033[31mDisabled\033[m\n" + fi + + printf " Strict user copy checks: " + if $kconfig | grep -qi 'CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y'; then + printf "\033[32mEnabled\033[m\n" + else + printf "\033[31mDisabled\033[m\n" + fi + + printf " Enforce read-only kernel data: " + if $kconfig | grep -qi 'CONFIG_DEBUG_RODATA=y'; then + printf "\033[32mEnabled\033[m\n" + else + printf "\033[31mDisabled\033[m\n" + fi + printf " Restrict /dev/mem access: " + if $kconfig | grep -qi 'CONFIG_STRICT_DEVMEM=y'; then + printf "\033[32mEnabled\033[m\n" + else + printf "\033[31mDisabled\033[m\n" + fi + + printf " Restrict /dev/kmem access: " + if $kconfig | grep -qi 'CONFIG_DEVKMEM=y'; then + printf "\033[31mDisabled\033[m\n" + else + printf "\033[32mEnabled\033[m\n" + fi + + printf "\n" + printf "* grsecurity / PaX: " + + if $kconfig | grep -qi 'CONFIG_GRKERNSEC=y'; then + if $kconfig | grep -qi 'CONFIG_GRKERNSEC_HIGH=y'; then + printf "\033[32mHigh GRKERNSEC\033[m\n\n" + elif $kconfig | grep -qi 'CONFIG_GRKERNSEC_MEDIUM=y'; then + printf "\033[33mMedium GRKERNSEC\033[m\n\n" + elif $kconfig | grep -qi 'CONFIG_GRKERNSEC_LOW=y'; then + printf "\033[31mLow GRKERNSEC\033[m\n\n" + else + printf "\033[33mCustom GRKERNSEC\033[m\n\n" + fi + + printf " Non-executable kernel pages: " + if $kconfig | grep -qi 'CONFIG_PAX_KERNEXEC=y'; then + printf "\033[32mEnabled\033[m\n" + else + printf "\033[31mDisabled\033[m\n" + fi + + printf " Prevent userspace pointer deref: " + if $kconfig | grep -qi 'CONFIG_PAX_MEMORY_UDEREF=y'; then + printf "\033[32mEnabled\033[m\n" + else + printf "\033[31mDisabled\033[m\n" + fi + + printf " Prevent kobject refcount overflow: " + if $kconfig | grep -qi 'CONFIG_PAX_REFCOUNT=y'; then + printf "\033[32mEnabled\033[m\n" + else + printf "\033[31mDisabled\033[m\n" + fi + + printf " Bounds check heap object copies: " + if $kconfig | grep -qi 'CONFIG_PAX_USERCOPY=y'; then + printf "\033[32mEnabled\033[m\n" + else + printf "\033[31mDisabled\033[m\n" + fi + + printf " Disable writing to kmem/mem/port: " + if $kconfig | grep -qi 'CONFIG_GRKERNSEC_KMEM=y'; then + printf "\033[32mEnabled\033[m\n" + else + printf "\033[31mDisabled\033[m\n" + fi + + printf " Disable privileged I/O: " + if $kconfig | grep -qi 'CONFIG_GRKERNSEC_IO=y'; then + printf "\033[32mEnabled\033[m\n" + else + printf "\033[31mDisabled\033[m\n" + fi + + printf " Harden module auto-loading: " + if $kconfig | grep -qi 'CONFIG_GRKERNSEC_MODHARDEN=y'; then + printf "\033[32mEnabled\033[m\n" + else + printf "\033[31mDisabled\033[m\n" + fi + + printf " Hide kernel symbols: " + if $kconfig | grep -qi 'CONFIG_GRKERNSEC_HIDESYM=y'; then + printf "\033[32mEnabled\033[m\n" + else + printf "\033[31mDisabled\033[m\n" + fi + else + printf "\033[31mNo GRKERNSEC\033[m\n\n" + printf " The grsecurity / PaX patchset is available here:\n" + printf " http://grsecurity.net/\n" + fi + + printf "\n" + printf "* Kernel Heap Hardening: " + + if $kconfig | grep -qi 'CONFIG_KERNHEAP=y'; then + if $kconfig | grep -qi 'CONFIG_KERNHEAP_FULLPOISON=y'; then + printf "\033[32mFull KERNHEAP\033[m\n\n" + else + printf "\033[33mPartial KERNHEAP\033[m\n\n" + fi + else + printf "\033[31mNo KERNHEAP\033[m\n\n" + printf " The KERNHEAP hardening patchset is available here:\n" + printf " https://www.subreption.com/kernheap/\n\n" + fi +} + +# --- FORTIFY_SOURCE subfunctions (start) --- + +# is FORTIFY_SOURCE supported by libc? +FS_libc_check() { + printf "* FORTIFY_SOURCE support available (libc) : " + + if [ "${#FS_chk_func_libc[@]}" != "0" ] ; then + printf "\033[32mYes\033[m\n" + else + printf "\033[31mNo\033[m\n" + exit 1 + fi +} + +# was the binary compiled with FORTIFY_SOURCE? +FS_binary_check() { + printf "* Binary compiled with FORTIFY_SOURCE support: " + + for FS_elem_functions in $(seq 0 $((${#FS_functions[@]} - 1))) + do + if [[ ${FS_functions[$FS_elem_functions]} =~ _chk ]] ; then + printf "\033[32mYes\033[m\n" + return + fi + done + printf "\033[31mNo\033[m\n" + exit 1 +} + +FS_comparison() { + echo + printf " ------ EXECUTABLE-FILE ------- . -------- LIBC --------\n" + printf " FORTIFY-able library functions | Checked function names\n" + printf " -------------------------------------------------------\n" + + for FS_elem_libc in $(seq 0 $((${#FS_chk_func_libc[@]} - 1))) + do + for FS_elem_functions in $(seq 0 $((${#FS_functions[@]} - 1))) + do + FS_tmp_func=${FS_functions[$FS_elem_functions]} + FS_tmp_libc=${FS_chk_func_libc[$FS_elem_libc]} + + if [[ $FS_tmp_func =~ ^$FS_tmp_libc$ ]] ; then + printf " \033[31m%-30s\033[m | __%s%s\n" $FS_tmp_func $FS_tmp_libc $FS_end + let FS_cnt_total++ + let FS_cnt_unchecked++ + elif [[ $FS_tmp_func =~ ^$FS_tmp_libc(_chk) ]] ; then + printf " \033[32m%-30s\033[m | __%s%s\n" $FS_tmp_func $FS_tmp_libc $FS_end + let FS_cnt_total++ + let FS_cnt_checked++ + fi + + done + done +} + +FS_summary() { + echo + printf "SUMMARY:\n\n" + printf "* Number of checked functions in libc : ${#FS_chk_func_libc[@]}\n" + printf "* Total number of library functions in the executable: ${#FS_functions[@]}\n" + printf "* Number of FORTIFY-able functions in the executable : %s\n" $FS_cnt_total + printf "* Number of checked functions in the executable : \033[32m%s\033[m\n" $FS_cnt_checked + printf "* Number of unchecked functions in the executable : \033[31m%s\033[m\n" $FS_cnt_unchecked + echo +} + +# --- FORTIFY_SOURCE subfunctions (end) --- + +if !(command_exists readelf) ; then + printf "\033[31mWarning: 'readelf' not found! It's required for most checks.\033[m\n\n" + have_readelf=0 +fi + +# parse command-line arguments +case "$1" in + + --version) + version + exit 0 + ;; + + --help) + help + exit 0 + ;; + + --dir) + if [ "$3" = "-v" ] ; then + verbose=true + fi + if [ $have_readelf -eq 0 ] ; then + exit 1 + fi + if [ -z "$2" ] ; then + printf "\033[31mError: Please provide a valid directory.\033[m\n\n" + exit 1 + fi + # remove trailing slashes + tempdir=`echo $2 | sed -e "s/\/*$//"` + if [ ! -d $tempdir ] ; then + printf "\033[31mError: The directory '$tempdir' does not exist.\033[m\n\n" + exit 1 + fi + cd $tempdir + printf "RELRO STACK CANARY NX PIE RPATH RUNPATH FILE\n" + for N in [A-Za-z]*; do + if [ "$N" != "[A-Za-z]*" ]; then + # read permissions? + if [ ! -r $N ]; then + printf "\033[31mError: No read permissions for '$tempdir/$N' (run as root).\033[m\n" + else + # ELF executable? + out=`file $N` + if [[ ! $out =~ ELF ]] ; then + if [ "$verbose" = "true" ] ; then + printf "\033[34m*** Not an ELF file: $tempdir/" + file $N + printf "\033[m" + fi + else + filecheck $N + if [ `find $tempdir/$N \( -perm -004000 -o -perm -002000 \) -type f -print` ]; then + printf "\033[37;41m%s%s\033[m" $2 $N + else + printf "%s%s" $tempdir/ $N + fi + echo + fi + fi + fi + done + exit 0 + ;; + + --file) + if [ $have_readelf -eq 0 ] ; then + exit 1 + fi + if [ -z "$2" ] ; then + printf "\033[31mError: Please provide a valid file.\033[m\n\n" + exit 1 + fi + # does the file exist? + if [ ! -e $2 ] ; then + printf "\033[31mError: The file '$2' does not exist.\033[m\n\n" + exit 1 + fi + # read permissions? + if [ ! -r $2 ] ; then + printf "\033[31mError: No read permissions for '$2' (run as root).\033[m\n\n" + exit 1 + fi + # ELF executable? + out=`file $2` + if [[ ! $out =~ ELF ]] ; then + printf "\033[31mError: Not an ELF file: " + file $2 + printf "\033[m\n" + exit 1 + fi + printf "RELRO STACK CANARY NX PIE RPATH RUNPATH FILE\n" + filecheck $2 + if [ `find $2 \( -perm -004000 -o -perm -002000 \) -type f -print` ] ; then + printf "\033[37;41m%s%s\033[m" $2 $N + else + printf "%s" $2 + fi + echo + exit 0 + ;; + + --proc-all) + if [ $have_readelf -eq 0 ] ; then + exit 1 + fi + cd /proc + printf "* System-wide ASLR" + aslrcheck + printf "* Does the CPU support NX: " + nxcheck + printf " COMMAND PID RELRO STACK CANARY NX/PaX PIE\n" + for N in [1-9]*; do + if [ $N != $$ ] && readlink -q $N/exe > /dev/null; then + printf "%16s" `head -1 $N/status | cut -b 7-` + printf "%7d " $N + proccheck $N + echo + fi + done + if [ ! -e /usr/bin/id ] ; then + printf "\n\033[33mNote: If you are running 'checksec.sh' as an unprivileged user, you\n" + printf " will not see all processes. Please run the script as root.\033[m\n\n" + else + if !(root_privs) ; then + printf "\n\033[33mNote: You are running 'checksec.sh' as an unprivileged user.\n" + printf " Too see all processes, please run the script as root.\033[m\n\n" + fi + fi + exit 0 + ;; + + --proc) + if [ $have_readelf -eq 0 ] ; then + exit 1 + fi + if [ -z "$2" ] ; then + printf "\033[31mError: Please provide a valid process name.\033[m\n\n" + exit 1 + fi + if !(isString "$2") ; then + printf "\033[31mError: Please provide a valid process name.\033[m\n\n" + exit 1 + fi + cd /proc + printf "* System-wide ASLR" + aslrcheck + printf "* Does the CPU support NX: " + nxcheck + printf " COMMAND PID RELRO STACK CANARY NX/PaX PIE\n" + for N in `ps -Ao pid,comm | grep $2 | cut -b1-6`; do + if [ -d $N ] ; then + printf "%16s" `head -1 $N/status | cut -b 7-` + printf "%7d " $N + # read permissions? + if [ ! -r $N/exe ] ; then + if !(root_privs) ; then + printf "\033[31mNo read permissions for '/proc/$N/exe' (run as root).\033[m\n\n" + exit 1 + fi + if [ ! `readlink $N/exe` ] ; then + printf "\033[31mPermission denied. Requested process ID belongs to a kernel thread.\033[m\n\n" + exit 1 + fi + exit 1 + fi + proccheck $N + echo + fi + done + exit 0 + ;; + + --proc-libs) + if [ $have_readelf -eq 0 ] ; then + exit 1 + fi + if [ -z "$2" ] ; then + printf "\033[31mError: Please provide a valid process ID.\033[m\n\n" + exit 1 + fi + if !(isNumeric "$2") ; then + printf "\033[31mError: Please provide a valid process ID.\033[m\n\n" + exit 1 + fi + cd /proc + printf "* System-wide ASLR" + aslrcheck + printf "* Does the CPU support NX: " + nxcheck + printf "* Process information:\n\n" + printf " COMMAND PID RELRO STACK CANARY NX/PaX PIE\n" + N=$2 + if [ -d $N ] ; then + printf "%16s" `head -1 $N/status | cut -b 7-` + printf "%7d " $N + # read permissions? + if [ ! -r $N/exe ] ; then + if !(root_privs) ; then + printf "\033[31mNo read permissions for '/proc/$N/exe' (run as root).\033[m\n\n" + exit 1 + fi + if [ ! `readlink $N/exe` ] ; then + printf "\033[31mPermission denied. Requested process ID belongs to a kernel thread.\033[m\n\n" + exit 1 + fi + exit 1 + fi + proccheck $N + echo + libcheck $N + fi + exit 0 + ;; + + --kernel) + cd /proc + printf "* Kernel protection information:\n\n" + kernelcheck + exit 0 + ;; + + --fortify-file) + if [ $have_readelf -eq 0 ] ; then + exit 1 + fi + if [ -z "$2" ] ; then + printf "\033[31mError: Please provide a valid file.\033[m\n\n" + exit 1 + fi + # does the file exist? + if [ ! -e $2 ] ; then + printf "\033[31mError: The file '$2' does not exist.\033[m\n\n" + exit 1 + fi + # read permissions? + if [ ! -r $2 ] ; then + printf "\033[31mError: No read permissions for '$2' (run as root).\033[m\n\n" + exit 1 + fi + # ELF executable? + out=`file $2` + if [[ ! $out =~ ELF ]] ; then + printf "\033[31mError: Not an ELF file: " + file $2 + printf "\033[m\n" + exit 1 + fi + if [ -e /lib/libc.so.6 ] ; then + FS_libc=/lib/libc.so.6 + elif [ -e /lib64/libc.so.6 ] ; then + FS_libc=/lib64/libc.so.6 + elif [ -e /lib/i386-linux-gnu/libc.so.6 ] ; then + FS_libc=/lib/i386-linux-gnu/libc.so.6 + elif [ -e /lib/x86_64-linux-gnu/libc.so.6 ] ; then + FS_libc=/lib/x86_64-linux-gnu/libc.so.6 + else + printf "\033[31mError: libc not found.\033[m\n\n" + exit 1 + fi + + FS_chk_func_libc=( $(readelf -s $FS_libc | grep _chk@@ | awk '{ print $8 }' | cut -c 3- | sed -e 's/_chk@.*//') ) + FS_functions=( $(readelf -s $2 | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//') ) + + FS_libc_check + FS_binary_check + FS_comparison + FS_summary + + exit 0 + ;; + + --fortify-proc) + if [ $have_readelf -eq 0 ] ; then + exit 1 + fi + if [ -z "$2" ] ; then + printf "\033[31mError: Please provide a valid process ID.\033[m\n\n" + exit 1 + fi + if !(isNumeric "$2") ; then + printf "\033[31mError: Please provide a valid process ID.\033[m\n\n" + exit 1 + fi + cd /proc + N=$2 + if [ -d $N ] ; then + # read permissions? + if [ ! -r $N/exe ] ; then + if !(root_privs) ; then + printf "\033[31mNo read permissions for '/proc/$N/exe' (run as root).\033[m\n\n" + exit 1 + fi + if [ ! `readlink $N/exe` ] ; then + printf "\033[31mPermission denied. Requested process ID belongs to a kernel thread.\033[m\n\n" + exit 1 + fi + exit 1 + fi + if [ -e /lib/libc.so.6 ] ; then + FS_libc=/lib/libc.so.6 + elif [ -e /lib64/libc.so.6 ] ; then + FS_libc=/lib64/libc.so.6 + elif [ -e /lib/i386-linux-gnu/libc.so.6 ] ; then + FS_libc=/lib/i386-linux-gnu/libc.so.6 + elif [ -e /lib/x86_64-linux-gnu/libc.so.6 ] ; then + FS_libc=/lib/x86_64-linux-gnu/libc.so.6 + else + printf "\033[31mError: libc not found.\033[m\n\n" + exit 1 + fi + printf "* Process name (PID) : %s (%d)\n" `head -1 $N/status | cut -b 7-` $N + FS_chk_func_libc=( $(readelf -s $FS_libc | grep _chk@@ | awk '{ print $8 }' | cut -c 3- | sed -e 's/_chk@.*//') ) + FS_functions=( $(readelf -s $2/exe | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//') ) + + FS_libc_check + FS_binary_check + FS_comparison + FS_summary + fi + exit 0 + ;; + + *) + if [ "$#" != "0" ] ; then + printf "\033[31mError: Unknown option '$1'.\033[m\n\n" + fi + help + exit 1 + ;; +esac diff --git a/meta-security/recipes-security/checksecurity/checksecurity_2.0.15.bb b/meta-security/recipes-security/checksecurity/checksecurity_2.0.15.bb new file mode 100644 index 000000000..a9616911b --- /dev/null +++ b/meta-security/recipes-security/checksecurity/checksecurity_2.0.15.bb @@ -0,0 +1,20 @@ +SUMMARY = "basic system security checks" +DESCRIPTION = "checksecurity is a simple package which will scan your system for several simple security holes." +SECTION = "security" +LICENSE = "GPL-2.0" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6" + +SRC_URI = "http://ftp.de.debian.org/debian/pool/main/c/checksecurity/checksecurity_${PV}.tar.gz \ + file://setuid-log-folder.patch" + +SRC_URI[md5sum] = "a30161c3e24d3be710b2fd13fcd1f32f" +SRC_URI[sha256sum] = "67abe3d6391c96146e96f376d3fd6eb7a9418b0f7fe205b465219889791dba32" + +do_compile() { +} + +do_install() { + oe_runmake PREFIX=${D} +} + +RDEPENDS_${PN} = "perl libenv-perl perl-module-tie-array perl-module-getopt-long perl-module-file-glob util-linux findutils coreutils" diff --git a/meta-security/recipes-security/checksecurity/files/setuid-log-folder.patch b/meta-security/recipes-security/checksecurity/files/setuid-log-folder.patch new file mode 100644 index 000000000..540ea9c31 --- /dev/null +++ b/meta-security/recipes-security/checksecurity/files/setuid-log-folder.patch @@ -0,0 +1,52 @@ +From 24dbeec135ff83f2fd35ef12fe9842f02d6fd337 Mon Sep 17 00:00:00 2001 +From: Andrei Dinu <andrei.adrianx.dinu@intel.com> +Date: Thu, 20 Jun 2013 15:14:55 +0300 +Subject: [PATCH] changed log folder for check-setuid + +check-setuid was creating logs in /var/log directory, +which cannot be created persistently. To avoid errors +the log folder was changed to /etc/checksecurity/. + +Signed-off-by: Andrei Dinu <andrei.adrianx.dinu@intel.com> +--- + etc/check-setuid.conf | 2 +- + plugins/check-setuid | 6 +++--- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/etc/check-setuid.conf b/etc/check-setuid.conf +index 621336f..e1532c0 100644 +--- a/etc/check-setuid.conf ++++ b/etc/check-setuid.conf +@@ -116,4 +116,4 @@ CHECKSECURITY_PATHFILTER="-false" + # + # Location of setuid file databases. + # +-LOGDIR=/var/log/setuid ++LOGDIR=/etc/checksecurity/ +diff --git a/plugins/check-setuid b/plugins/check-setuid +index 8d6f90b..bdb21c1 100755 +--- a/plugins/check-setuid ++++ b/plugins/check-setuid +@@ -44,8 +44,8 @@ if [ `/usr/bin/id -u` != 0 ] ; then + exit 1 + fi + +-TMPSETUID=${LOGDIR:=/var/log/setuid}/setuid.new.tmp +-TMPDIFF=${LOGDIR:=/var/log/setuid}/setuid.diff.tmp ++TMPSETUID=${LOGDIR:=/etc/checksecurity/}/setuid.new.tmp ++TMPDIFF=${LOGDIR:=/etc/checksecurity/}/setuid.diff.tmp + + # + # Check for NFS/AFS mounts that are not nosuid/nodev +@@ -75,7 +75,7 @@ if [ "$CHECKSECURITY_NOFINDERRORS" = "TRUE" ] ; then + fi + + # Guard against undefined vars +-[ -z "$LOGDIR" ] && LOGDIR=/var/log/setuid ++[ -z "$LOGDIR" ] && LOGDIR=/etc/checksecurity/ + if [ ! -e "$LOGDIR" ] ; then + echo "ERROR: Log directory $LOGDIR does not exist" + exit 1 +-- +1.7.9.5 + diff --git a/meta-security/recipes-security/clamav/clamav_0.99.3.bb b/meta-security/recipes-security/clamav/clamav_0.99.3.bb new file mode 100644 index 000000000..688250da4 --- /dev/null +++ b/meta-security/recipes-security/clamav/clamav_0.99.3.bb @@ -0,0 +1,158 @@ +SUMMARY = "ClamAV anti-virus utility for Unix - command-line interface" +DESCRIPTION = "ClamAV is an open source antivirus engine for detecting trojans, viruses, malware & other malicious threats." +HOMEPAGE = "http://www.clamav.net/index.html" +SECTION = "security" +LICENSE = "LGPL-2.1" + +DEPENDS = "libtool db libmspack chrpath-replacement-native" + +LIC_FILES_CHKSUM = "file://COPYING.LGPL;beginline=2;endline=3;md5=4b89c05acc71195e9a06edfa2fa7d092" + +SRCREV = "224f73461a44e278e9fa50ba59f51ee5e64373e0" + +SRC_URI = "git://github.com/vrtadmin/clamav-devel;branch=rel/0.99 \ + file://clamd.conf \ + file://freshclam.conf \ + file://volatiles.03_clamav \ + file://${BPN}.service \ + " + +S = "${WORKDIR}/git" + +LEAD_SONAME = "libclamav.so" +SO_VER = "7.1.1" + +EXTRANATIVEPATH += "chrpath-native" + +inherit autotools-brokensep pkgconfig useradd systemd + +UID = "clamav" +GID = "clamav" + +# Clamav has a built llvm version 2 but does not build with gcc 6.x, +# disable the internal one. This is a known issue +# If you want LLVM support, use meta-oe llvm3.3 to build for GCC 6.X, +# as defined below + +CLAMAV_LLVM ?= "oellvm" +CLAMAV_LLVM_RELEASE ?= "6.0" + +PACKAGECONFIG ?= "ncurses openssl bz2 zlib ${CLAMAV_LLVM}" +PACKAGECONFIG += " ${@bb.utils.contains("DISTRO_FEATURES", "ipv6", "ipv6", "", d)}" +PACKAGECONFIG += "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd', '', d)}" + +PACKAGECONFIG[oellvm] = "--with-system-llvm --with-llvm-linking=dynamic --disable-llvm, ,llvm${CLAMAV_LLVM_RELEASE}" + +PACKAGECONFIG[pcre] = "--with-pcre=${STAGING_LIBDIR}, --without-pcre, libpcre" +PACKAGECONFIG[xml] = "--with-xml=${STAGING_LIBDIR}/.., --with-xml=no, libxml2," +PACKAGECONFIG[json] = "--with-libjson=${STAGING_LIBDIR}, --without-libjson, json," +PACKAGECONFIG[curl] = "--with-libcurl=${STAGING_LIBDIR}, --without-libcurl, curl," +PACKAGECONFIG[ipv6] = "--enable-ipv6, --disable-ipv6" +PACKAGECONFIG[openssl] = "--with-openssl=${STAGING_DIR_HOST}/usr, --without-openssl, openssl, openssl" +PACKAGECONFIG[zlib] = "--with-zlib=${STAGING_DIR_HOST}/usr --disable-zlib-vcheck , --without-zlib, zlib, " +PACKAGECONFIG[bz2] = "--with-libbz2-prefix=${STAGING_LIBDIR}/.., --without-libbz2-prefix, " +PACKAGECONFIG[ncurses] = "--with-libncurses-prefix=${STAGING_LIBDIR}/.., --without-libncurses-prefix, ncurses, " +PACKAGECONFIG[systemd] = "--with-systemdsystemunitdir=${systemd_unitdir}/system/, --without-systemdsystemunitdir, " + +EXTRA_OECONF += " --with-user=${UID} --with-group=${GID} \ + --without-libcheck-prefix --disable-unrar \ + --disable-mempool \ + --program-prefix="" \ + --disable-yara \ + --disable-rpath \ + " + +do_configure () { + cd ${S} + ./configure ${CONFIGUREOPTS} ${EXTRA_OECONF} +} + +do_compile_append() { + # brute force removing RPATH + chrpath -d ${B}/libclamav/.libs/libclamav.so.${SO_VER} + chrpath -d ${B}/sigtool/.libs/sigtool + chrpath -d ${B}/clambc/.libs/clambc + chrpath -d ${B}/clamscan/.libs/clamscan + chrpath -d ${B}/clamconf/.libs/clamconf + chrpath -d ${B}/clamd/.libs/clamd + chrpath -d ${B}/freshclam/.libs/freshclam +} + +do_install_append() { + install -d ${D}/${sysconfdir} + install -d ${D}/${localstatedir}/lib/clamav + install -d ${D}${sysconfdir}/clamav ${D}${sysconfdir}/default/volatiles + + install -m 644 ${WORKDIR}/clamd.conf ${D}/${sysconfdir} + install -m 644 ${WORKDIR}/freshclam.conf ${D}/${sysconfdir} + install -m 0644 ${WORKDIR}/volatiles.03_clamav ${D}${sysconfdir}/default/volatiles/volatiles.03_clamav + sed -i -e 's#${STAGING_DIR_HOST}##g' ${D}${libdir}/pkgconfig/libclamav.pc + rm ${D}/${libdir}/libclamav.so + if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)};then + install -D -m 0644 ${WORKDIR}/clamav.service ${D}${systemd_unitdir}/system/clamav.service + fi +} + +pkg_postinst_ontarget_${PN} () { + if [ -e /etc/init.d/populate-volatile.sh ] ; then + ${sysconfdir}/init.d/populate-volatile.sh update + fi + chown ${UID}:${GID} ${localstatedir}/lib/clamav +} + + +PACKAGES = "${PN} ${PN}-dev ${PN}-dbg ${PN}-daemon ${PN}-doc \ + ${PN}-clamdscan ${PN}-freshclam ${PN}-libclamav ${PN}-staticdev" + +FILES_${PN} = "${bindir}/clambc ${bindir}/clamscan ${bindir}/clamsubmit \ + ${bindir}/*sigtool ${mandir}/man1/clambc* ${mandir}/man1/clamscan* \ + ${mandir}/man1/sigtool* ${mandir}/man1/clambsubmit* \ + ${docdir}/clamav/* " + +FILES_${PN}-clamdscan = " ${bindir}/clamdscan \ + ${docdir}/clamdscan/* \ + ${mandir}/man1/clamdscan* \ + " + +FILES_${PN}-daemon = "${bindir}/clamconf ${bindir}/clamdtop ${sbindir}/clamd \ + ${mandir}/man1/clamconf* ${mandir}/man1/clamdtop* \ + ${mandir}/man5/clamd* ${mandir}/man8/clamd* \ + ${sysconfdir}/clamd.conf* \ + ${systemd_unitdir}/system/clamav-daemon/* \ + ${docdir}/clamav-daemon/* ${sysconfdir}/clamav-daemon \ + ${sysconfdir}/logcheck/ignore.d.server/clamav-daemon " + +FILES_${PN}-freshclam = "${bindir}/freshclam \ + ${sysconfdir}/freshclam.conf* \ + ${sysconfdir}/clamav ${sysconfdir}/default/volatiles \ + ${localstatedir}/lib/clamav \ + ${docdir}/${PN}-freshclam ${mandir}/man1/freshclam.* \ + ${mandir}/man5/freshclam.conf.* \ + ${systemd_unitdir}/system/clamav-freshclam.service" + +FILES_${PN}-dev = " ${bindir}/clamav-config ${libdir}/*.la \ + ${libdir}/pkgconfig/*.pc \ + ${mandir}/man1/clamav-config.* \ + ${includedir}/*.h ${docdir}/libclamav* " + +FILES_${PN}-staticdev = "${libdir}/*.a" + +FILES_${PN}-libclamav = "${libdir}/libclamav.so* ${libdir}/libmspack.so*\ + ${docdir}/libclamav/* " + +FILES_${PN}-doc = "${mandir}/man/* \ + ${datadir}/man/* \ + ${docdir}/* " + +USERADD_PACKAGES = "${PN}" +GROUPADD_PARAM_${PN} = "--system ${UID}" +USERADD_PARAM_${PN} = "--system -g ${GID} --home-dir \ + ${localstatedir}/spool/${BPN} \ + --no-create-home --shell /bin/false ${BPN}" + +RPROVIDES_${PN} += "${PN}-systemd" +RREPLACES_${PN} += "${PN}-systemd" +RCONFLICTS_${PN} += "${PN}-systemd" +SYSTEMD_SERVICE_${PN} = "${BPN}.service" + +RDEPENDS_${PN} += "openssl ncurses-libncurses libbz2 ncurses-libtinfo clamav-freshclam clamav-libclamav" diff --git a/meta-security/recipes-security/clamav/files/clamav-freshclam.service b/meta-security/recipes-security/clamav/files/clamav-freshclam.service new file mode 100644 index 000000000..0c909fb32 --- /dev/null +++ b/meta-security/recipes-security/clamav/files/clamav-freshclam.service @@ -0,0 +1,12 @@ +[Unit] +Description=ClamAV virus database updater +Documentation=man:freshclam(1) man:freshclam.conf(5) http://www.clamav.net/lang/en/doc/ +# If user wants it run from cron, don't start the daemon. +ConditionPathExists=!/etc/cron.d/clamav-freshclam + +[Service] +ExecStart=/usr/bin/freshclam -d --foreground=true +StandardOutput=syslog + +[Install] +WantedBy=multi-user.target diff --git a/meta-security/recipes-security/clamav/files/clamav-milter.conf.sample b/meta-security/recipes-security/clamav/files/clamav-milter.conf.sample new file mode 100644 index 000000000..ed0d519ff --- /dev/null +++ b/meta-security/recipes-security/clamav/files/clamav-milter.conf.sample @@ -0,0 +1,293 @@ +## +## Example config file for clamav-milter +## + +# Comment or remove the line below. +Example + + +## +## Main options +## + +# Define the interface through which we communicate with sendmail +# This option is mandatory! Possible formats are: +# [[unix|local]:]/path/to/file - to specify a unix domain socket +# inet:port@[hostname|ip-address] - to specify an ipv4 socket +# inet6:port@[hostname|ip-address] - to specify an ipv6 socket +# +# Default: no default +#MilterSocket /tmp/clamav-milter.socket +#MilterSocket inet:7357 + +# Define the group ownership for the (unix) milter socket. +# Default: disabled (the primary group of the user running clamd) +#MilterSocketGroup virusgroup + +# Sets the permissions on the (unix) milter socket to the specified mode. +# Default: disabled (obey umask) +#MilterSocketMode 660 + +# Remove stale socket after unclean shutdown. +# +# Default: yes +#FixStaleSocket yes + +# Run as another user (clamav-milter must be started by root for this option to work) +# +# Default: unset (don't drop privileges) +#User clamav + +# Initialize supplementary group access (clamav-milter must be started by root). +# +# Default: no +#AllowSupplementaryGroups no + +# Waiting for data from clamd will timeout after this time (seconds). +# Value of 0 disables the timeout. +# +# Default: 120 +#ReadTimeout 300 + +# Don't fork into background. +# +# Default: no +#Foreground yes + +# Chroot to the specified directory. +# Chrooting is performed just after reading the config file and before dropping privileges. +# +# Default: unset (don't chroot) +#Chroot /newroot + +# This option allows you to save a process identifier of the listening +# daemon (main thread). +# +# Default: disabled +#PidFile /var/run/clamav/clamav-milter.pid + +# Optional path to the global temporary directory. +# Default: system specific (usually /tmp or /var/tmp). +# +#TemporaryDirectory /var/tmp + +## +## Clamd options +## + +# Define the clamd socket to connect to for scanning. +# This option is mandatory! Syntax: +# ClamdSocket unix:path +# ClamdSocket tcp:host:port +# The first syntax specifies a local unix socket (needs an absolute path) e.g.: +# ClamdSocket unix:/var/run/clamd/clamd.socket +# The second syntax specifies a tcp local or remote tcp socket: the +# host can be a hostname or an ip address; the ":port" field is only required +# for IPv6 addresses, otherwise it defaults to 3310, e.g.: +# ClamdSocket tcp:192.168.0.1 +# +# This option can be repeated several times with different sockets or even +# with the same socket: clamd servers will be selected in a round-robin fashion. +# +# Default: no default +ClamdSocket /var/run/clamav/clamd + + +## +## Exclusions +## + +# Messages originating from these hosts/networks will not be scanned +# This option takes a host(name)/mask pair in CIRD notation and can be +# repeated several times. If "/mask" is omitted, a host is assumed. +# To specify a locally orignated, non-smtp, email use the keyword "local" +# +# Default: unset (scan everything regardless of the origin) +#LocalNet local +#LocalNet 192.168.0.0/24 +#LocalNet 1111:2222:3333::/48 + +# This option specifies a file which contains a list of basic POSIX regular +# expressions. Addresses (sent to or from - see below) matching these regexes +# will not be scanned. Optionally each line can start with the string "From:" +# or "To:" (note: no whitespace after the colon) indicating if it is, +# respectively, the sender or recipient that is to be whitelisted. +# If the field is missing, "To:" is assumed. +# Lines starting with #, : or ! are ignored. +# +# Default unset (no exclusion applied) +#Whitelist /etc/whitelisted_addresses + +# Messages from authenticated SMTP users matching this extended POSIX +# regular expression (egrep-like) will not be scanned. +# As an alternative, a file containing a plain (not regex) list of names (one +# per line) can be specified using the prefix "file:". +# e.g. SkipAuthenticated file:/etc/good_guys +# +# Note: this is the AUTH login name! +# +# Default: unset (no whitelisting based on SMTP auth) +#SkipAuthenticated ^(tom|dick|henry)$ + +# Messages larger than this value won't be scanned. +# Make sure this value is lower or equal than StreamMaxLength in clamd.conf +# +# Default: 25M +#MaxFileSize 10M + + +## +## Actions +## + +# The following group of options controls the delievery process under +# different circumstances. +# The following actions are available: +# - Accept +# The message is accepted for delievery +# - Reject +# Immediately refuse delievery (a 5xx error is returned to the peer) +# - Defer +# Return a temporary failure message (4xx) to the peer +# - Blackhole (not available for OnFail) +# Like Accept but the message is sent to oblivion +# - Quarantine (not available for OnFail) +# Like Accept but message is quarantined instead of being delivered +# +# NOTE: In Sendmail the quarantine queue can be examined via mailq -qQ +# For Postfix this causes the message to be placed on hold +# +# Action to be performed on clean messages (mostly useful for testing) +# Default: Accept +#OnClean Accept + +# Action to be performed on infected messages +# Default: Quarantine +#OnInfected Quarantine + +# Action to be performed on error conditions (this includes failure to +# allocate data structures, no scanners available, network timeouts, +# unknown scanner replies and the like) +# Default: Defer +#OnFail Defer + +# This option allows to set a specific rejection reason for infected messages +# and it's therefore only useful together with "OnInfected Reject" +# The string "%v", if present, will be replaced with the virus name. +# Default: MTA specific +#RejectMsg + +# If this option is set to "Replace" (or "Yes"), an "X-Virus-Scanned" and an +# "X-Virus-Status" headers will be attached to each processed message, possibly +# replacing existing headers. +# If it is set to Add, the X-Virus headers are added possibly on top of the +# existing ones. +# Note that while "Replace" can potentially break DKIM signatures, "Add" may +# confuse procmail and similar filters. +# Default: no +#AddHeader Replace + +# When AddHeader is in use, this option allows to arbitrary set the reported +# hostname. This may be desirable in order to avoid leaking internal names. +# If unset the real machine name is used. +# Default: disabled +#ReportHostname my.mail.server.name + +# Execute a command (possibly searching PATH) when an infected message is found. +# The following parameters are passed to the invoked program in this order: +# virus name, queue id, sender, destination, subject, message id, message date. +# Note #1: this requires MTA macroes to be available (see LogInfected below) +# Note #2: the process is invoked in the context of clamav-milter +# Note #3: clamav-milter will wait for the process to exit. Be quick or fork to +# avoid unnecessary delays in email delievery +# Default: disabled +#VirusAction /usr/local/bin/my_infected_message_handler + +## +## Logging options +## + +# Uncomment this option to enable logging. +# LogFile must be writable for the user running daemon. +# A full path is required. +# +# Default: disabled +#LogFile /var/log/clamav/clamav-milter.log + +# By default the log file is locked for writing - the lock protects against +# running clamav-milter multiple times. +# This option disables log file locking. +# +# Default: no +#LogFileUnlock yes + +# Maximum size of the log file. +# Value of 0 disables the limit. +# You may use 'M' or 'm' for megabytes (1M = 1m = 1048576 bytes) +# and 'K' or 'k' for kilobytes (1K = 1k = 1024 bytes). To specify the size +# in bytes just don't use modifiers. If LogFileMaxSize is enabled, log +# rotation (the LogRotate option) will always be enabled. +# +# Default: 1M +#LogFileMaxSize 2M + +# Log time with each message. +# +# Default: no +#LogTime yes + +# Use system logger (can work together with LogFile). +# +# Default: no +#LogSyslog yes + +# Specify the type of syslog messages - please refer to 'man syslog' +# for facility names. +# +# Default: LOG_LOCAL6 +#LogFacility LOG_MAIL + +# Enable verbose logging. +# +# Default: no +#LogVerbose yes + +# Enable log rotation. Always enabled when LogFileMaxSize is enabled. +# Default: no +#LogRotate yes + +# This option allows to tune what is logged when a message is infected. +# Possible values are Off (the default - nothing is logged), +# Basic (minimal info logged), Full (verbose info logged) +# Note: +# For this to work properly in sendmail, make sure the msg_id, mail_addr, +# rcpt_addr and i macroes are available in eom. In other words add a line like: +# Milter.macros.eom={msg_id}, {mail_addr}, {rcpt_addr}, i +# to your .cf file. Alternatively use the macro: +# define(`confMILTER_MACROS_EOM', `{msg_id}, {mail_addr}, {rcpt_addr}, i') +# Postfix should be working fine with the default settings. +# +# Default: disabled +#LogInfected Basic + +# This option allows to tune what is logged when no threat is found in a scanned message. +# See LogInfected for possible values and caveats. +# Useful in debugging but drastically increases the log size. +# Default: disabled +#LogClean Basic + +# This option affects the behaviour of LogInfected, LogClean and VirusAction +# when a message with multiple recipients is scanned: +# If SupportMultipleRecipients is off (the default) +# then one single log entry is generated for the message and, in case the +# message is determined to be malicious, the command indicated by VirusAction +# is executed just once. In both cases only the last recipient is reported. +# If SupportMultipleRecipients is on: +# then one line is logged for each recipient and the command indicated +# by VirusAction is also executed once for each recipient. +# +# Note: although it's probably a good idea to enable this option, the default value +# is currently set to off for legacy reasons. +# Default: no +#SupportMultipleRecipients yes + diff --git a/meta-security/recipes-security/clamav/files/clamav.service b/meta-security/recipes-security/clamav/files/clamav.service new file mode 100644 index 000000000..f13191fcc --- /dev/null +++ b/meta-security/recipes-security/clamav/files/clamav.service @@ -0,0 +1,17 @@ +[Unit] +Description=Clam AntiVirus userspace daemon +Documentation=man:clamd(8) man:clamd.conf(5) http://www.clamav.net/lang/en/doc/ +Requires=clamav-daemon.socket +# Check for database existence +ConditionPathExistsGlob=/usr/share/clamav/main.{c[vl]d,inc} +ConditionPathExistsGlob=/usr/share/clamav/daily.{c[vl]d,inc} + +[Service] +ExecStart=/usr/sbin/clamd --foreground=true +# Reload the database +ExecReload=/bin/kill -USR2 $MAINPID +StandardOutput=syslog + +[Install] +WantedBy=multi-user.target +Also=clamav-daemon.socket diff --git a/meta-security/recipes-security/clamav/files/clamd.conf b/meta-security/recipes-security/clamav/files/clamd.conf new file mode 100644 index 000000000..045778506 --- /dev/null +++ b/meta-security/recipes-security/clamav/files/clamd.conf @@ -0,0 +1,595 @@ +# Uncomment this option to enable logging. +# LogFile must be writable for the user running daemon. +# A full path is required. +# Default: disabled +LogFile /tmp/clamd.log + +# By default the log file is locked for writing - the lock protects against +# running clamd multiple times (if want to run another clamd, please +# copy the configuration file, change the LogFile variable, and run +# the daemon with --config-file option). +# This option disables log file locking. +# Default: no +LogFileUnlock yes + +# Maximum size of the log file. +# Value of 0 disables the limit. +# You may use 'M' or 'm' for megabytes (1M = 1m = 1048576 bytes) +# and 'K' or 'k' for kilobytes (1K = 1k = 1024 bytes). To specify the size +# in bytes just don't use modifiers. If LogFileMaxSize is enabled, log +# rotation (the LogRotate option) will always be enabled. +# Default: 1M +LogFileMaxSize 2M + +# Log time with each message. +# Default: no +LogTime yes + +# Also log clean files. Useful in debugging but drastically increases the +# log size. +# Default: no +#LogClean yes + +# Use system logger (can work together with LogFile). +# Default: no +#LogSyslog yes + +# Specify the type of syslog messages - please refer to 'man syslog' +# for facility names. +# Default: LOG_LOCAL6 +#LogFacility LOG_MAIL + +# Enable verbose logging. +# Default: no +#LogVerbose yes + +# Enable log rotation. Always enabled when LogFileMaxSize is enabled. +# Default: no +#LogRotate yes + +# Log additional information about the infected file, such as its +# size and hash, together with the virus name. +ExtendedDetectionInfo yes + +# This option allows you to save a process identifier of the listening +# daemon (main thread). +# Default: disabled +PidFile /var/run/clamd.pid + +# Optional path to the global temporary directory. +# Default: system specific (usually /tmp or /var/tmp). +TemporaryDirectory /var/tmp + +# Path to the database directory. +# Default: hardcoded (depends on installation options) +DatabaseDirectory /var/lib/clamav + +# Only load the official signatures published by the ClamAV project. +# Default: no +#OfficialDatabaseOnly no + +# The daemon can work in local mode, network mode or both. +# Due to security reasons we recommend the local mode. + +# Path to a local socket file the daemon will listen on. +# Default: disabled (must be specified by a user) +LocalSocket /tmp/clamd.socket + +# Sets the group ownership on the unix socket. +# Default: disabled (the primary group of the user running clamd) +#LocalSocketGroup virusgroup + +# Sets the permissions on the unix socket to the specified mode. +# Default: disabled (socket is world accessible) +#LocalSocketMode 660 + +# Remove stale socket after unclean shutdown. +# Default: yes +#FixStaleSocket yes + +# TCP port address. +# Default: no +#TCPSocket 3310 + +# TCP address. +# By default we bind to INADDR_ANY, probably not wise. +# Enable the following to provide some degree of protection +# from the outside world. This option can be specified multiple +# times if you want to listen on multiple IPs. IPv6 is now supported. +# Default: no +#TCPAddr 127.0.0.1 + +# Maximum length the queue of pending connections may grow to. +# Default: 200 +#MaxConnectionQueueLength 30 + +# Clamd uses FTP-like protocol to receive data from remote clients. +# If you are using clamav-milter to balance load between remote clamd daemons +# on firewall servers you may need to tune the options below. + +# Close the connection when the data size limit is exceeded. +# The value should match your MTA's limit for a maximum attachment size. +# Default: 25M +#StreamMaxLength 10M + +# Limit port range. +# Default: 1024 +#StreamMinPort 30000 +# Default: 2048 +#StreamMaxPort 32000 + +# Maximum number of threads running at the same time. +# Default: 10 +#MaxThreads 20 + +# Waiting for data from a client socket will timeout after this time (seconds). +# Default: 120 +#ReadTimeout 300 + +# This option specifies the time (in seconds) after which clamd should +# timeout if a client doesn't provide any initial command after connecting. +# Default: 5 +#CommandReadTimeout 5 + +# This option specifies how long to wait (in miliseconds) if the send buffer is full. +# Keep this value low to prevent clamd hanging +# +# Default: 500 +#SendBufTimeout 200 + +# Maximum number of queued items (including those being processed by MaxThreads threads) +# It is recommended to have this value at least twice MaxThreads if possible. +# WARNING: you shouldn't increase this too much to avoid running out of file descriptors, +# the following condition should hold: +# MaxThreads*MaxRecursion + (MaxQueue - MaxThreads) + 6< RLIMIT_NOFILE (usual max is 1024) +# +# Default: 100 +#MaxQueue 200 + +# Waiting for a new job will timeout after this time (seconds). +# Default: 30 +#IdleTimeout 60 + +# Don't scan files and directories matching regex +# This directive can be used multiple times +# Default: scan all +#ExcludePath ^/proc/ +#ExcludePath ^/sys/ + +# Maximum depth directories are scanned at. +# Default: 15 +#MaxDirectoryRecursion 20 + +# Follow directory symlinks. +# Default: no +#FollowDirectorySymlinks yes + +# Follow regular file symlinks. +# Default: no +#FollowFileSymlinks yes + +# Scan files and directories on other filesystems. +# Default: yes +#CrossFilesystems yes + +# Perform a database check. +# Default: 600 (10 min) +#SelfCheck 600 + +# Execute a command when virus is found. In the command string %v will +# be replaced with the virus name. +# Default: no +#VirusEvent /usr/local/bin/send_sms 123456789 "VIRUS ALERT: %v" + +# Run as another user (clamd must be started by root for this option to work) +# Default: don't drop privileges +User clamav + +# Initialize supplementary group access (clamd must be started by root). +# Default: no +#AllowSupplementaryGroups no + +# Stop daemon when libclamav reports out of memory condition. +#ExitOnOOM yes + +# Don't fork into background. +# Default: no +#Foreground yes + +# Enable debug messages in libclamav. +# Default: no +#Debug yes + +# Do not remove temporary files (for debug purposes). +# Default: no +#LeaveTemporaryFiles yes + +# Permit use of the ALLMATCHSCAN command. If set to no, clamd will reject +# any ALLMATCHSCAN command as invalid. +# Default: yes +#AllowAllMatchScan no + +# Detect Possibly Unwanted Applications. +# Default: no +#DetectPUA yes + +# Exclude a specific PUA category. This directive can be used multiple times. +# See https://github.com/vrtadmin/clamav-faq/blob/master/faq/faq-pua.md for +# the complete list of PUA categories. +# Default: Load all categories (if DetectPUA is activated) +#ExcludePUA NetTool +#ExcludePUA PWTool + +# Only include a specific PUA category. This directive can be used multiple +# times. +# Default: Load all categories (if DetectPUA is activated) +#IncludePUA Spy +#IncludePUA Scanner +#IncludePUA RAT + +# In some cases (eg. complex malware, exploits in graphic files, and others), +# ClamAV uses special algorithms to provide accurate detection. This option +# controls the algorithmic detection. +# Default: yes +#AlgorithmicDetection yes + +# This option causes memory or nested map scans to dump the content to disk. +# If you turn on this option, more data is written to disk and is available +# when the LeaveTemporaryFiles option is enabled. +#ForceToDisk yes + +# This option allows you to disable the caching feature of the engine. By +# default, the engine will store an MD5 in a cache of any files that are +# not flagged as virus or that hit limits checks. Disabling the cache will +# have a negative performance impact on large scans. +# Default: no +#DisableCache yes + +## +## Executable files +## + +# PE stands for Portable Executable - it's an executable file format used +# in all 32 and 64-bit versions of Windows operating systems. This option allows +# ClamAV to perform a deeper analysis of executable files and it's also +# required for decompression of popular executable packers such as UPX, FSG, +# and Petite. If you turn off this option, the original files will still be +# scanned, but without additional processing. +# Default: yes +#ScanPE yes + +# Certain PE files contain an authenticode signature. By default, we check +# the signature chain in the PE file against a database of trusted and +# revoked certificates if the file being scanned is marked as a virus. +# If any certificate in the chain validates against any trusted root, but +# does not match any revoked certificate, the file is marked as whitelisted. +# If the file does match a revoked certificate, the file is marked as virus. +# The following setting completely turns off authenticode verification. +# Default: no +#DisableCertCheck yes + +# Executable and Linking Format is a standard format for UN*X executables. +# This option allows you to control the scanning of ELF files. +# If you turn off this option, the original files will still be scanned, but +# without additional processing. +# Default: yes +#ScanELF yes + +# With this option clamav will try to detect broken executables (both PE and +# ELF) and mark them as Broken.Executable. +# Default: no +#DetectBrokenExecutables yes + + +## +## Documents +## + +# This option enables scanning of OLE2 files, such as Microsoft Office +# documents and .msi files. +# If you turn off this option, the original files will still be scanned, but +# without additional processing. +# Default: yes +#ScanOLE2 yes + +# With this option enabled OLE2 files with VBA macros, which were not +# detected by signatures will be marked as "Heuristics.OLE2.ContainsMacros". +# Default: no +#OLE2BlockMacros no + +# This option enables scanning within PDF files. +# If you turn off this option, the original files will still be scanned, but +# without decoding and additional processing. +# Default: yes +#ScanPDF yes + +# This option enables scanning within SWF files. +# If you turn off this option, the original files will still be scanned, but +# without decoding and additional processing. +# Default: yes +#ScanSWF yes + + +## +## Mail files +## + +# Enable internal e-mail scanner. +# If you turn off this option, the original files will still be scanned, but +# without parsing individual messages/attachments. +# Default: yes +#ScanMail yes + +# Scan RFC1341 messages split over many emails. +# You will need to periodically clean up $TemporaryDirectory/clamav-partial directory. +# WARNING: This option may open your system to a DoS attack. +# Never use it on loaded servers. +# Default: no +#ScanPartialMessages yes + +# With this option enabled ClamAV will try to detect phishing attempts by using +# signatures. +# Default: yes +#PhishingSignatures yes + +# Scan URLs found in mails for phishing attempts using heuristics. +# Default: yes +#PhishingScanURLs yes + +# Always block SSL mismatches in URLs, even if the URL isn't in the database. +# This can lead to false positives. +# +# Default: no +#PhishingAlwaysBlockSSLMismatch no + +# Always block cloaked URLs, even if URL isn't in database. +# This can lead to false positives. +# +# Default: no +#PhishingAlwaysBlockCloak no + +# Detect partition intersections in raw disk images using heuristics. +# Default: no +#PartitionIntersection no + +# Allow heuristic match to take precedence. +# When enabled, if a heuristic scan (such as phishingScan) detects +# a possible virus/phish it will stop scan immediately. Recommended, saves CPU +# scan-time. +# When disabled, virus/phish detected by heuristic scans will be reported only at +# the end of a scan. If an archive contains both a heuristically detected +# virus/phish, and a real malware, the real malware will be reported +# +# Keep this disabled if you intend to handle "*.Heuristics.*" viruses +# differently from "real" malware. +# If a non-heuristically-detected virus (signature-based) is found first, +# the scan is interrupted immediately, regardless of this config option. +# +# Default: no +#HeuristicScanPrecedence yes + + +## +## Data Loss Prevention (DLP) +## + +# Enable the DLP module +# Default: No +#StructuredDataDetection yes + +# This option sets the lowest number of Credit Card numbers found in a file +# to generate a detect. +# Default: 3 +#StructuredMinCreditCardCount 5 + +# This option sets the lowest number of Social Security Numbers found +# in a file to generate a detect. +# Default: 3 +#StructuredMinSSNCount 5 + +# With this option enabled the DLP module will search for valid +# SSNs formatted as xxx-yy-zzzz +# Default: yes +#StructuredSSNFormatNormal yes + +# With this option enabled the DLP module will search for valid +# SSNs formatted as xxxyyzzzz +# Default: no +#StructuredSSNFormatStripped yes + + +## +## HTML +## + +# Perform HTML normalisation and decryption of MS Script Encoder code. +# Default: yes +# If you turn off this option, the original files will still be scanned, but +# without additional processing. +#ScanHTML yes + + +## +## Archives +## + +# ClamAV can scan within archives and compressed files. +# If you turn off this option, the original files will still be scanned, but +# without unpacking and additional processing. +# Default: yes +#ScanArchive yes + +# Mark encrypted archives as viruses (Encrypted.Zip, Encrypted.RAR). +# Default: no +#ArchiveBlockEncrypted no + + +## +## Limits +## + +# The options below protect your system against Denial of Service attacks +# using archive bombs. + +# This option sets the maximum amount of data to be scanned for each input file. +# Archives and other containers are recursively extracted and scanned up to this +# value. +# Value of 0 disables the limit +# Note: disabling this limit or setting it too high may result in severe damage +# to the system. +# Default: 100M +#MaxScanSize 150M + +# Files larger than this limit won't be scanned. Affects the input file itself +# as well as files contained inside it (when the input file is an archive, a +# document or some other kind of container). +# Value of 0 disables the limit. +# Note: disabling this limit or setting it too high may result in severe damage +# to the system. +# Default: 25M +#MaxFileSize 30M + +# Nested archives are scanned recursively, e.g. if a Zip archive contains a RAR +# file, all files within it will also be scanned. This options specifies how +# deeply the process should be continued. +# Note: setting this limit too high may result in severe damage to the system. +# Default: 16 +#MaxRecursion 10 + +# Number of files to be scanned within an archive, a document, or any other +# container file. +# Value of 0 disables the limit. +# Note: disabling this limit or setting it too high may result in severe damage +# to the system. +# Default: 10000 +#MaxFiles 15000 + +# Maximum size of a file to check for embedded PE. Files larger than this value +# will skip the additional analysis step. +# Note: disabling this limit or setting it too high may result in severe damage +# to the system. +# Default: 10M +#MaxEmbeddedPE 10M + +# Maximum size of a HTML file to normalize. HTML files larger than this value +# will not be normalized or scanned. +# Note: disabling this limit or setting it too high may result in severe damage +# to the system. +# Default: 10M +#MaxHTMLNormalize 10M + +# Maximum size of a normalized HTML file to scan. HTML files larger than this +# value after normalization will not be scanned. +# Note: disabling this limit or setting it too high may result in severe damage +# to the system. +# Default: 2M +#MaxHTMLNoTags 2M + +# Maximum size of a script file to normalize. Script content larger than this +# value will not be normalized or scanned. +# Note: disabling this limit or setting it too high may result in severe damage +# to the system. +# Default: 5M +#MaxScriptNormalize 5M + +# Maximum size of a ZIP file to reanalyze type recognition. ZIP files larger +# than this value will skip the step to potentially reanalyze as PE. +# Note: disabling this limit or setting it too high may result in severe damage +# to the system. +# Default: 1M +#MaxZipTypeRcg 1M + +# This option sets the maximum number of partitions of a raw disk image to be scanned. +# Raw disk images with more partitions than this value will have up to the value number +# partitions scanned. Negative values are not allowed. +# Note: setting this limit too high may result in severe damage or impact performance. +# Default: 50 +#MaxPartitions 128 + +# This option sets the maximum number of icons within a PE to be scanned. +# PE files with more icons than this value will have up to the value number icons scanned. +# Negative values are not allowed. +# WARNING: setting this limit too high may result in severe damage or impact performance. +# Default: 100 +#MaxIconsPE 200 + +## +## On-access Scan Settings +## + +# Enable on-access scanning. Currently, this is supported via fanotify. +# Clamuko/Dazuko support has been deprecated. +# Default: no +#ScanOnAccess yes + +# Don't scan files larger than OnAccessMaxFileSize +# Value of 0 disables the limit. +# Default: 5M +#OnAccessMaxFileSize 10M + +# Set the include paths (all files inside them will be scanned). You can have +# multiple OnAccessIncludePath directives but each directory must be added +# in a separate line. (On-access scan only) +# Default: disabled +#OnAccessIncludePath /home +#OnAccessIncludePath /students + +# Set the exclude paths. All subdirectories are also excluded. +# (On-access scan only) +# Default: disabled +#OnAccessExcludePath /home/bofh + +# With this option you can whitelist specific UIDs. Processes with these UIDs +# will be able to access all files. +# This option can be used multiple times (one per line). +# Default: disabled +#OnAccessExcludeUID 0 + + +## +## Bytecode +## + +# With this option enabled ClamAV will load bytecode from the database. +# It is highly recommended you keep this option on, otherwise you'll miss detections for many new viruses. +# Default: yes +#Bytecode yes + +# Set bytecode security level. +# Possible values: +# None - no security at all, meant for debugging. DO NOT USE THIS ON PRODUCTION SYSTEMS +# This value is only available if clamav was built with --enable-debug! +# TrustSigned - trust bytecode loaded from signed .c[lv]d files, +# insert runtime safety checks for bytecode loaded from other sources +# Paranoid - don't trust any bytecode, insert runtime checks for all +# Recommended: TrustSigned, because bytecode in .cvd files already has these checks +# Note that by default only signed bytecode is loaded, currently you can only +# load unsigned bytecode in --enable-debug mode. +# +# Default: TrustSigned +#BytecodeSecurity TrustSigned + +# Set bytecode timeout in miliseconds. +# +# Default: 5000 +# BytecodeTimeout 1000 + +## +## Statistics gathering and submitting +## + +# Enable statistical reporting. +# Default: no +#StatsEnabled yes + +# Disable submission of individual PE sections for files flagged as malware. +# Default: no +#StatsPEDisabled yes + +# HostID in the form of an UUID to use when submitting statistical information. +# Default: auto +#StatsHostID auto + +# Time in seconds to wait for the stats server to come back with a response +# Default: 10 +#StatsTimeout 10 diff --git a/meta-security/recipes-security/clamav/files/freshclam.conf b/meta-security/recipes-security/clamav/files/freshclam.conf new file mode 100644 index 000000000..100724f16 --- /dev/null +++ b/meta-security/recipes-security/clamav/files/freshclam.conf @@ -0,0 +1,224 @@ +# Path to the database directory. +# WARNING: It must match clamd.conf's directive! +# Default: hardcoded (depends on installation options) +DatabaseDirectory /var/lib/clamav + +# Path to the log file (make sure it has proper permissions) +# Default: disabled +UpdateLogFile /var/log/clamav/freshclam.log + +# Maximum size of the log file. +# Value of 0 disables the limit. +# You may use 'M' or 'm' for megabytes (1M = 1m = 1048576 bytes) +# and 'K' or 'k' for kilobytes (1K = 1k = 1024 bytes). +# in bytes just don't use modifiers. If LogFileMaxSize is enabled, +# log rotation (the LogRotate option) will always be enabled. +# Default: 1M +LogFileMaxSize 2M + +# Log time with each message. +# Default: no +LogTime yes + +# Enable verbose logging. +# Default: no +#LogVerbose yes + +# Use system logger (can work together with UpdateLogFile). +# Default: no +#LogSyslog yes + +# Specify the type of syslog messages - please refer to 'man syslog' +# for facility names. +# Default: LOG_LOCAL6 +#LogFacility LOG_MAIL + +# Enable log rotation. Always enabled when LogFileMaxSize is enabled. +# Default: no +#LogRotate yes + +# This option allows you to save the process identifier of the daemon +# Default: disabled +PidFile /var/run/freshclam.pid + +# By default when started freshclam drops privileges and switches to the +# "clamav" user. This directive allows you to change the database owner. +# Default: clamav (may depend on installation options) +DatabaseOwner clamav + +# Initialize supplementary group access (freshclam must be started by root). +# Default: no +#AllowSupplementaryGroups yes + +# Use DNS to verify virus database version. Freshclam uses DNS TXT records +# to verify database and software versions. With this directive you can change +# the database verification domain. +# WARNING: Do not touch it unless you're configuring freshclam to use your +# own database verification domain. +# Default: current.cvd.clamav.net +#DNSDatabaseInfo current.cvd.clamav.net + +# Uncomment the following line and replace XY with your country +# code. See http://www.iana.org/cctld/cctld-whois.htm for the full list. +# You can use db.XY.ipv6.clamav.net for IPv6 connections. +#DatabaseMirror db.XY.clamav.net + +# database.clamav.net is a round-robin record which points to our most +# reliable mirrors. It's used as a fall back in case db.XY.clamav.net is +# not working. DO NOT TOUCH the following line unless you know what you +# are doing. +DatabaseMirror database.clamav.net + +# How many attempts to make before giving up. +# Default: 3 (per mirror) +#MaxAttempts 5 + +# With this option you can control scripted updates. It's highly recommended +# to keep it enabled. +# Default: yes +#ScriptedUpdates yes + +# By default freshclam will keep the local databases (.cld) uncompressed to +# make their handling faster. With this option you can enable the compression; +# the change will take effect with the next database update. +# Default: no +#CompressLocalDatabase no + +# With this option you can provide custom sources (http:// or file://) for +# database files. This option can be used multiple times. +# Default: no custom URLs +#DatabaseCustomURL http://myserver.com/mysigs.ndb +#DatabaseCustomURL file:///mnt/nfs/local.hdb + +# This option allows you to easily point freshclam to private mirrors. +# If PrivateMirror is set, freshclam does not attempt to use DNS +# to determine whether its databases are out-of-date, instead it will +# use the If-Modified-Since request or directly check the headers of the +# remote database files. For each database, freshclam first attempts +# to download the CLD file. If that fails, it tries to download the +# CVD file. This option overrides DatabaseMirror, DNSDatabaseInfo +# and ScriptedUpdates. It can be used multiple times to provide +# fall-back mirrors. +# Default: disabled +#PrivateMirror mirror1.mynetwork.com +#PrivateMirror mirror2.mynetwork.com + +# Number of database checks per day. +# Default: 12 (every two hours) +#Checks 24 + +# Proxy settings +# Default: disabled +#HTTPProxyServer myproxy.com +#HTTPProxyPort 1234 +#HTTPProxyUsername myusername +#HTTPProxyPassword mypass + +# If your servers are behind a firewall/proxy which applies User-Agent +# filtering you can use this option to force the use of a different +# User-Agent header. +# Default: clamav/version_number +#HTTPUserAgent SomeUserAgentIdString + +# Use aaa.bbb.ccc.ddd as client address for downloading databases. Useful for +# multi-homed systems. +# Default: Use OS'es default outgoing IP address. +#LocalIPAddress aaa.bbb.ccc.ddd + +# Send the RELOAD command to clamd. +# Default: no +#NotifyClamd /path/to/clamd.conf + +# Run command after successful database update. +# Default: disabled +#OnUpdateExecute command + +# Run command when database update process fails. +# Default: disabled +#OnErrorExecute command + +# Run command when freshclam reports outdated version. +# In the command string %v will be replaced by the new version number. +# Default: disabled +#OnOutdatedExecute command + +# Don't fork into background. +# Default: no +#Foreground yes + +# Enable debug messages in libclamav. +# Default: no +#Debug yes + +# Timeout in seconds when connecting to database server. +# Default: 30 +#ConnectTimeout 60 + +# Timeout in seconds when reading from database server. +# Default: 30 +#ReceiveTimeout 60 + +# With this option enabled, freshclam will attempt to load new +# databases into memory to make sure they are properly handled +# by libclamav before replacing the old ones. +# Default: yes +#TestDatabases yes + +# When enabled freshclam will submit statistics to the ClamAV Project about +# the latest virus detections in your environment. The ClamAV maintainers +# will then use this data to determine what types of malware are the most +# detected in the field and in what geographic area they are. +# Freshclam will connect to clamd in order to get recent statistics. +# Default: no +#SubmitDetectionStats /path/to/clamd.conf + +# Country of origin of malware/detection statistics (for statistical +# purposes only). The statistics collector at ClamAV.net will look up +# your IP address to determine the geographical origin of the malware +# reported by your installation. If this installation is mainly used to +# scan data which comes from a different location, please enable this +# option and enter a two-letter code (see http://www.iana.org/domains/root/db/) +# of the country of origin. +# Default: disabled +#DetectionStatsCountry country-code + +# This option enables support for our "Personal Statistics" service. +# When this option is enabled, the information on malware detected by +# your clamd installation is made available to you through our website. +# To get your HostID, log on http://www.stats.clamav.net and add a new +# host to your host list. Once you have the HostID, uncomment this option +# and paste the HostID here. As soon as your freshclam starts submitting +# information to our stats collecting service, you will be able to view +# the statistics of this clamd installation by logging into +# http://www.stats.clamav.net with the same credentials you used to +# generate the HostID. For more information refer to: +# http://www.clamav.net/documentation.html#cctts +# This feature requires SubmitDetectionStats to be enabled. +# Default: disabled +#DetectionStatsHostID unique-id + +# This option enables support for Google Safe Browsing. When activated for +# the first time, freshclam will download a new database file (safebrowsing.cvd) +# which will be automatically loaded by clamd and clamscan during the next +# reload, provided that the heuristic phishing detection is turned on. This +# database includes information about websites that may be phishing sites or +# possible sources of malware. When using this option, it's mandatory to run +# freshclam at least every 30 minutes. +# Freshclam uses the ClamAV's mirror infrastructure to distribute the +# database and its updates but all the contents are provided under Google's +# terms of use. See http://www.google.com/transparencyreport/safebrowsing +# and http://www.clamav.net/documentation.html#safebrowsing +# for more information. +# Default: disabled +#SafeBrowsing yes + +# This option enables downloading of bytecode.cvd, which includes additional +# detection mechanisms and improvements to the ClamAV engine. +# Default: enabled +#Bytecode yes + +# Download an additional 3rd party signature database distributed through +# the ClamAV mirrors. +# This option can be used multiple times. +#ExtraDatabase dbname1 +#ExtraDatabase dbname2 diff --git a/meta-security/recipes-security/clamav/files/volatiles.03_clamav b/meta-security/recipes-security/clamav/files/volatiles.03_clamav new file mode 100644 index 000000000..ee2153cab --- /dev/null +++ b/meta-security/recipes-security/clamav/files/volatiles.03_clamav @@ -0,0 +1,3 @@ +# <type> <owner> <group> <mode> <path> <linksource> +d clamav clamav 0755 /var/log/clamav none +f clamav clamav 0655 /var/log/clamav/freshclam.log none diff --git a/meta-security/recipes-security/ecryptfs-utils/ecryptfs-utils_111.bb b/meta-security/recipes-security/ecryptfs-utils/ecryptfs-utils_111.bb new file mode 100644 index 000000000..f55b0c390 --- /dev/null +++ b/meta-security/recipes-security/ecryptfs-utils/ecryptfs-utils_111.bb @@ -0,0 +1,63 @@ +SUMMARY = "The eCryptfs mount helper and support libraries" +DESCRIPTION = "eCryptfs is a stacked cryptographic filesystem \ + that ships in Linux kernel versions 2.6.19 and above. This \ + package provides the mount helper and supporting libraries \ + to perform key management and mount functions." +HOMEPAGE = "https://launchpad.net/ecryptfs" +SECTION = "base" + +LICENSE = "GPL-2.0" +LIC_FILES_CHKSUM = "file://COPYING;md5=8ca43cbc842c2336e835926c2166c28b" + +DEPENDS = "keyutils libgcrypt intltool-native glib-2.0-native" + +SRC_URI = "\ + https://launchpad.net/ecryptfs/trunk/${PV}/+download/${BPN}_${PV}.orig.tar.gz \ + file://ecryptfs-utils-CVE-2016-6224.patch \ + file://ecryptfs.service \ + " + +SRC_URI[md5sum] = "83513228984f671930752c3518cac6fd" +SRC_URI[sha256sum] = "112cb3e37e81a1ecd8e39516725dec0ce55c5f3df6284e0f4cc0f118750a987f" + +inherit autotools pkgconfig systemd + +SYSTEMD_PACKAGES = "${PN}" +SYSTEMD_SERVICE_${PN} = "ecryptfs.service" + +EXTRA_OECONF = "\ + --libdir=${base_libdir} \ + --disable-pywrap \ + --disable-nls \ + " + +PACKAGECONFIG ??= "nss \ + ${@bb.utils.filter('DISTRO_FEATURES', 'pam', d)} \ + " +PACKAGECONFIG[nss] = "--enable-nss,--disable-nss,nss," +PACKAGECONFIG[openssl] = "--enable-openssl,--disable-openssl,openssl," +PACKAGECONFIG[pam] = "--enable-pam,--disable-pam,libpam," + +do_configure_prepend() { + export NSS_CFLAGS="-I${STAGING_INCDIR}/nspr4 -I${STAGING_INCDIR}/nss3" + export NSS_LIBS="-L${STAGING_BASELIBDIR} -lssl3 -lsmime3 -lnss3 -lsoftokn3 -lnssutil3" + export KEYUTILS_CFLAGS="-I${STAGING_INCDIR}" + export KEYUTILS_LIBS="-L${STAGING_LIBDIR} -lkeyutils" +} + +do_install_append() { + chmod 4755 ${D}${base_sbindir}/mount.ecryptfs_private + mkdir -p ${D}/${libdir} + mv ${D}/${base_libdir}/pkgconfig ${D}/${libdir} + sed -i -e 's:-I${STAGING_INCDIR}::' \ + -e 's:-L${STAGING_LIBDIR}::' ${D}/${libdir}/pkgconfig/libecryptfs.pc + sed -i -e "s: ${base_sbindir}/cryptsetup: ${sbindir}/cryptsetup:" ${D}${bindir}/ecryptfs-setup-swap + if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then + install -D -m 0644 ${WORKDIR}/ecryptfs.service ${D}${systemd_system_unitdir}/ecryptfs.service + fi +} + +FILES_${PN} += "${base_libdir}/security/* ${base_libdir}/ecryptfs/*" + +RDEPENDS_${PN} += "cryptsetup" +RRECOMMENDS_${PN} = "gettext-runtime" diff --git a/meta-security/recipes-security/ecryptfs-utils/files/ecryptfs-utils-CVE-2016-6224.patch b/meta-security/recipes-security/ecryptfs-utils/files/ecryptfs-utils-CVE-2016-6224.patch new file mode 100644 index 000000000..4252f97c3 --- /dev/null +++ b/meta-security/recipes-security/ecryptfs-utils/files/ecryptfs-utils-CVE-2016-6224.patch @@ -0,0 +1,65 @@ +From 558a513ba3100ea5190de1a24cf1fed663367765 Mon Sep 17 00:00:00 2001 +From: Li Zhou <li.zhou@windriver.com> +Date: Mon, 5 Sep 2016 10:28:08 +0800 +Subject: [PATCH] ecryptfs-utils: CVE-2016-6224 + +src/utils/ecryptfs-setup-swap: Prevent unencrypted swap partitions from +being automatically enabled by systemd. This bug affected GPT partitioned +NVMe/MMC drives and resulted in the swap partition being used without +encryption. It also resulted in a usability issue in that users were +erroneously prompted to enter a pass-phrase to unlock their swap partition +at boot. (LP: #1597154) + +the patch comes from: +https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-6224 +https://bazaar.launchpad.net/~ecryptfs/ecryptfs/trunk/revision/882 + +Upstream-Status: backport + +Signed-off-by: Li Zhou <li.zhou@windriver.com> +--- + ChangeLog | 9 +++++++++ + src/utils/ecryptfs-setup-swap | 10 ++++++++-- + 2 files changed, 17 insertions(+), 2 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index d255a94..2c9c73e 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,12 @@ ++ecryptfs-utils-112 ++ [ Jason Gerard DeRose ] ++ * src/utils/ecryptfs-setup-swap: Prevent unencrypted swap partitions from ++ being automatically enabled by systemd. This bug affected GPT partitioned ++ NVMe/MMC drives and resulted in the swap partition being used without ++ encryption. It also resulted in a usability issue in that users were ++ erroneously prompted to enter a pass-phrase to unlock their swap partition ++ at boot. (LP: #1597154) ++ + ecryptfs-utils-74 + [ Michal Hlavinka ] + * Changes for RH/Fedora release +diff --git a/src/utils/ecryptfs-setup-swap b/src/utils/ecryptfs-setup-swap +index 41cf18a..e4785d7 100755 +--- a/src/utils/ecryptfs-setup-swap ++++ b/src/utils/ecryptfs-setup-swap +@@ -166,8 +166,14 @@ for swap in $swaps; do + # If this is a GPT partition, mark it as no-auto mounting, to avoid + # auto-activating it on boot + if [ "$(blkid -p -s PART_ENTRY_SCHEME -o value "$swap")" = "gpt" ]; then +- drive="${swap%[0-9]*}" +- partno="${swap#$drive}" ++ # Correctly handle NVMe/MMC drives, as well as any similar physical ++ # block device that follow the "/dev/foo0p1" pattern (LP: #1597154) ++ if echo "$swap" | grep -qE "^/dev/.+[0-9]+p[0-9]+$"; then ++ drive=$(echo "$swap" | sed "s:\(.\+[0-9]\)p[0-9]\+:\1:") ++ else ++ drive=$(echo "$swap" | sed "s:\(.\+[^0-9]\)[0-9]\+:\1:") ++ fi ++ partno=$(echo "$swap" | sed "s:.\+[^0-9]\([0-9]\+\):\1:") + if [ -b "$drive" ]; then + if printf "x\np\n" | fdisk "$drive" | grep -q "^$swap .* GUID:.*\b63\b"; then + echo "$swap is already marked as no-auto" +-- +1.9.1 + diff --git a/meta-security/recipes-security/ecryptfs-utils/files/ecryptfs.service b/meta-security/recipes-security/ecryptfs-utils/files/ecryptfs.service new file mode 100644 index 000000000..c23a03aa4 --- /dev/null +++ b/meta-security/recipes-security/ecryptfs-utils/files/ecryptfs.service @@ -0,0 +1,9 @@ +[Unit] +Description=A userspace daemon that runs as the user perform file operations under the eCryptfs mount point +After=udev.service + +[Service] +ExecStart=/usr/bin/ecryptfsd -f + +[Install] +WantedBy=multi-user.target diff --git a/meta-security/recipes-security/fail2ban/fail2ban_0.10.2.bb b/meta-security/recipes-security/fail2ban/fail2ban_0.10.2.bb new file mode 100644 index 000000000..7e2deba2d --- /dev/null +++ b/meta-security/recipes-security/fail2ban/fail2ban_0.10.2.bb @@ -0,0 +1,41 @@ +SUMMARY = "Daemon to ban hosts that cause multiple authentication errors." +DESCRIPTION = "Fail2Ban scans log files like /var/log/auth.log and bans IP addresses having too \ +many failed login attempts. It does this by updating system firewall rules to reject new \ +connections from those IP addresses, for a configurable amount of time. Fail2Ban comes \ +out-of-the-box ready to read many standard log files, such as those for sshd and Apache, \ +and is easy to configure to read any log file you choose, for any error you choose." +HOMEPAGE = "http://www.fail2ban.org" + +LICENSE = "GPL-2.0" +LIC_FILES_CHKSUM = "file://COPYING;md5=ecabc31e90311da843753ba772885d9f" + +SRCREV ="a45488465e0dd547eb8479c0fa9fd577c1837213" +SRC_URI = " \ + git://github.com/fail2ban/fail2ban.git;branch=0.10 \ + file://initd \ + file://fail2ban_setup.py \ +" + +inherit update-rc.d setuptools + +S = "${WORKDIR}/git" + +INITSCRIPT_PACKAGES = "${PN}" +INITSCRIPT_NAME = "fail2ban-server" +INITSCRIPT_PARAMS = "defaults 25" + +do_compile_prepend () { + cp ${WORKDIR}/fail2ban_setup.py ${S}/setup.py +} + +do_install_append () { + install -d ${D}/${sysconfdir}/fail2ban + install -d ${D}/${sysconfdir}/init.d + install -m 0755 ${WORKDIR}/initd ${D}${sysconfdir}/init.d/fail2ban-server +} + +FILES_${PN} += "/run" + +INSANE_SKIP_${PN}_append = "already-stripped" + +RDEPENDS_${PN} = "sysklogd iptables sqlite3 python python-pyinotify" diff --git a/meta-security/recipes-security/fail2ban/files/fail2ban_setup.py b/meta-security/recipes-security/fail2ban/files/fail2ban_setup.py new file mode 100755 index 000000000..a5d4ed6cb --- /dev/null +++ b/meta-security/recipes-security/fail2ban/files/fail2ban_setup.py @@ -0,0 +1,175 @@ +#!/usr/bin/env python +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*- +# vi: set ft=python sts=4 ts=4 sw=4 noet : + +# This file is part of Fail2Ban. +# +# Fail2Ban is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Fail2Ban is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Fail2Ban; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +__author__ = "Cyril Jaquier, Steven Hiscocks, Yaroslav Halchenko" +__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2008-2016 Fail2Ban Contributors" +__license__ = "GPL" + +import platform + +try: + import setuptools + from setuptools import setup + from setuptools.command.install import install + from setuptools.command.install_scripts import install_scripts +except ImportError: + setuptools = None + from distutils.core import setup + +# all versions +from distutils.command.build_py import build_py +from distutils.command.build_scripts import build_scripts +if setuptools is None: + from distutils.command.install import install + from distutils.command.install_scripts import install_scripts +try: + # python 3.x + from distutils.command.build_py import build_py_2to3 + from distutils.command.build_scripts import build_scripts_2to3 + _2to3 = True +except ImportError: + # python 2.x + _2to3 = False + +import os +from os.path import isfile, join, isdir, realpath +import sys +import warnings +from glob import glob + +from fail2ban.setup import updatePyExec + +if setuptools and "test" in sys.argv: + import logging + logSys = logging.getLogger("fail2ban") + hdlr = logging.StreamHandler(sys.stdout) + fmt = logging.Formatter("%(asctime)-15s %(message)s") + hdlr.setFormatter(fmt) + logSys.addHandler(hdlr) + if set(["-q", "--quiet"]) & set(sys.argv): + logSys.setLevel(logging.CRITICAL) + warnings.simplefilter("ignore") + sys.warnoptions.append("ignore") + elif set(["-v", "--verbose"]) & set(sys.argv): + logSys.setLevel(logging.DEBUG) + else: + logSys.setLevel(logging.INFO) +elif "test" in sys.argv: + print("python distribute required to execute fail2ban tests") + print("") + +longdesc = ''' +Fail2Ban scans log files like /var/log/pwdfail or +/var/log/apache/error_log and bans IP that makes +too many password failures. It updates firewall rules +to reject the IP address or executes user defined +commands.''' + +if setuptools: + setup_extra = { + 'test_suite': "fail2ban.tests.utils.gatherTests", + 'use_2to3': True, + } +else: + setup_extra = {} + +data_files_extra = [] + +# Installing documentation files only under Linux or other GNU/ systems +# (e.g. GNU/kFreeBSD), since others might have protective mechanisms forbidding +# installation there (see e.g. #1233) +platform_system = platform.system().lower() +doc_files = ['README.md', 'DEVELOP', 'FILTERS', 'doc/run-rootless.txt'] +if platform_system in ('solaris', 'sunos'): + doc_files.append('README.Solaris') +if platform_system in ('linux', 'solaris', 'sunos') or platform_system.startswith('gnu'): + data_files_extra.append( + ('/usr/share/doc/fail2ban', doc_files) + ) + +# Get version number, avoiding importing fail2ban. +# This is due to tests not functioning for python3 as 2to3 takes place later +exec(open(join("fail2ban", "version.py")).read()) + +setup( + name = "fail2ban", + version = version, + description = "Ban IPs that make too many password failures", + long_description = longdesc, + author = "Cyril Jaquier & Fail2Ban Contributors", + author_email = "cyril.jaquier@fail2ban.org", + url = "http://www.fail2ban.org", + license = "GPL", + platforms = "Posix", + cmdclass = { + 'build_py': build_py, 'build_scripts': build_scripts, + }, + scripts = [ + 'bin/fail2ban-client', + 'bin/fail2ban-server', + 'bin/fail2ban-regex', + 'bin/fail2ban-testcases', + # 'bin/fail2ban-python', -- link (binary), will be installed via install_scripts_f2b wrapper + ], + packages = [ + 'fail2ban', + 'fail2ban.client', + 'fail2ban.server', + 'fail2ban.tests', + 'fail2ban.tests.action_d', + ], + package_data = { + 'fail2ban.tests': + [ join(w[0], f).replace("fail2ban/tests/", "", 1) + for w in os.walk('fail2ban/tests/files') + for f in w[2]] + + [ join(w[0], f).replace("fail2ban/tests/", "", 1) + for w in os.walk('fail2ban/tests/config') + for f in w[2]] + + [ join(w[0], f).replace("fail2ban/tests/", "", 1) + for w in os.walk('fail2ban/tests/action_d') + for f in w[2]] + }, + data_files = [ + ('/etc/fail2ban', + glob("config/*.conf") + ), + ('/etc/fail2ban/filter.d', + glob("config/filter.d/*.conf") + ), + ('/etc/fail2ban/filter.d/ignorecommands', + [p for p in glob("config/filter.d/ignorecommands/*") if isfile(p)] + ), + ('/etc/fail2ban/action.d', + glob("config/action.d/*.conf") + + glob("config/action.d/*.py") + ), + ('/etc/fail2ban/fail2ban.d', + '' + ), + ('/etc/fail2ban/jail.d', + '' + ), + ('/var/lib/fail2ban', + '' + ), + ] + data_files_extra, + **setup_extra +) diff --git a/meta-security/recipes-security/fail2ban/files/initd b/meta-security/recipes-security/fail2ban/files/initd new file mode 100644 index 000000000..4f4b394c4 --- /dev/null +++ b/meta-security/recipes-security/fail2ban/files/initd @@ -0,0 +1,98 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: fail2ban +# Required-Start: $local_fs $remote_fs +# Required-Stop: $local_fs $remote_fs +# Should-Start: $time $network $syslog iptables firehol shorewall ferm +# Should-Stop: $network $syslog iptables firehol shorewall ferm +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start/Stop fail2ban +# Description: Start/Stop fail2ban, a daemon to ban hosts that cause multiple authentication errors +### END INIT INFO + +# Source function library. +. /etc/init.d/functions + +# Check that the config file exists +[ -f /etc/fail2ban/fail2ban.conf ] || exit 0 + +check_privsep_dir() { + # Create the PrivSep empty dir if necessary + if [ ! -d /var/run/fail2ban ]; then + mkdir /var/run/fail2ban + chmod 0755 /var/run/fail2ban + fi +} + +FAIL2BAN="/usr/bin/fail2ban-client" +prog=fail2ban-server +lockfile=${LOCKFILE-/var/lock/subsys/fail2ban} +socket=${SOCKET-/var/run/fail2ban/fail2ban.sock} +pidfile=${PIDFILE-/var/run/fail2ban/fail2ban.pid} +RETVAL=0 + +start() { + echo -n $"Starting fail2ban: " + check_privsep_dir + ${FAIL2BAN} -x start > /dev/null + RETVAL=$? + if [ $RETVAL = 0 ]; then + touch ${lockfile} + echo_success + else + echo_failure + fi + echo + return $RETVAL +} + +stop() { + echo -n $"Stopping fail2ban: " + ${FAIL2BAN} stop > /dev/null + RETVAL=$? + if [ $RETVAL = 0 ]; then + rm -f ${lockfile} ${pidfile} + echo_success + else + echo_failure + fi + echo + return $RETVAL +} + +reload() { + echo "Reloading fail2ban: " + ${FAIL2BAN} reload + RETVAL=$? + echo + return $RETVAL +} + +# See how we were called. +case "$1" in + start) + status -p ${pidfile} ${prog} >/dev/null 2>&1 && exit 0 + start + ;; + stop) + stop + ;; + reload) + reload + ;; + restart) + stop + start + ;; + status) + status -p ${pidfile} ${prog} + RETVAL=$? + [ $RETVAL = 0 ] && ${FAIL2BAN} status + ;; + *) + echo $"Usage: fail2ban {start|stop|restart|reload|status}" + RETVAL=2 +esac + +exit $RETVAL diff --git a/meta-security/recipes-security/fscryptctl/fscryptctl_0.1.0.bb b/meta-security/recipes-security/fscryptctl/fscryptctl_0.1.0.bb new file mode 100644 index 000000000..4f0b12c4a --- /dev/null +++ b/meta-security/recipes-security/fscryptctl/fscryptctl_0.1.0.bb @@ -0,0 +1,27 @@ +SUMMARY = "low-level tool handling Linux filesystem encryption" +DESCIPTION = "fscryptctl is a low-level tool written in C that handles raw keys and manages \ +policies for Linux filesystem encryption (https://lwn.net/Articles/639427). \ +For a tool that presents a higher level interface and manages metadata, key \ +generation, key wrapping, PAM integration, and passphrase hashing, see \ +fscrypt (https://github.com/google/fscrypt)." +HOMEPAGE = "https://github.com/google/fscryptctl" +SECTION = "base" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57" + +SRCREV = "e4c4d0984dee2531897e13c32a18d5e54a2a4aa6" +SRC_URI = "git://github.com/google/fscryptctl.git" + +S = "${WORKDIR}/git" + +do_install() { + oe_runmake DESTDIR=${D}${bindir} install +} + +RRECOMMENDS_${PN} += "\ + keyutils \ + kernel-module-cbc \ + kernel-module-cts \ + kernel-module-ecb \ + kernel-module-xts \ +" diff --git a/meta-security/recipes-security/google-authenticator-libpam/google-authenticator-libpam_1.05.bb b/meta-security/recipes-security/google-authenticator-libpam/google-authenticator-libpam_1.05.bb new file mode 100644 index 000000000..73b802fb9 --- /dev/null +++ b/meta-security/recipes-security/google-authenticator-libpam/google-authenticator-libpam_1.05.bb @@ -0,0 +1,20 @@ +SUMMARY = "Google Authenticator PAM module" +HOME_PAGE = "https://github.com/google/google-authenticator-libpam" +LIC_FILES_CHKSUM = "file://LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57" +LICENSE = "Apache-2.0" + +SRC_URI = "git://github.com/google/google-authenticator-libpam.git" +SRCREV = "7365ed10d54393fb4c100cac063ae8edb744eac6" + +DEPENDS = "libpam" + +S = "${WORKDIR}/git" + +inherit autotools distro_features_check + +REQUIRED_DISTRO_FEATURES = "pam" + +PACKAGES += "pam-google-authenticator" +FILES_pam-google-authenticator = "${libdir}/security/pam_google_authenticator.so" + +RDEPNEDS_pam-google-authenticator = "libpam" diff --git a/meta-security/recipes-security/images/security-build-image.bb b/meta-security/recipes-security/images/security-build-image.bb new file mode 100644 index 000000000..1a7af86be --- /dev/null +++ b/meta-security/recipes-security/images/security-build-image.bb @@ -0,0 +1,21 @@ +DESCRIPTION = "A small image for building meta-security packages" + +IMAGE_FEATURES += "ssh-server-openssh" + +IMAGE_INSTALL = "\ + packagegroup-base \ + packagegroup-core-boot \ + packagegroup-core-security \ + os-release \ + ${@bb.utils.contains("DISTRO_FEATURES", "x11", "packagegroup-xfce-base", "", d)} \ + ${CORE_IMAGE_EXTRA_INSTALL}" + +IMAGE_LINGUAS ?= " " + +LICENSE = "MIT" + +inherit core-image + +export IMAGE_BASENAME = "security-build-image" + +IMAGE_ROOTFS_EXTRA_SPACE = "5242880" diff --git a/meta-security/recipes-security/images/security-client-image.bb b/meta-security/recipes-security/images/security-client-image.bb new file mode 100644 index 000000000..1a9247972 --- /dev/null +++ b/meta-security/recipes-security/images/security-client-image.bb @@ -0,0 +1,17 @@ +DESCRIPTION = "A Client side Security example" + +IMAGE_INSTALL = "\ + packagegroup-base \ + packagegroup-core-boot \ + os-release \ + samhain-client \ + ${@bb.utils.contains("DISTRO_FEATURES", "x11", "packagegroup-xfce-base", "", d)} \ + ${ROOTFS_PKGMANAGE_BOOTSTRAP} ${CORE_IMAGE_EXTRA_INSTALL}" + +IMAGE_LINGUAS ?= " " + +LICENSE = "MIT" + +inherit core-image + +export IMAGE_BASENAME = "security-client-image" diff --git a/meta-security/recipes-security/images/security-server-image.bb b/meta-security/recipes-security/images/security-server-image.bb new file mode 100644 index 000000000..502b5c142 --- /dev/null +++ b/meta-security/recipes-security/images/security-server-image.bb @@ -0,0 +1,20 @@ +DESCRIPTION = "A Serve side image for Security example " + +IMAGE_FEATURES += "ssh-server-openssh" + +IMAGE_INSTALL = "\ + packagegroup-base \ + packagegroup-core-boot \ + samhain-server \ + os-release \ + ${ROOTFS_PKGMANAGE_BOOTSTRAP} ${CORE_IMAGE_EXTRA_INSTALL}" + +IMAGE_LINGUAS ?= " " + +LICENSE = "MIT" + +inherit core-image + +export IMAGE_BASENAME = "security-server-image" + +IMAGE_ROOTFS_EXTRA_SPACE = "5242880" diff --git a/meta-security/recipes-security/isic/files/configure_fix.patch b/meta-security/recipes-security/isic/files/configure_fix.patch new file mode 100644 index 000000000..fc2a7749d --- /dev/null +++ b/meta-security/recipes-security/isic/files/configure_fix.patch @@ -0,0 +1,170 @@ +isic: add with-libnet remove libnet test + +Inappropriate - builds fine on non-oe systems. We need to exlude +cross compile libnet test. Pass in the location for libnet.a. Path +did not support mulitlib either. + +Signed-off-by: Armin Kuster <akuster808@gmail.com> + +Index: isic-0.07/configure +=================================================================== +--- isic-0.07.orig/configure ++++ isic-0.07/configure +@@ -45,6 +45,8 @@ includedir='${prefix}/include' + oldincludedir='/usr/include' + infodir='${prefix}/info' + mandir='${prefix}/man' ++with_libnet_libraries ++libnet_libraries + + # Initialize some other variables. + subdirs= +@@ -180,6 +182,7 @@ Features and packages: + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR ++ --with-libnet-dir=DIR libnet library is in this DIR + EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" +@@ -828,117 +832,36 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCR + test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +-PREFIX=/usr/local +- +-ac_safe=`echo "$PREFIX/lib/libnet.a" | sed 'y%./+-%__p_%'` +-echo $ac_n "checking for $PREFIX/lib/libnet.a""... $ac_c" 1>&6 +-echo "configure:836: checking for $PREFIX/lib/libnet.a" >&5 +-if eval "test \"`echo '$''{'ac_cv_file_$ac_safe'+set}'`\" = set"; then +- echo $ac_n "(cached) $ac_c" 1>&6 +-else +- if test "$cross_compiling" = yes; then +- { echo "configure: error: Cannot check for file existence when cross compiling" 1>&2; exit 1; } +-else +- if test -r $PREFIX/lib/libnet.a; then +- eval "ac_cv_file_$ac_safe=yes" +- else +- eval "ac_cv_file_$ac_safe=no" +- fi +-fi +-fi +-if eval "test \"`echo '$ac_cv_file_'$ac_safe`\" = yes"; then +- echo "$ac_t""yes" 1>&6 +- FOO=$LIBS; CFLAGS="$CFLAGS -I$PREFIX/include" LIBS="-L$PREFIX/lib $LIBS" +-else +- echo "$ac_t""no" 1>&6 +- +-fi +- +-echo $ac_n "checking for -lnet""... $ac_c" 1>&6 +-echo "configure:884: checking for -lnet" >&5 +-if eval "test \"`echo '$''{'ac_cv_lib_net'+set}'`\" = set"; then +- echo $ac_n "(cached) $ac_c" 1>&6 +-else +- ac_save_LIBS="$LIBS" +-LIBS="-lnet $LIBS" +-cat > conftest.$ac_ext <<EOF +-#line 891 "configure" +-#include "confdefs.h" +- +-int main() { +-main() +-; return 0; } +-EOF +-if { (eval echo configure:898: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +- rm -rf conftest* +- ac_cv_lib_net=yes +-else +- echo "configure: failed program was:" >&5 +- cat conftest.$ac_ext >&5 +- rm -rf conftest* +- ac_cv_lib_net=no ++LIBNET_GLOB='libnet.a' ++libnet_libraries="" ++ac_libnet_libraries=NO ++ ++# Check whether --with-libnet-libraries was given. ++if test "${with_libnet_libraries+set}" = set; then : ++ withval=$with_libnet_libraries; ac_libnet_libraries="$withval" ++fi ++ ++if test ! "$ac_libnet_libraries" = "NO"; then ++ libnet_libdir=$ac_libnet_libraries ++else ++ libnet_libdirs="/usr/lib" ++ libnet_libdir=NONE ++ for dir in $libnet_libdirs; do ++ try="ls -1 $dir/${LIBNET_GLOB}" ++ if test -n "`$try 2> /dev/null`"; then libnet_libdir=$dir; break; else echo "tried $dir" >&5; fi ++ done + fi +-rm -f conftest* +-LIBS="$ac_save_LIBS" + +-fi +-echo "$ac_t""$ac_cv_lib_net" 1>&6 +-if test "$ac_cv_lib_net" = yes; then +- DEFINES= +-else +- { echo "configure: error: Cannot find libnet... please get it from +- http://www.packetfactory.net/libnet" 1>&2; exit 1; } +-fi ++ac_libnet_libdir="$libnet_libdir" + +-echo $ac_n "checking for libnet_init in -lnet""... $ac_c" 1>&6 +-echo "configure:921: checking for libnet_init in -lnet" >&5 +-ac_lib_var=`echo net'_'libnet_init | sed 'y%./+-%__p_%'` +-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then +- echo $ac_n "(cached) $ac_c" 1>&6 +-else +- ac_save_LIBS="$LIBS" +-LIBS="-lnet $LIBS" +-cat > conftest.$ac_ext <<EOF +-#line 929 "configure" +-#include "confdefs.h" +-/* Override any gcc2 internal prototype to avoid an error. */ +-/* We use char because int might match the return type of a gcc2 +- builtin and then its argument prototype would still apply. */ +-char libnet_init(); +- +-int main() { +-libnet_init() +-; return 0; } +-EOF +-if { (eval echo configure:940: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +- rm -rf conftest* +- eval "ac_cv_lib_$ac_lib_var=yes" +-else +- echo "configure: failed program was:" >&5 +- cat conftest.$ac_ext >&5 +- rm -rf conftest* +- eval "ac_cv_lib_$ac_lib_var=no" ++if test "$libnet_libraries"; then ++ libnet_libraries="$ac_libnet_libdir" + fi +-rm -f conftest* +-LIBS="$ac_save_LIBS" +- +-fi +-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then +- echo "$ac_t""yes" 1>&6 +- ac_tr_lib=HAVE_LIB`echo net | sed -e 's/[^a-zA-Z0-9_]/_/g' \ +- -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` +- cat >> confdefs.h <<EOF +-#define $ac_tr_lib 1 +-EOF + +- LIBS="-lnet $LIBS" +- +-else +- echo "$ac_t""no" 1>&6 ++if test "$libnet_libraries" != "$x_libraries" && test -n "$libnet_libraries"; then ++ LIBS="$LIBS -lnet" + fi + +- +- + echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 + echo "configure:970: checking how to run the C preprocessor" >&5 + # On Suns, sometimes $CPP names a directory. diff --git a/meta-security/recipes-security/isic/files/isic-0.07-make.patch b/meta-security/recipes-security/isic/files/isic-0.07-make.patch new file mode 100644 index 000000000..9cffa8a3d --- /dev/null +++ b/meta-security/recipes-security/isic/files/isic-0.07-make.patch @@ -0,0 +1,23 @@ +isic: Fixup makefile to support destination + +Backport: +http://pkgs.fedoraproject.org/cgit/isic.git/tree/isic-0.07-make.patch + +Signed-off-by: Armin Kuster <akuser808@gmail.com> + +Index: isic-0.07/Makefile.in +=================================================================== +--- isic-0.07.orig/Makefile.in ++++ isic-0.07/Makefile.in +@@ -63,7 +63,7 @@ package: distclean + tar -czvf isic-$(VERSION).tgz ./isic-$(VERSION)/* ) + + install: $(BINS) $(MAN) +- $(INSTALL) -m 0755 -d $(PREFIX)/bin +- $(INSTALL) -m 0755 -c $(BINS) $(PREFIX)/bin +- $(INSTALL) -m 0755 -d $(PREFIX)/man/man1 +- ${INSTALL} -m 0755 -c $(MAN) $(PREFIX)/man/man1 ++ $(INSTALL) -m 0755 -d $(DESTDIR)$(PREFIX)/bin ++ $(INSTALL) -m 0755 -c $(BINS) $(DESTDIR)$(PREFIX)/bin ++ $(INSTALL) -m 0755 -d $(DESTDIR)$(PREFIX)/share/man/man1 ++ ${INSTALL} -m 0755 -c $(MAN) $(DESTDIR)$(PREFIX)/share/man/man1 diff --git a/meta-security/recipes-security/isic/files/isic-0.07-netinet.patch b/meta-security/recipes-security/isic/files/isic-0.07-netinet.patch new file mode 100644 index 000000000..c4ea74ee2 --- /dev/null +++ b/meta-security/recipes-security/isic/files/isic-0.07-netinet.patch @@ -0,0 +1,68 @@ +isic: add missing header file + +Backport: +http://pkgs.fedoraproject.org/cgit/isic.git/tree/isic-0.07-netinet.patch + +Signed-off-by: Armin Kuster <akuster808@gmail.com> + +Index: isic-0.07/multisic.c +=================================================================== +--- isic-0.07.orig/multisic.c ++++ isic-0.07/multisic.c +@@ -1,5 +1,8 @@ + #include "isic.h" + ++#include <netinet/udp.h> ++/*#include <netinet/tcp.h>*/ ++ + /* This is tuned for ethernet sized frames (1500 bytes) + * For user over a modem or frame (or other) you will have to change the + * 'rand() & 0x4ff' line below. The 0x4ff needs to be less than the size of +Index: isic-0.07/tcpsic.c +=================================================================== +--- isic-0.07.orig/tcpsic.c ++++ isic-0.07/tcpsic.c +@@ -1,5 +1,7 @@ + #include "isic.h" + ++#include <netinet/tcp.h> ++ + /* This is tuned for ethernet sized frames (1500 bytes) + * For user over a modem or frame (or other) you will have to change the + * 'rand() & 0x4ff' line below. The 0x4ff needs to be less than the size of +Index: isic-0.07/tcpsic6.c +=================================================================== +--- isic-0.07.orig/tcpsic6.c ++++ isic-0.07/tcpsic6.c +@@ -1,5 +1,7 @@ + #include "isic.h" + ++#include <netinet/tcp.h> ++ + /* This is tuned for ethernet sized frames (1500 bytes) + * For user over a modem or frame (or other) you will have to change the + * 'rand() & 0x4ff' line below. The 0x4ff needs to be less than the size of +Index: isic-0.07/udpsic.c +=================================================================== +--- isic-0.07.orig/udpsic.c ++++ isic-0.07/udpsic.c +@@ -1,5 +1,7 @@ + #include "isic.h" + ++#include <netinet/udp.h> ++ + /* This is tuned for ethernet sized frames (1500 bytes) + * For user over a modem or frame (or other) you will have to change the + * 'rand() & 0x4ff' line below. The 0x4ff needs to be less than the size of +Index: isic-0.07/udpsic6.c +=================================================================== +--- isic-0.07.orig/udpsic6.c ++++ isic-0.07/udpsic6.c +@@ -1,5 +1,7 @@ + #include "isic.h" + ++#include <netinet/udp.h> ++ + /* This is tuned for ethernet sized frames (1500 bytes) + * For user over a modem or frame (or other) you will have to change the + * 'rand() & 0x4ff' line below. The 0x4ff needs to be less than the size of diff --git a/meta-security/recipes-security/isic/isic_0.07.bb b/meta-security/recipes-security/isic/isic_0.07.bb new file mode 100644 index 000000000..fb6e9046d --- /dev/null +++ b/meta-security/recipes-security/isic/isic_0.07.bb @@ -0,0 +1,30 @@ +SUMMARY = "ISIC -- IP Stack Integrity Checker" +DESCRIPTION = "ISIC is a suite of utilities to exercise the stability of an IP Stack and its component stacks (TCP, UDP, ICMP et. al.)" +HOMEPAGE = "http://isic.sourceforge.net/" +SECTION = "security" +LICENSE = "BSD" +LIC_FILES_CHKSUM = "file://LICENSE;md5=d41d8cd98f00b204e9800998ecf8427e" + +DEPENDS = "libnet" +PARALLEL_MAKE = "" + +SRC_URI = "http://prdownloads.sourceforge.net/isic/${BPN}-${PV}.tgz \ + file://configure_fix.patch \ + file://isic-0.07-netinet.patch \ + file://isic-0.07-make.patch \ + " + +SRC_URI[md5sum] = "29f70c9bde9aa9128b8f7e66a315f9a4" +SRC_URI[sha256sum] = "e033c53e03e26a4c72b723e2a5a1c433ee70eb4d23a1ba0d7d7e14ee1a80429d" + +S="${WORKDIR}/${BPN}-${PV}" + +inherit autotools-brokensep + +EXTRA_OECONF += "--with-libnet-dir=${STAGING_DIR_HOST}${libdir} " + +do_configure () { + oe_runconf +} + +RDEPNEDS += "libnet" diff --git a/meta-security/recipes-security/keynote/keynote-2.3/configure-remove-hardcode-path.patch b/meta-security/recipes-security/keynote/keynote-2.3/configure-remove-hardcode-path.patch new file mode 100644 index 000000000..af3ef421d --- /dev/null +++ b/meta-security/recipes-security/keynote/keynote-2.3/configure-remove-hardcode-path.patch @@ -0,0 +1,37 @@ +Remove the hardcoded lib and include dirs + +Upstream-Status: Inappropriate [cross compile specific] + +written by: Amy Fong <amy.fong@windriver.com> +Signed-off-by: Jackie Huang <jackie.huang@windriver.com> + +--- keynote-2.3/configure.in.orig 2010-05-24 04:44:16.000000000 -0700 ++++ keynote-2.3/configure.in 2010-05-24 04:44:55.000000000 -0700 +@@ -21,27 +21,16 @@ + AC_PATH_PROG(ECHO, echo, /bin/echo) + AC_PATH_PROG(SED, sed, /usr/bin/sed) + +-dnl Checks for libraries. +-LIBS="-L/usr/lib -L/usr/local/lib -L/usr/ssl/lib -L/usr/openssl/lib\ +- -L/usr/local/ssl/lib -L/usr/local/openssl/lib -L/usr/pkg/lib -L/pkg/lib" +- + AC_CHECK_LIB(m, floor, LIBS="$LIBS -lm") + AC_CHECK_LIB(rsaref, RSAPrivateDecrypt, LIBS="$LIBS -lrsaref") + AC_CHECK_LIB(crypto, i2a_ASN1_STRING, LIBS="$LIBS -lcrypto") + AC_CHECK_LIB(RSAglue, RSA_ref_private_encrypt, LIBS="$LIBS -lRSAglue") + +-dnl Checks for header files. +-CPPFLAGS="-I/usr/include -I/usr/local/include -I/usr/ssl/include\ +- -I/usr/local/ssl/include -I/usr/openssl/include -I/usr/pkg/include\ +- -I/usr/local/openssl/include -I/pkg/include" +- + AC_HEADER_STDC + AC_HEADER_TIME + AC_CHECK_HEADERS(fcntl.h limits.h unistd.h regex.h sys/time.h io.h) + AC_CHECK_HEADERS(ssl/crypto.h openssl/crypto.h crypto.h memory.h) + +-dnl Checks for other files +- + dnl Checks for typedefs, structures, and compiler characteristics. + AC_C_CONST + AC_CHECK_TYPE(u_int, unsigned int) diff --git a/meta-security/recipes-security/keynote/keynote-2.3/makefile-add-ldflags.patch b/meta-security/recipes-security/keynote/keynote-2.3/makefile-add-ldflags.patch new file mode 100644 index 000000000..80d87cf28 --- /dev/null +++ b/meta-security/recipes-security/keynote/keynote-2.3/makefile-add-ldflags.patch @@ -0,0 +1,36 @@ +Add LDFLAGS variable to Makefile so that extra linker flags can be sent via this variable. + +Upstream-Status: Pending + +Signed-off-by: Yi Zhao <yi.zhao@windriver.com> + +diff --git a/Makefile.in b/Makefile.in +index b216648..42b4827 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -35,6 +35,7 @@ MKDIR = @MKDIR@ + SED = @SED@ + ECHO = @ECHO@ + TR = @TR@ ++LDFLAGS = @LDFLAGS@ + + TARFLAGS = -cvzf ${DISTFILE} + YACCFLAGS2 = -d -p kv -b z +@@ -83,7 +84,7 @@ $(TARGET): $(OBJS) + $(RANLIB) $(TARGET) + + $(TARGET2): $(TARGET) $(OBJS2) +- $(CC) $(CFLAGS) -o $(TARGET2) $(OBJS2) $(LIBS) ++ $(CC) $(CFLAGS) $(LDFLAGS) -o $(TARGET2) $(OBJS2) $(LIBS) + + k.tab.c: keynote.y header.h keynote.h assertion.h config.h + $(YACC) $(YACCFLAGS) keynote.y +@@ -131,7 +132,7 @@ $(SSLCERT) $(SSLKEY): + -keyout $(SSLKEY) + + test-sample: all $(OBJS3) +- $(CC) $(CFLAGS) -o $(TARGET3) $(OBJS3) $(LIBS) ++ $(CC) $(CFLAGS) $(LDFLAGS) -o $(TARGET3) $(OBJS3) $(LIBS) + + test-sig: all $(SSLCERT) $(SSLKEY) + $(SED) -e 's/--.*//' < $(SSLCERT) > $(SSLCERT).1 diff --git a/meta-security/recipes-security/keynote/keynote-2.3/run-ptest b/meta-security/recipes-security/keynote/keynote-2.3/run-ptest new file mode 100644 index 000000000..4dc35c9d1 --- /dev/null +++ b/meta-security/recipes-security/keynote/keynote-2.3/run-ptest @@ -0,0 +1,16 @@ +#!/bin/sh + +cd @PTEST_PATH@ +keynote verify -e testsuite/test-env \ + -r false,maybe,probably,true \ + -k testsuite/auth1 -k testsuite/auth2 \ + -k testsuite/auth3 -k testsuite/auth4 \ + -l testsuite/test-assertion1 \ + -l testsuite/test-assertion2 \ + -l testsuite/test-assertion3 \ + -l testsuite/test-assertion4 \ + -l testsuite/test-assertion5 \ + -l testsuite/test-assertion6 \ + -l testsuite/test-assertion7 \ + && echo "PASS: keynote-ptest" \ + || echo "FAIL: keynote-ptest" diff --git a/meta-security/recipes-security/keynote/keynote_2.3.bb b/meta-security/recipes-security/keynote/keynote_2.3.bb new file mode 100644 index 000000000..e6924858d --- /dev/null +++ b/meta-security/recipes-security/keynote/keynote_2.3.bb @@ -0,0 +1,40 @@ +SUMMARY = "Keynote tool and library" +DESCRIPTION = "KeyNote is a simple and flexible trust-management \ + system designed to work well for a variety of large- and small- \ + scale Internet-based applications. \ +" +HOMEPAGE = "http://www.cs.columbia.edu/~angelos/keynote.html" +SECTION = "security" + +LICENSE = "ISC" +LIC_FILES_CHKSUM = "file://LICENSE;md5=3a265095c549c1808686a676f2699c98" + +MAIN_ID = "${@d.getVar('PV').split('.')[0]}" +MINOR_ID = "${@d.getVar('PV').split('.')[1]}" +SRC_URI = "${SOURCEFORGE_MIRROR}/project/${BPN}-${MAIN_ID}-${MINOR_ID}/${BPN}_${PV}.tar.gz \ + file://configure-remove-hardcode-path.patch \ + file://makefile-add-ldflags.patch \ + file://run-ptest \ +" +S = "${WORKDIR}/${BPN}-${PV}+dfsg.orig" + +inherit autotools-brokensep ptest + +SRC_URI[md5sum] = "a14553e6ad921b5c85026ce5bec3afe7" +SRC_URI[sha256sum] = "38d2acfa1c3630a07adcb5c8fe92d2aef7f0e6d242b8998b2bbb1c6e4c408d46" + +DEPENDS = "flex openssl" + +EXTRA_OEMAKE += "test-sample -j1" + +do_install() { + install -D -m 0755 ${S}/keynote ${D}${bindir}/keynote + install -D -m 0644 ${S}/libkeynote.a ${D}${libdir}/libkeynote.a + install -D -m 0644 ${S}/keynote.h ${D}${includedir}/keynote.h +} + +do_install_ptest() { + install -D -m 0755 ${S}/sample-app ${D}${PTEST_PATH} + cp -r ${S}/testsuite ${D}${PTEST_PATH} + sed -i 's|@PTEST_PATH@|${PTEST_PATH}|' ${D}${PTEST_PATH}/run-ptest +} diff --git a/meta-security/recipes-security/keyutils/files/keyutils-fix-error-report-by-adding-default-message.patch b/meta-security/recipes-security/keyutils/files/keyutils-fix-error-report-by-adding-default-message.patch new file mode 100644 index 000000000..acd91c01c --- /dev/null +++ b/meta-security/recipes-security/keyutils/files/keyutils-fix-error-report-by-adding-default-message.patch @@ -0,0 +1,42 @@ +fix keyutils test error report + +Upstream-Status: Pending + +"Permission denied" may be the reason of EKEYEXPIRED and EKEYREVOKED. +"Required key not available" may be the reason of EKEYREVOKED. +EXPIRED and REVOKED are 2 status of kernel security keys features. +But the userspace keyutils lib will output the error message, which may +have several reasons. + +Signed-off-by: Han Chao <chan@windriver.com> + +diff --git a/tests/toolbox.inc.sh b/tests/toolbox.inc.sh +index bbca00a..739e9d0 100644 +--- a/tests/toolbox.inc.sh ++++ b/tests/toolbox.inc.sh +@@ -227,11 +227,12 @@ function expect_error () + ;; + EKEYEXPIRED) + my_err="Key has expired" +- alt_err="Unknown error 127" ++ alt_err="Permission denied" + ;; + EKEYREVOKED) + my_err="Key has been revoked" +- alt_err="Unknown error 128" ++ alt_err="Permission denied" ++ alt2_err="Required key not available" + ;; + EKEYREJECTED) + my_err="Key has been rejected" +@@ -249,6 +250,9 @@ function expect_error () + elif [ "x$alt_err" != "x" ] && expr "$my_errmsg" : ".*: $alt_err" >&/dev/null + then + : ++ elif [ "x$alt2_err" != "x" ] && expr "$my_errmsg" : ".*: $alt2_err" >&/dev/null ++ then ++ : + elif [ "x$old_err" != "x" ] && expr "$my_errmsg" : ".*: $old_err" >&/dev/null + then + : + diff --git a/meta-security/recipes-security/keyutils/files/keyutils-test-fix-output-format.patch b/meta-security/recipes-security/keyutils/files/keyutils-test-fix-output-format.patch new file mode 100644 index 000000000..a4ffd50ce --- /dev/null +++ b/meta-security/recipes-security/keyutils/files/keyutils-test-fix-output-format.patch @@ -0,0 +1,41 @@ +From 49b6321368e4bd3cd233d045cd09004ddd7968b2 Mon Sep 17 00:00:00 2001 +From: Jackie Huang <jackie.huang@windriver.com> +Date: Mon, 15 May 2017 14:52:00 +0800 +Subject: [PATCH] keyutils: fix output format + +keyutils ptest output format is incorrect, according to yocto +Development Manual +(http://www.yoctoproject.org/docs/latest/dev-manual/dev-manual.html#testing-packages-with-ptest) +5.10.6. Testing Packages With ptestThe test generates output in the format used by Automake: +<result>: <testname> +where the result can be PASS, FAIL, or SKIP, and the testname can be any +identifying string. +So we should change the test result format to match yocto ptest rules. + +Upstream-Status: Inappropriate [OE ptest specific] + +Signed-off-by: Li Wang <li.wang@windriver.com> +Signed-off-by: Jackie Huang <jackie.huang@windriver.com> +--- + tests/runtest.sh | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/tests/runtest.sh b/tests/runtest.sh +index b6eaa7c..84263fb 100644 +--- a/tests/runtest.sh ++++ b/tests/runtest.sh +@@ -21,6 +21,11 @@ for i in ${TESTS}; do + echo "### RUNNING TEST $i" + if [[ $AUTOMATED != 0 ]] ; then + bash ./runtest.sh ++ if [ $? != 0 ]; then ++ echo "FAIL: $i" ++ else ++ echo "PASS: $i" ++ fi + else + bash ./runtest.sh || exit 1 + fi +-- +2.11.0 + diff --git a/meta-security/recipes-security/keyutils/files/keyutils-use-relative-path-for-link.patch b/meta-security/recipes-security/keyutils/files/keyutils-use-relative-path-for-link.patch new file mode 100644 index 000000000..dde1af44a --- /dev/null +++ b/meta-security/recipes-security/keyutils/files/keyutils-use-relative-path-for-link.patch @@ -0,0 +1,28 @@ +Subject: [PATCH] keyutils: use relative path for link + +The absolute path of the symlink will be invalid +when populated in sysroot, so use relative path instead. + +Upstream-Status: Pending + +Signed-off-by: Jackie Huang <jackie.huang@windriver.com> +--- + Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index 824bbbf..8ce3a13 100644 +--- a/Makefile ++++ b/Makefile +@@ -167,7 +167,7 @@ ifeq ($(NO_SOLIB),0) + $(INSTALL) -D $(LIBNAME) $(DESTDIR)$(LIBDIR)/$(LIBNAME) + $(LNS) $(LIBNAME) $(DESTDIR)$(LIBDIR)/$(SONAME) + mkdir -p $(DESTDIR)$(USRLIBDIR) +- $(LNS) $(LIBDIR)/$(SONAME) $(DESTDIR)$(USRLIBDIR)/$(DEVELLIB) ++ $(LNS) $(SONAME) $(DESTDIR)$(USRLIBDIR)/$(DEVELLIB) + endif + $(INSTALL) -D keyctl $(DESTDIR)$(BINDIR)/keyctl + $(INSTALL) -D request-key $(DESTDIR)$(SBINDIR)/request-key +-- +2.11.0 + diff --git a/meta-security/recipes-security/keyutils/files/run-ptest b/meta-security/recipes-security/keyutils/files/run-ptest new file mode 100755 index 000000000..305707f65 --- /dev/null +++ b/meta-security/recipes-security/keyutils/files/run-ptest @@ -0,0 +1,3 @@ +#!/bin/sh +export AUTOMATED=1 +make -C tests run diff --git a/meta-security/recipes-security/keyutils/keyutils_1.5.10.bb b/meta-security/recipes-security/keyutils/keyutils_1.5.10.bb new file mode 100644 index 000000000..2ead8fa19 --- /dev/null +++ b/meta-security/recipes-security/keyutils/keyutils_1.5.10.bb @@ -0,0 +1,45 @@ +SUMMARY = "Linux Key Management Utilities" +DESCRIPTION = "\ + Utilities to control the kernel key management facility and to provide \ + a mechanism by which the kernel call back to userspace to get a key \ + instantiated. \ + " +HOMEPAGE = "http://people.redhat.com/dhowells/keyutils" +SECTION = "base" + +LICENSE = "LGPLv2.1+ & GPLv2.0+" + +LIC_FILES_CHKSUM = "file://LICENCE.GPL;md5=5f6e72824f5da505c1f4a7197f004b45 \ + file://LICENCE.LGPL;md5=7d1cacaa3ea752b72ea5e525df54a21f" + + +inherit siteinfo ptest + +SRC_URI = "http://people.redhat.com/dhowells/keyutils/${BP}.tar.bz2 \ + file://keyutils-use-relative-path-for-link.patch \ + file://keyutils-test-fix-output-format.patch \ + file://keyutils-fix-error-report-by-adding-default-message.patch \ + file://run-ptest \ + " + +SRC_URI[md5sum] = "3771676319bc7b84b1549b5c63ff5243" +SRC_URI[sha256sum] = "115c3deae7f181778fd0e0ffaa2dad1bf1fe2f5677cf2e0e348cdb7a1c93afb6" + +EXTRA_OEMAKE = "'CFLAGS=${CFLAGS} -Wall' \ + NO_ARLIB=1 \ + LIBDIR=${base_libdir} \ + USRLIBDIR=${base_libdir} \ + BUILDFOR=${SITEINFO_BITS}-bit \ + NO_GLIBC_KEYERR=1 \ + " + +do_install () { + oe_runmake DESTDIR=${D} install +} + +do_install_ptest () { + cp -r ${S}/tests ${D}${PTEST_PATH}/ + sed -i -e 's/OSDIST=Unknown/OSDIST=${DISTRO}/' ${D}${PTEST_PATH}/tests/prepare.inc.sh +} + +RDEPENDS_${PN}-ptest += "glibc-utils" diff --git a/meta-security/recipes-security/libdhash/ding-libs_0.5.0.bb b/meta-security/recipes-security/libdhash/ding-libs_0.5.0.bb new file mode 100644 index 000000000..9db66e86f --- /dev/null +++ b/meta-security/recipes-security/libdhash/ding-libs_0.5.0.bb @@ -0,0 +1,13 @@ +SUMMARY = "Dynamic hash table implementation" +DESCRIPTION = "Dynamic hash table implementation" +HOMEPAGE = "https://fedorahosted.org/released/ding-libs" +SECTION = "base" +LICENSE = "GPLv3+" +LIC_FILES_CHKSUM = "file://COPYING;md5=d32239bcb673463ab874e80d47fae504" + +SRC_URI = "https://fedorahosted.org/released/${BPN}/${BP}.tar.gz" + +inherit autotools pkgconfig + +SRC_URI[md5sum] = "786f2880d30136a61df02e5d740ddc6e" +SRC_URI[sha256sum] = "dab937537a05d7a7cbe605fdb9b3809080d67b124ac97eb321255b35f5b172fd" diff --git a/meta-security/recipes-security/libgssglue/files/libgssglue-canon-name.patch b/meta-security/recipes-security/libgssglue/files/libgssglue-canon-name.patch new file mode 100644 index 000000000..cb7c47b3f --- /dev/null +++ b/meta-security/recipes-security/libgssglue/files/libgssglue-canon-name.patch @@ -0,0 +1,60 @@ +fix the bug: +g_canon_name.c:125:5: warning: passing argument 2 of '__gss_copy_namebuf' from incompatible pointer type [enabled by default] + +the 2nd argument of __gss_copy_namebuf should be address of *gss_buffer_t, \ +but a *gss_buffer_t is assigned. + +what __gss_copy_namebuf does is to alloc memory for a gss_buffer_desc and \ +copy from src and return its address. + +if following code failed, gss_release_name will free \ +union_canon_name->external_name.value if it is not NULL. + +OM_uint32 __gss_copy_namebuf(src, dest) + gss_buffer_t src; + gss_buffer_t *dest; + +typedef struct gss_union_name_t { + gss_mechanism gss_mech; + gss_OID name_type; + gss_buffer_desc external_name; + /* + * These last two fields are only filled in for mechanism + * names. + */ + gss_OID mech_type; + gss_name_t mech_name; +} gss_union_name_desc, *gss_union_name_t; + +typedef struct gss_buffer_desc_struct { + size_t length; + void FAR *value; +} gss_buffer_desc, FAR *gss_buffer_t; + +Upstream-Status: Pending +Signed-off-by: Yao Zhao <yao.zhao@windriver.com> + +--- a/src/g_canon_name.c ++++ b/src/g_canon_name.c +@@ -121,11 +121,17 @@ gss_canonicalize_name (OM_uint32 *minor_ + + union_canon_name->mech_name = mech_name; + +- status = __gss_copy_namebuf(&union_input_name->external_name, +- &union_canon_name->external_name); +- if (status != GSS_S_COMPLETE) +- goto failure; ++ union_canon_name->external_name.value = (void*) malloc( ++ union_input_name->external_name.length + 1); ++ if (!union_canon_name->external_name.value) ++ goto failure; + ++ memcpy(union_canon_name->external_name.value, ++ union_input_name->external_name.value, ++ union_input_name->external_name.length); ++ union_canon_name->external_name.length = ++ union_input_name->external_name.length; ++ + if (union_input_name->name_type != GSS_C_NO_OID) { + status = generic_gss_copy_oid(minor_status, + union_input_name->name_type, diff --git a/meta-security/recipes-security/libgssglue/files/libgssglue-fix-CVE-2011-2709.patch b/meta-security/recipes-security/libgssglue/files/libgssglue-fix-CVE-2011-2709.patch new file mode 100644 index 000000000..6aa1a657a --- /dev/null +++ b/meta-security/recipes-security/libgssglue/files/libgssglue-fix-CVE-2011-2709.patch @@ -0,0 +1,43 @@ +Use secure_getenv instead of getenv for setuid programs + +(bnc#694598 CVE-2011-2709 bnc#831805) + +import from: +https://build.opensuse.org/package/view_file/openSUSE:Factory/libgssglue/secure-getenv.patch + +Upstream-Status: Pending + +Signed-off-by: Jackie Huang <jackie.huang@windriver.com> + +diff --git a/src/g_initialize.c b/src/g_initialize.c +index 200f173..935a9fa 100644 +--- a/src/g_initialize.c ++++ b/src/g_initialize.c +@@ -26,6 +26,7 @@ + * This function will initialize the gssapi mechglue library + */ + ++#define _GNU_SOURCE + #include "mglueP.h" + #include <stdlib.h> + +@@ -197,8 +198,7 @@ static void solaris_initialize () + void *dl; + gss_mechanism (*sym)(void), mech; + +- if ((getuid() != geteuid()) || +- ((filename = getenv("GSSAPI_MECH_CONF")) == NULL)) ++ if ((filename = secure_getenv("GSSAPI_MECH_CONF")) == NULL) + filename = MECH_CONF; + + if ((conffile = fopen(filename, "r")) == NULL) { +@@ -274,8 +274,7 @@ static void linux_initialize () + void *dl; + gss_mechanism (*sym)(void), mech; + +- if ((getuid() != geteuid()) || +- ((filename = getenv("GSSAPI_MECH_CONF")) == NULL)) ++ if ((filename = secure_getenv("GSSAPI_MECH_CONF")) == NULL) + filename = MECH_CONF; + + if ((conffile = fopen(filename, "r")) == NULL) { diff --git a/meta-security/recipes-security/libgssglue/files/libgssglue-g-initialize.patch b/meta-security/recipes-security/libgssglue/files/libgssglue-g-initialize.patch new file mode 100644 index 000000000..4a9ba3322 --- /dev/null +++ b/meta-security/recipes-security/libgssglue/files/libgssglue-g-initialize.patch @@ -0,0 +1,21 @@ +Fix the warning for getuid, geteuid +g_initialize.c: In function 'linux_initialize': +g_initialize.c:275:5: warning: implicit declaration of function 'getuid' [-Wimplicit-function-declaration] +g_initialize.c:275:5: warning: implicit declaration of function 'geteuid' [-Wimplicit-function-declaration] + +Upstream-Status: Pending +Signed-off-by: Yao Zhao <yao.zhao@windriver.com> + +diff --git a/src/g_initialize.c b/src1/g_initialize.c +index 82fcce1..200f173 100644 +--- a/src/g_initialize.c ++++ b/src/g_initialize.c +@@ -29,6 +29,8 @@ + #include "mglueP.h" + #include <stdlib.h> + ++#include <unistd.h> /*getuid, geteuid */ ++#include <sys/types.h> + #include <stdio.h> + #include <string.h> + #include <ctype.h> diff --git a/meta-security/recipes-security/libgssglue/files/libgssglue-gss-inq-cred.patch b/meta-security/recipes-security/libgssglue/files/libgssglue-gss-inq-cred.patch new file mode 100644 index 000000000..6dce3e737 --- /dev/null +++ b/meta-security/recipes-security/libgssglue/files/libgssglue-gss-inq-cred.patch @@ -0,0 +1,27 @@ +1) add free if malloc failed for (*mechanisms)->elements +2) g_inq_cred.c: In function 'gss_inquire_cred': +g_inq_cred.c:161:8: warning: passing argument 3 of 'generic_gss_copy_oid' from incompatible pointer type [enabled by default] + +Upstream-Status: Pending +Signed-off-by: Yao Zhao <yao.zhao@windriver.com> + +--- a/src/g_inq_cred.c ++++ b/src/g_inq_cred.c +@@ -152,13 +152,15 @@ gss_OID_set * mechanisms; + union_cred->count); + if ((*mechanisms)->elements == NULL) { + *minor_status = ENOMEM; ++ free(*mechanisms); ++ *mechanisms = GSS_C_NO_OID_SET; + return (GSS_S_FAILURE); + } + + for (i=0; i < union_cred->count; i++) { +- status = generic_gss_copy_oid(minor_status, ++ status = generic_gss_add_oid_set_member(minor_status, + &union_cred->mechs_array[i], +- &((*mechanisms)->elements[i])); ++ mechanisms); + if (status != GSS_S_COMPLETE) + break; + } diff --git a/meta-security/recipes-security/libgssglue/files/libgssglue-mglueP.patch b/meta-security/recipes-security/libgssglue/files/libgssglue-mglueP.patch new file mode 100644 index 000000000..6c9ebf05c --- /dev/null +++ b/meta-security/recipes-security/libgssglue/files/libgssglue-mglueP.patch @@ -0,0 +1,21 @@ +fix the warning: +warning: implicit declaration of function 'generic_gss_copy_oid_set' [-Wimplicit-function-declaration] + +Upstream-Status: Pending +Signed-off-by: Yao Zhao <yao.zhao@windriver.com> + +--- a/src/mglueP.h ++++ b/src/mglueP.h +@@ -447,6 +447,12 @@ OM_uint32 generic_gss_copy_oid + gss_OID * /* new_oid */ + ); + ++OM_uint32 generic_gss_copy_oid_set ++ (OM_uint32 *minor_status, /* minor_status */ ++ const gss_OID_set_desc * const oidset, /* oid */ ++ gss_OID_set *new_oidset /* new_oid */ ++ ); ++ + OM_uint32 generic_gss_create_empty_oid_set + (OM_uint32 *, /* minor_status */ + gss_OID_set * /* oid_set */ diff --git a/meta-security/recipes-security/libgssglue/libgssglue_0.4.bb b/meta-security/recipes-security/libgssglue/libgssglue_0.4.bb new file mode 100644 index 000000000..f7859a71c --- /dev/null +++ b/meta-security/recipes-security/libgssglue/libgssglue_0.4.bb @@ -0,0 +1,51 @@ +SUMMARY = "Exports a gssapi interface which calls other gssapi libraries" +DESCRIPTION = "\ +This library exports a gssapi interface, but does not implement any gssapi \ +mechanisms itself; instead it calls gssapi routines in other libraries, \ +depending on the mechanism. \ +" + +HOMEPAGE = "http://www.citi.umich.edu/projects/nfsv4/linux/" +SECTION = "libs" + +LICENSE = "BSD-3-Clause | HPND" + +#Copyright (c) 1996, by Sun Microsystems, Inc. HPND +#Copyright (c) 2007 The Regents of the University of Michigan. BSD-3-Clause +#Copyright 1995 by the Massachusetts Institute of Technology. HPND without Disclaimer +#Copyright 1993 by OpenVision Technologies, Inc. HPND +LIC_FILES_CHKSUM = "file://COPYING;md5=56871e72a5c475289c0d5e4ba3f2ee3a \ + file://src/g_accept_sec_context.c;beginline=3;endline=23;md5=8a7f4017cb7f4be49f8981cb8c472690 \ + file://src/g_ccache_name.c;beginline=1;endline=32;md5=208d4de05d5c8273963a8332f084faa7 \ + file://src/oid_ops.c;beginline=1;endline=26;md5=1f194d148b396972da26759a8ec399f0 \ + file://src/oid_ops.c;beginline=378;endline=398;md5=e02c165cb8383e950214baca2fbd664b \ +" + +SRC_URI = "http://www.citi.umich.edu/projects/nfsv4/linux/${BPN}/${BP}.tar.gz \ + file://libgssglue-canon-name.patch \ + file://libgssglue-gss-inq-cred.patch \ + file://libgssglue-mglueP.patch \ + file://libgssglue-g-initialize.patch \ + file://libgssglue-fix-CVE-2011-2709.patch \ +" + +SRC_URI[md5sum] = "088797f3180702fa54e786496b32e750" +SRC_URI[sha256sum] = "3f791a75502ba723e5e85e41e5e0c711bb89e2716b7c0ec6e74bd1df6739043a" + +# gssglue can use krb5, spkm3... as gssapi library, configurable +RRECOMMENDS_${PN} += "krb5" + +inherit autotools + +do_install_append() { + # install some docs + install -d -m 0755 ${D}${docdir}/${BPN} + install -m 0644 ${S}/AUTHORS ${S}/ChangeLog ${S}/NEWS ${S}/README ${D}${docdir}/${BPN} + + # install the gssapi_mech.conf + install -d -m 0755 ${D}${sysconfdir} + install -m 0644 ${S}/doc/gssapi_mech.conf ${D}${sysconfdir} + + # change the libgssapi_krb5.so path and name(it is .so.2) + sed -i -e "s:/usr/lib/libgssapi_krb5.so:libgssapi_krb5.so.2:" ${D}${sysconfdir}/gssapi_mech.conf +} diff --git a/meta-security/recipes-security/libmhash/files/Makefile.test b/meta-security/recipes-security/libmhash/files/Makefile.test new file mode 100644 index 000000000..2e32626e2 --- /dev/null +++ b/meta-security/recipes-security/libmhash/files/Makefile.test @@ -0,0 +1,13 @@ +# +# Makefile for compiling mhash tests +# + +ALL = mhash + +all: $(ALL) + +mhash: mhash.c + $(CC) $(CFLAGS) $(LDFLAGS) -o mhash mhash.c -lmhash + +clean: + rm -f *.debug $(ALL) diff --git a/meta-security/recipes-security/libmhash/files/mhash.c b/meta-security/recipes-security/libmhash/files/mhash.c new file mode 100644 index 000000000..5d123cc28 --- /dev/null +++ b/meta-security/recipes-security/libmhash/files/mhash.c @@ -0,0 +1,32 @@ +#include <mhash.h> +#include <stdio.h> + +int main() +{ + + char password[] = "Jefe"; + int keylen = 4; + char data[] = "what do ya want for nothing?"; + int datalen = 28; + MHASH td; + unsigned char mac[16]; + int j; + + td = mhash_hmac_init(MHASH_MD5, password, keylen, mhash_get_hash_pblock(MHASH_MD5)); + + mhash(td, data, datalen); + mhash_hmac_deinit(td, mac); + +/* + * The output should be 0x750c783e6ab0b503eaa86e310a5db738 + * according to RFC 2104. + */ + + printf("0x"); + for (j = 0; j < mhash_get_block_size(MHASH_MD5); j++) { + printf("%.2x", mac[j]); + } + printf("\n"); + + exit(0); +} diff --git a/meta-security/recipes-security/libmhash/files/run-ptest b/meta-security/recipes-security/libmhash/files/run-ptest new file mode 100644 index 000000000..2b0b94a6e --- /dev/null +++ b/meta-security/recipes-security/libmhash/files/run-ptest @@ -0,0 +1,12 @@ +#!/bin/sh + +OUTPUT=$($(dirname $0)/mhash) +MHASH_MD5="0x750c783e6ab0b503eaa86e310a5db738" + +if [ x"$OUTPUT" = x"$MHASH_MD5" ]; then + echo "PASS: mhash ptest" + exit 0 +else + echo "FAIL: mhash ptest" + exit 1 +fi diff --git a/meta-security/recipes-security/libmhash/libmhash_0.9.9.9.bb b/meta-security/recipes-security/libmhash/libmhash_0.9.9.9.bb new file mode 100644 index 000000000..9b34cb18c --- /dev/null +++ b/meta-security/recipes-security/libmhash/libmhash_0.9.9.9.bb @@ -0,0 +1,37 @@ +SUMMARY = "Library of hashing algorithms." +DESCRIPTION = "\ + Mhash is a free (under GNU Lesser GPL) library \ + which provides a uniform interface to a large number of hash \ + algorithms. These algorithms can be used to compute checksums, \ + message digests, and other signatures. \ + " +HOMEPAGE = "http://mhash.sourceforge.net/" + +LICENSE = "LGPLv2.0" +LIC_FILES_CHKSUM = "file://COPYING;md5=3bf50002aefd002f49e7bb854063f7e7" + +S = "${WORKDIR}/mhash-${PV}" + +SECTION = "libs" + +SRC_URI = "${SOURCEFORGE_MIRROR}/mhash/mhash-${PV}.tar.bz2 \ + file://Makefile.test \ + file://mhash.c \ + file://run-ptest \ + " + +SRC_URI[md5sum] = "f91c74f9ccab2b574a98be5bc31eb280" +SRC_URI[sha256sum] = "56521c52a9033779154432d0ae47ad7198914785265e1f570cee21ab248dfef0" + +inherit autotools-brokensep ptest + +do_compile_ptest() { + if [ ! -d ${S}/demo ]; then mkdir ${S}/demo; fi + cp ${WORKDIR}/Makefile.test ${S}/demo/Makefile + cp ${WORKDIR}/mhash.c ${S}/demo/ + make -C ${S}/demo CFLAGS="${CFLAGS} -I${S}/include/" LDFLAGS="${LDFLAGS} -L${S}/lib/.libs" +} + +do_install_ptest() { + install -m 0755 ${S}/demo/mhash ${D}${PTEST_PATH} +} diff --git a/meta-security/recipes-security/libmspack/libmspack_0.5.bb b/meta-security/recipes-security/libmspack/libmspack_0.5.bb new file mode 100644 index 000000000..80db23cec --- /dev/null +++ b/meta-security/recipes-security/libmspack/libmspack_0.5.bb @@ -0,0 +1,16 @@ +SUMMARY = "A library for Microsoft compression formats" +HOMEPAGE = "http://www.cabextract.org.uk/libmspack/" +SECTION = "lib" +LICENSE = "LGPL-2.1" +DEPENDS = "" + +LIC_FILES_CHKSUM = "file://COPYING.LIB;beginline=1;endline=2;md5=5b1fd1f66ef926b3c8a5bb00a72a28dd" + +SRC_URI = "${DEBIAN_MIRROR}/main/libm/${BPN}/${BPN}_${PV}.orig.tar.gz\ +" +SRC_URI[md5sum] = "3aa3f6b9ef101463270c085478fda1da" +SRC_URI[sha256sum] = "8967f275525f5067b364cee43b73e44d0433668c39f9376dfff19f653d1c8110" + +inherit autotools + +S = "${WORKDIR}/${BP}alpha" diff --git a/meta-security/recipes-security/libseccomp/files/run-ptest b/meta-security/recipes-security/libseccomp/files/run-ptest new file mode 100644 index 000000000..54b4a63cd --- /dev/null +++ b/meta-security/recipes-security/libseccomp/files/run-ptest @@ -0,0 +1,4 @@ +#!/bin/sh + +cd tests +./regression -a diff --git a/meta-security/recipes-security/libseccomp/libseccomp_2.3.3.bb b/meta-security/recipes-security/libseccomp/libseccomp_2.3.3.bb new file mode 100644 index 000000000..8d58163c9 --- /dev/null +++ b/meta-security/recipes-security/libseccomp/libseccomp_2.3.3.bb @@ -0,0 +1,42 @@ +SUMMARY = "interface to seccomp filtering mechanism" +DESCRIPTION = "The libseccomp library provides and easy to use, platform independent,interface to the Linux Kernel's syscall filtering mechanism: seccomp." +SECTION = "security" +LICENSE = "LGPL-2.1" +LIC_FILES_CHKSUM = "file://LICENSE;beginline=0;endline=1;md5=8eac08d22113880357ceb8e7c37f989f" + +SRCREV = "74b190e1aa05f07da0c61fb9a30dbc9c18ce2c9d" + +SRC_URI = "git://github.com/seccomp/libseccomp.git;branch=release-2.3 \ + file://run-ptest \ +" + +S = "${WORKDIR}/git" + +inherit autotools-brokensep pkgconfig ptest + +PACKAGECONFIG ??= "" +PACKAGECONFIG[python] = "--enable-python, --disable-python, python" + +do_compile_ptest() { + oe_runmake -C tests check-build +} + +do_install_ptest() { + install -d ${D}${PTEST_PATH}/tests + install -d ${D}${PTEST_PATH}/tools + for file in $(find tests/* -executable -type f); do + install -m 744 ${S}/${file} ${D}/${PTEST_PATH}/tests + done + for file in $(find tests/*.tests -type f); do + install -m 744 ${S}/${file} ${D}/${PTEST_PATH}/tests + done + for file in $(find tools/* -executable -type f); do + install -m 744 ${S}/${file} ${D}/${PTEST_PATH}/tools + done +} + +FILES_${PN} = "${bindir} ${libdir}/${PN}.so*" +FILES_${PN}-dbg += "${libdir}/${PN}/tests/.debug/* ${libdir}/${PN}/tools/.debug" + +RDEPENDS_${PN} = "bash" +RDEPENDS_${PN}-ptest = "bash" diff --git a/meta-security/recipes-security/nikto/files/CVE-2018-11652.patch b/meta-security/recipes-security/nikto/files/CVE-2018-11652.patch new file mode 100644 index 000000000..5ddb16926 --- /dev/null +++ b/meta-security/recipes-security/nikto/files/CVE-2018-11652.patch @@ -0,0 +1,106 @@ +From e759b3300aace5314fe3d30800c8bd83c81c29f7 Mon Sep 17 00:00:00 2001 +From: sullo <sullo@cirt.net> +Date: Thu, 31 May 2018 23:30:03 -0400 +Subject: [PATCH] Fix CSV injection issue if server responds with a malicious + Server string & CSV output is opened in Excel or other spreadsheet app. + Potentially malicious cell start characters are now prefaced with a ' mark. + Thanks to Adam (@bytesoverbombs) for letting me know! + +Also fixed a crash in the outdated plugin if the $sepr field ends up being something that triggers a panic in split(). + +CVE: CVE-2018-11652 +Upstream-Status: Backport +Signed-off-by: Nagalakshmi Veeramallu <nveeramallu@mvista.com> +--- + plugins/nikto_outdated.plugin | 2 +- + plugins/nikto_report_csv.plugin | 42 +++++++++++++++++++++++++++++------------ + 2 files changed, 31 insertions(+), 13 deletions(-) + +diff --git a/plugins/nikto_outdated.plugin b/plugins/nikto_outdated.plugin +index 72379cc..eb1d889 100644 +--- a/plugins/nikto_outdated.plugin ++++ b/plugins/nikto_outdated.plugin +@@ -83,7 +83,7 @@ sub nikto_outdated { + $sepr = substr($sepr, (length($sepr) - 1), 1); + + # break up ID string on $sepr +- my @T = split(/$sepr/, $mark->{'banner'}); ++ my @T = split(/\\$sepr/, $mark->{'banner'}); + + # assume last is version... + for ($i = 0 ; $i < $#T ; $i++) { $MATCHSTRING .= "$T[$i] "; } +diff --git a/plugins/nikto_report_csv.plugin b/plugins/nikto_report_csv.plugin +index d13acab..b942e78 100644 +--- a/plugins/nikto_report_csv.plugin ++++ b/plugins/nikto_report_csv.plugin +@@ -52,10 +52,12 @@ sub csv_open { + sub csv_host_start { + my ($handle, $mark) = @_; + $mark->{'banner'} =~ s/"/\\"/g; +- print OUT "\"$mark->{'hostname'}\"," +- . "\"$mark->{'ip'}\"," +- . "\"$mark->{'port'}\"," . "\"\"," . "\"\"," . "\"\"," +- . "\"$mark->{'banner'}\"\n"; ++ print $handle "\"" . csv_safecell($hostname) . "\"," ++ . "\"" . csv_safecell($mark->{'ip'}) . "\"," ++ . "\"" . csv_safecell($mark->{'port'}) . "\"," . "\"\"," . "\"\"," . "\"\"," ++ #. "\"" . $mark->{'banner'} . "\"\n"; ++ . "\"" . csv_safecell($mark->{'banner'}) . "\"\n"; ++ + return; + } + +@@ -65,26 +67,42 @@ sub csv_item { + my ($handle, $mark, $item) = @_; + foreach my $uri (split(' ', $item->{'uri'})) { + my $line = ''; +- $line .= "\"$item->{'mark'}->{'hostname'}\","; +- $line .= "\"$item->{'mark'}->{'ip'}\","; +- $line .= "\"$item->{'mark'}->{'port'}\","; ++ $line .= "\"" . csv_safecell($hostname) . "\","; ++ $line .= "\"" . csv_safecell($item->{'mark'}->{'ip'}) . \","; ++ $line .= "\"" . csv_safecell($item->{'mark'}->{'port'}) . "\","; + + $line .= "\""; + if ($item->{'osvdb'} ne '') { $line .= "OSVDB-" . $item->{'osvdb'}; } + $line .= "\","; + + $line .= "\""; +- if ($item->{'method'} ne '') { $line .= $item->{'method'}; } ++ if ($item->{'method'} ne '') { $line .= csv_safecell($item->{'method'}); } + $line .= "\","; + + $line .= "\""; +- if ($uri ne '') { $line .= $mark->{'root'} . $uri; } ++ { $line .= csv_safecell($mark->{'root'}) . $uri; } ++ else { $line .= csv_safecell($ur + $line .= "\","; + +- $item->{'message'} =~ s/"/\\"/g; +- $line .= "\"$item->{'message'}\""; +- print $handle "$line\n"; ++ my $msg = $item->{'message'}; ++ $uri=quotemeta($uri); ++ my $root = quotemeta($mark->{'root'}); ++ $msg =~ s/^$uri:\s//; ++ $msg =~ s/^$root$uri:\s//; ++ $msg =~ s/"/\\"/g; ++ $line .= "\"" . csv_safecell($msg) ."\""; ++ print $handle "$line\n"; ++ + } + } + ++############################################################################### ++# prevent CSV injection attacks ++sub csv_safecell { ++ my $celldata = $_[0] || return; ++ if ($celldata =~ /^[=+@-]/) { $celldata = "'" . $celldata; } ++ return $celldata; ++} ++ ++ + 1; +-- +2.6.4 + diff --git a/meta-security/recipes-security/nikto/files/location.patch b/meta-security/recipes-security/nikto/files/location.patch new file mode 100644 index 000000000..a95b0629f --- /dev/null +++ b/meta-security/recipes-security/nikto/files/location.patch @@ -0,0 +1,36 @@ +From e10b9b1f6704057ace39956ae1dc5c7caca07ff1 Mon Sep 17 00:00:00 2001 +From: Andrei Dinu <andrei.adrianx.dinu@intel.com> +Date: Mon, 8 Jul 2013 11:53:54 +0300 +Subject: [PATCH] Setting the location of nikto on the image + +Upstream Status: Inapropriate + +Signed-off-by: Andrei Dinu <andrei.adrianx.dinu@intel.com> +--- + nikto.conf | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/nikto.conf b/nikto.conf +index 25b784d..9577033 100644 +--- a/nikto.conf ++++ b/nikto.conf +@@ -61,11 +61,11 @@ CIRT=174.142.17.165 + CHECKMETHODS=HEAD GET + + # If you want to specify the location of any of the files, specify them here +-# EXECDIR=/opt/nikto # Location of Nikto +-# PLUGINDIR=/opt/nikto/plugins # Location of plugin dir +-# DBDIR=/opt/nikto/databases # Location of plugin dir +-# TEMPLATEDIR=/opt/nikto/templates # Location of tempmlate dir +-# DOCDIR=/opt/nikto/docs # Location of docs dir ++EXECDIR=/usr/bin/nikto # Location of Nikto ++PLUGINDIR=/etc/nikto/plugins # Location of plugin dir ++DBDIR=/etc/nikto/databases # Location of plugin dir ++TEMPLATEDIR=/etc/nikto/templates # Location of tempmlate dir ++DOCDIR=/usr/share/doc/nikto # Location of docs dir + + # Default plugin macros + @@MUTATE=dictionary;subdomain +-- +1.7.9.5 + diff --git a/meta-security/recipes-security/nikto/nikto_2.1.5.bb b/meta-security/recipes-security/nikto/nikto_2.1.5.bb new file mode 100644 index 000000000..19eb14f3e --- /dev/null +++ b/meta-security/recipes-security/nikto/nikto_2.1.5.bb @@ -0,0 +1,108 @@ +SUMMARY = "web server scanner" +DESCRIPTION = "Nikto is an Open Source (GPL) web server scanner which performs comprehensive tests against web servers for multiple items, including over 6500 potentially dangerous \ + files/CGIs, checks for outdated versions of over 1250 servers, and version specific problems on over 270 servers." +SECTION = "security" +LICENSE = "GPLv2" + +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6" + +SRC_URI = "http://cirt.net/nikto/${BP}.tar.gz \ + file://location.patch \ + file://CVE-2018-11652.patch" + +SRC_URI[md5sum] = "efcc98a918becb77471ee9a5df0a7b1e" +SRC_URI[sha256sum] = "0e672a6a46bf2abde419a0e8ea846696d7f32e99ad18a6b405736ee6af07509f" + +do_install() { + install -d ${D}${bindir} + install -d ${D}${datadir} + install -d ${D}${datadir}/man/man1 + install -d ${D}${datadir}/doc/nikto + install -d ${D}${sysconfdir}/nikto + install -d ${D}${sysconfdir}/nikto/databases + install -d ${D}${sysconfdir}/nikto/plugins + install -d ${D}${sysconfdir}/nikto/templates + + install -m 0644 databases/db_404_strings ${D}${sysconfdir}/nikto/databases + install -m 0644 databases/db_content_search ${D}${sysconfdir}/nikto/databases + install -m 0644 databases/db_dictionary ${D}${sysconfdir}/nikto/databases + install -m 0644 databases/db_embedded ${D}${sysconfdir}/nikto/databases + install -m 0644 databases/db_favicon ${D}${sysconfdir}/nikto/databases + install -m 0644 databases/db_headers ${D}${sysconfdir}/nikto/databases + install -m 0644 databases/db_httpoptions ${D}${sysconfdir}/nikto/databases + install -m 0644 databases/db_multiple_index ${D}${sysconfdir}/nikto/databases + install -m 0644 databases/db_outdated ${D}${sysconfdir}/nikto/databases + install -m 0644 databases/db_parked_strings ${D}${sysconfdir}/nikto/databases + install -m 0644 databases/db_realms ${D}${sysconfdir}/nikto/databases + install -m 0644 databases/db_server_msgs ${D}${sysconfdir}/nikto/databases + install -m 0644 databases/db_subdomains ${D}${sysconfdir}/nikto/databases + install -m 0644 databases/db_tests ${D}${sysconfdir}/nikto/databases + install -m 0644 databases/db_variables ${D}${sysconfdir}/nikto/databases + + install -m 0644 plugins/JSON-PP.pm ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/LW2.pm ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_apache_expect_xss.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_apacheusers.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_auth.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_cgi.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_clientaccesspolicy.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_content_search.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_cookies.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_core.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_dictionary_attack.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_embedded.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_favicon.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_fileops.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_headers.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_httpoptions.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_msgs.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_multiple_index.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_outdated.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_parked.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_paths.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_put_del_test.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_report_csv.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_report_html.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_report_msf.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_report_nbe.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_report_text.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_report_xml.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_robots.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_siebel.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_ssl.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_subdomain.plugin ${D}${sysconfdir}/nikto/plugins + install -m 0644 plugins/nikto_tests.plugin ${D}${sysconfdir}/nikto/plugins + + install -m 0644 templates/htm_close.tmpl ${D}${sysconfdir}/nikto/templates + install -m 0644 templates/htm_end.tmpl ${D}${sysconfdir}/nikto/templates + install -m 0644 templates/htm_host_head.tmpl ${D}${sysconfdir}/nikto/templates + install -m 0644 templates/htm_host_im.tmpl ${D}${sysconfdir}/nikto/templates + install -m 0644 templates/htm_host_item.tmpl ${D}${sysconfdir}/nikto/templates + install -m 0644 templates/htm_start.tmpl ${D}${sysconfdir}/nikto/templates + install -m 0644 templates/htm_stop.tmpl ${D}${sysconfdir}/nikto/templates + install -m 0644 templates/htm_start.tmpl ${D}${sysconfdir}/nikto/templates + install -m 0644 templates/htm_summary.tmpl ${D}${sysconfdir}/nikto/templates + install -m 0644 templates/xml_end.tmpl ${D}${sysconfdir}/nikto/templates + install -m 0644 templates/xml_host_head.tmpl ${D}${sysconfdir}/nikto/templates + install -m 0644 templates/xml_host_im.tmpl ${D}${sysconfdir}/nikto/templates + install -m 0644 templates/xml_host_item.tmpl ${D}${sysconfdir}/nikto/templates + install -m 0644 templates/xml_start.tmpl ${D}${sysconfdir}/nikto/templates + install -m 0644 templates/xml_summary.tmpl ${D}${sysconfdir}/nikto/templates + + install -m 0644 nikto.conf ${D}${sysconfdir} + + install -m 0755 nikto.pl ${D}${bindir}/nikto + install -m 0644 replay.pl ${D}${bindir} + install -m 0644 docs/nikto.1 ${D}${datadir}/man/man1 + + install -m 0644 docs/CHANGES.txt ${D}${datadir}/doc/nikto + install -m 0644 docs/LICENSE.txt ${D}${datadir}/doc/nikto + install -m 0644 docs/nikto.dtd ${D}${datadir}/doc/nikto + install -m 0644 docs/nikto_manual.html ${D}${datadir}/doc/nikto +} + +RDEPENDS_${PN} = "perl libnet-ssleay-perl libwhisker2-perl \ + perl-module-getopt-long perl-module-time-local \ + perl-module-io-socket perl-module-overloading \ + perl-module-base perl-module-b perl-module-bytes \ + nikto-doc" diff --git a/meta-security/recipes-security/nmap/files/nmap-redefine-the-python-library-dir.patch b/meta-security/recipes-security/nmap/files/nmap-redefine-the-python-library-dir.patch new file mode 100644 index 000000000..356b5071b --- /dev/null +++ b/meta-security/recipes-security/nmap/files/nmap-redefine-the-python-library-dir.patch @@ -0,0 +1,37 @@ +[PATCH] redefine the python library install dir + +Upstream-Status: Pending + +If install-lib is not defined, it is always /usr/lib/, but it +maybe /usr/lib64 for multilib + +Signed-off-by: Roy Li <rongqing.li@windriver.com> +--- + Makefile.in | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/Makefile.in b/Makefile.in +index 1bb062c..cced2fb 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -311,7 +311,7 @@ build-zenmap: $(ZENMAPDIR)/setup.py $(ZENMAPDIR)/zenmapCore/Version.py + + install-zenmap: $(ZENMAPDIR)/setup.py + $(INSTALL) -d $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man1 +- cd $(ZENMAPDIR) && $(PYTHON) setup.py --quiet install --prefix "$(prefix)" --force $(if $(DESTDIR),--root "$(DESTDIR)") ++ cd $(ZENMAPDIR) && $(PYTHON) setup.py --quiet install --prefix "$(prefix)" --install-lib="${PYTHON_SITEPACKAGES_DIR}" --force $(if $(DESTDIR),--root "$(DESTDIR)") + $(INSTALL) -c -m 644 docs/zenmap.1 $(DESTDIR)$(mandir)/man1/ + # Create a symlink from nmapfe to zenmap if nmapfe doesn't exist or is + # already a link. +@@ -328,7 +328,7 @@ build-nping: $(NPINGDIR)/Makefile nbase_build nsock_build netutil_build $(NPINGD + @cd $(NPINGDIR) && $(MAKE) + + install-ndiff: +- cd $(NDIFFDIR) && $(PYTHON) setup.py install --prefix "$(prefix)" $(if $(DESTDIR),--root "$(DESTDIR)") ++ cd $(NDIFFDIR) && $(PYTHON) setup.py install --prefix "$(prefix)" --install-lib="${PYTHON_SITEPACKAGES_DIR}" $(if $(DESTDIR),--root "$(DESTDIR)") + + NSE_FILES = scripts/script.db scripts/*.nse + NSE_LIB_LUA_FILES = nselib/*.lua nselib/*.luadoc +-- +1.9.1 + diff --git a/meta-security/recipes-security/nmap/files/nmap-replace-shtool-mkdir-with-coreutils-mkdir-command.patch b/meta-security/recipes-security/nmap/files/nmap-replace-shtool-mkdir-with-coreutils-mkdir-command.patch new file mode 100644 index 000000000..cfe043af4 --- /dev/null +++ b/meta-security/recipes-security/nmap/files/nmap-replace-shtool-mkdir-with-coreutils-mkdir-command.patch @@ -0,0 +1,48 @@ +[PATCH] replace "./shtool mkdir" with coreutils mkdir command + +Upstream-Status: Pending + +"./shtool mkdir" is used when mkdir has not -p parameter, but mkdir in today +most release has supportted the -p parameter, not need to use shtool, and it +can not fix the race if two process are running mkdir to create same dir + +Signed-off-by: Roy Li <rongqing.li@windriver.com> +--- + ncat/Makefile.in | 4 ++-- + nmap-update/Makefile.in | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/ncat/Makefile.in b/ncat/Makefile.in +index cfd306d..2166e08 100644 +--- a/ncat/Makefile.in ++++ b/ncat/Makefile.in +@@ -163,11 +163,11 @@ $(NSOCKDIR)/libnsock.a: $(NSOCKDIR)/Makefile + + install: $(TARGET) + @echo Installing Ncat; +- $(SHTOOL) mkdir -f -p -m 755 $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man1 ++ mkdir -p -m 755 $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man1 + $(INSTALL) -c -m 755 ncat $(DESTDIR)$(bindir)/ncat + $(STRIP) -x $(DESTDIR)$(bindir)/ncat + if [ -n "$(DATAFILES)" ]; then \ +- $(SHTOOL) mkdir -f -p -m 755 $(DESTDIR)$(pkgdatadir); \ ++ mkdir -p -m 755 $(DESTDIR)$(pkgdatadir); \ + $(INSTALL) -c -m 644 $(DATAFILES) $(DESTDIR)$(pkgdatadir)/; \ + fi + $(INSTALL) -c -m 644 docs/$(TARGET).1 $(DESTDIR)$(mandir)/man1/$(TARGET).1 +diff --git a/nmap-update/Makefile.in b/nmap-update/Makefile.in +index 89ff928..93f48d8 100644 +--- a/nmap-update/Makefile.in ++++ b/nmap-update/Makefile.in +@@ -37,7 +37,7 @@ $(NBASELIB): + cd $(NBASEDIR) && $(MAKE) + + install: nmap-update +- $(SHTOOL) mkdir -f -p -m 755 $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man1 ++ mkdir -p -m 755 $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man1 + $(INSTALL) -c -m 755 nmap-update $(DESTDIR)$(bindir) + $(STRIP) -x $(DESTDIR)$(bindir)/nmap-update + $(INSTALL) -c -m 644 ../docs/nmap-update.1 $(DESTDIR)$(mandir)/man1/ +-- +1.9.1 + diff --git a/meta-security/recipes-security/nmap/nmap_7.60.bb b/meta-security/recipes-security/nmap/nmap_7.60.bb new file mode 100644 index 000000000..a6616eb13 --- /dev/null +++ b/meta-security/recipes-security/nmap/nmap_7.60.bb @@ -0,0 +1,54 @@ +SUMMARY = "network auditing tool" +DESCRIPTION = "Nmap ("Network Mapper") is a free and open source (license) utility for network discovery and security auditing.\nGui support via appending to IMAGE_FEATURES x11-base in local.conf" +SECTION = "security" +LICENSE = "GPL-2.0" + +LIC_FILES_CHKSUM = "file://COPYING;beginline=7;endline=12;md5=700c690f4ca6b1754f3f1db8645e42d9" + +SRC_URI = "http://nmap.org/dist/${BP}.tar.bz2 \ + file://nmap-redefine-the-python-library-dir.patch \ + file://nmap-replace-shtool-mkdir-with-coreutils-mkdir-command.patch \ +" + +SRC_URI[md5sum] = "4e454266559ddf2c4e2109866c62560c" +SRC_URI[sha256sum] = "a8796ecc4fa6c38aad6139d9515dc8113023a82e9d787e5a5fb5fa1b05516f21" + +inherit autotools-brokensep pkgconfig pythonnative distro_features_check + +PACKAGECONFIG ?= "ncat nping ndiff pcap" +PACKAGECONFIG += " ${@bb.utils.contains('IMAGE_FEATURES', 'x11-base', 'zenmap', '', d)}" + +PACKAGECONFIG[pcap] = "--with-pcap=linux, --without-pcap, libpcap, libpcap" +PACKAGECONFIG[pcre] = "--with-libpcre=${STAGING_LIBDIR}/.., --with-libpcre=included, libpre" +PACKAGECONFIG[ssl] = "--with-openssl=${STAGING_LIBDIR}/.., --without-openssl, openssl, openssl" +PACKAGECONFIG[ssh2] = "--with-openssh2=${STAGING_LIBDIR}/.., --without-openssh2, libssh2, libssh2" +PACKAGECONFIG[libz] = "--with-libz=${STAGING_LIBDIR}/.., --without-libz, zlib, zlib" + +#disable/enable packages +PACKAGECONFIG[nping] = ",--without-nping," +PACKAGECONFIG[ncat] = ",--without-ncat," +PACKAGECONFIG[ndiff] = ",--without-ndiff,python" +PACKAGECONFIG[update] = ",--without-nmap-update," + +#Add gui +PACKAGECONFIG[zenmap] = "--with-zenmap, --without-zenmap, gtk+ python-core python-codecs python-io python-logging python-unittest python-xml python-netclient python-doctest python-subprocess python-pygtk, python-core python-codecs python-io python-logging python-netclient python-xml python-unittest python-doctest python-subprocess python-pygtk gtk+" + +EXTRA_OECONF = "--with-libdnet=included --with-liblinear=included --without-subversion --with-liblua=included" + +export PYTHON_SITEPACKAGES_DIR + +do_configure() { + # strip hard coded python2# + sed -i -e 's=python2\.*=python=g' ${S}/configure.ac + sed -i -e 's=python2\.*=python=g' ${S}/configure + autoconf + oe_runconf +} + +PACKAGES += "${@bb.utils.contains('PACKAGECONFIG', 'zenmap', '${PN}-zenmap', '', d)}" + +FILES_${PN} += "${PYTHON_SITEPACKAGES_DIR}" +FILES_${PN}-zenmap = "${@bb.utils.contains("PACKAGECONFIG", "zenmap", "${bindir}/*zenmap ${bindir}/xnmap ${datadir}/applications/* ${bindir}/nmapfe ${datadir}/zenmap/* ${PYTHON_SITEPACKAGES_DIR}/radialnet/* ${PYTHON_SITEPACKAGES_DIR}/zenmap*", "", d)}" + +RDEPENDS_${PN} = "python" +RDEPENDS_${PN}-zenmap = "nmap" diff --git a/meta-security/recipes-security/packagegroup/packagegroup-core-security.bb b/meta-security/recipes-security/packagegroup/packagegroup-core-security.bb new file mode 100644 index 000000000..6682d2905 --- /dev/null +++ b/meta-security/recipes-security/packagegroup/packagegroup-core-security.bb @@ -0,0 +1,64 @@ +DESCRIPTION = "Security packagegroup for Poky" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302 \ + file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-core-security \ + packagegroup-security-utils \ + packagegroup-security-scanners \ + packagegroup-security-ids \ + packagegroup-security-mac \ + ${@bb.utils.contains("MACHINE_FEATURES", "tpm", "packagegroup-security-tpm", "",d)} \ + " + +RDEPENDS_packagegroup-core-security = "\ + packagegroup-security-utils \ + packagegroup-security-scanners \ + packagegroup-security-ids \ + packagegroup-security-mac \ + ${@bb.utils.contains("MACHINE_FEATURES", "tpm", "packagegroup-security-tpm", "",d)} \ + " + +SUMMARY_packagegroup-security-utils = "Security utilities" +RDEPENDS_packagegroup-security-utils = "\ + checksec \ + nmap \ + pinentry \ + scapy \ + ${@bb.utils.contains("DISTRO_FEATURES", "pax", "pax-utils", "",d)} \ + " + +SUMMARY_packagegroup-security-scanners = "Security scanners" +RDEPENDS_packagegroup-security-scanners = "\ + nikto \ + checksecurity \ + clamav \ + " + +SUMMARY_packagegroup-security-audit = "Security Audit tools " +RDEPENDS_packagegroup-security-audit = " \ + buck-security \ + redhat-security \ + " + +SUMMARY_packagegroup-security-hardening = "Security Hardening tools" +RDEPENDS_packagegroup-security-hardening = " \ + bastille \ + " + +SUMMARY_packagegroup-security-ids = "Security Intrusion Detection systems" +RDEPENDS_packagegroup-security-ids = " \ + tripwire \ + samhain-client \ + suricata \ + " + +SUMMARY_packagegroup-security-mac = "Security Mandatory Access Control systems" +RDEPENDS_packagegroup-security-mac = " \ + ${@bb.utils.contains("DISTRO_FEATURES", "tomoyo", "ccs-tools", "",d)} \ + ${@bb.utils.contains("DISTRO_FEATURES", "apparmor", "", "",d)} \ + ${@bb.utils.contains("DISTRO_FEATURES", "smack", "smack", "",d)} \ + " diff --git a/meta-security/recipes-security/paxctl/paxctl_0.9.bb b/meta-security/recipes-security/paxctl/paxctl_0.9.bb new file mode 100644 index 000000000..3c04141ee --- /dev/null +++ b/meta-security/recipes-security/paxctl/paxctl_0.9.bb @@ -0,0 +1,38 @@ +DESCRIPTION = "paxctl is a tool that allows PaX flags to be modified on a \ + per-binary basis. PaX is part of common security-enhancing \ + kernel patches and secure distributions, such as \ + GrSecurity or Adamantix and Hardened Gen-too, respectively." +HOMEPAGE = "https://pax.grsecurity.net/" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://paxctl.c;beginline=1;endline=5;md5=0ddd065c61020dda79729e6bedaed2c7 \ + file://paxctl-elf.c;beginline=1;endline=5;md5=99f453ce7f6d1687ee808982e2924813 \ + " + +SRC_URI = "http://pax.grsecurity.net/${BP}.tar.gz" + +SRC_URI[md5sum] = "9bea59b1987dc4e16c2d22d745374e64" +SRC_URI[sha256sum] = "a330ddd812688169802a3ba29e5e3b19956376b8f6f73b8d7e9586eb04423c2e" + +EXTRA_OEMAKE = "CC='${CC}' DESTDIR='${D}'" + +do_install() { + oe_runmake install +} + +# The install target in the Makefile will fail for paxctl-native with error: +# install -D --owner 0 --group 0 --mode a=rx paxctl .../sbin/paxctl +# install: cannot change ownership of '.../sbin/paxctl': \ +# Operation not permitted +# Drop '--owner 0 --group 0' to fix the issue. +do_install_class-native() { + local PROG=paxctl + install -d ${D}${base_sbindir} + install -d ${D}${mandir}/man1 + install --mode a=rx $PROG ${D}${base_sbindir}/$PROG + install --mode a=r $PROG.1 ${D}${mandir}/man1/$PROG.1 +} + +# Avoid QA Issue: No GNU_HASH in the elf binary +INSANE_SKIP_${PN} = "ldflags" + +BBCLASSEXTEND = "native" diff --git a/meta-security/recipes-security/redhat-security/files/find-chroot-py.sh b/meta-security/recipes-security/redhat-security/files/find-chroot-py.sh new file mode 100644 index 000000000..9996e087c --- /dev/null +++ b/meta-security/recipes-security/redhat-security/files/find-chroot-py.sh @@ -0,0 +1,96 @@ +#!/bin/sh +# +# find-chroot-py utility +# Copyright (c) 2011 Steve Grubb. ALL RIGHTS RESERVED. +# sgrubb@redhat.com +# +# This software may be freely redistributed under the terms of the GNU +# public license. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# This program looks for python apps that use chroot(2) without using chdir(2) +# +# To save to file: ./find-chroot | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" | tee findings.txt + +libdirs="/lib /lib64 /usr/lib /usr/lib64" +progdirs="/bin /sbin /usr/bin /usr/sbin /usr/libexec" +FOUND=0 + +# First param is which list to use, second is search pattern +scan () { +if [ "$1" = "1" ] ; then + dirs=$libdirs +elif [ "$1" = "2" ] ; then + dirs=$progdirs +elif [ "$1" = "3" ] ; then + dirs=$3 +fi + +for d in $dirs ; do + if [ ! -d $d ] ; then + continue + fi + files=`/usr/bin/find $d -name "$2" -type f 2>/dev/null` + for f in $files + do + if [ "$1" = "2" ] ; then + testf=`/usr/bin/file $f | egrep 'ython'` + if [ x"$testf" = "x" ] ; then + continue + fi + fi + syms=`egrep ' os.chroot' $f` + if [ x"$syms" != "x" ] ; then + syms=`egrep ' os.chdir' $f` + if [ x"$syms" = "x" ] ; then + if [ $FOUND = 0 ] ; then + printf "%-44s%s\n" "FILE" " PACKAGE" + FOUND=1 + fi + # Red + printf "\033[31m%-44s\033[m" $f + #rpm -qf --queryformat "%{NAME}-%{VERSION}" $f + rpm -qf --queryformat " %{SOURCERPM}" $f + echo + else + # One last test to see if chdir is within 4 + # lines of chroot + syms=`cat $f | egrep ' os.chroot' -A3 | egrep ' os.chdir'` + if [ x"$syms" = "x" ] ; then + if [ $FOUND = 0 ] ; then + printf "%-44s%s\n" "FILE" " PACKAGE" + FOUND=1 + fi + printf "\033[31m%-44s\033[m" $f + rpm -qf --queryformat " %{SOURCERPM}" $f + echo + fi + fi + fi + done +done +} + +if [ $# -eq 1 ] ; then + if [ -d $1 ] ; then + scan 3 '*' $1 + else + echo "Input is not a directory" + exit 1 + fi +else + scan 2 '*' + scan 1 '*.py' +fi + +if [ $FOUND -eq 0 ] ; then + # Nothing to report, just exit + echo "No problems found" 1>&2 + exit 0 +fi +exit 1 + + diff --git a/meta-security/recipes-security/redhat-security/files/find-chroot.sh b/meta-security/recipes-security/redhat-security/files/find-chroot.sh new file mode 100644 index 000000000..adce7fc8e --- /dev/null +++ b/meta-security/recipes-security/redhat-security/files/find-chroot.sh @@ -0,0 +1,93 @@ +#!/bin/sh +# +# find-chroot utility +# Copyright (c) 2011 Steve Grubb. ALL RIGHTS RESERVED. +# sgrubb@redhat.com +# +# This software may be freely redistributed under the terms of the GNU +# public license. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# This program looks for apps that use chroot(2) without using chdir(2) +# +# To save to file: ./find-chroot | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" | tee findings.txt + +libdirs="/lib /lib64 /usr/lib /usr/lib64" +progdirs="/bin /sbin /usr/bin /usr/sbin /usr/libexec" +FOUND=0 + +# First param is which list to use, second is search pattern +scan () { +if [ "$1" = "1" ] ; then + dirs=$libdirs +elif [ "$1" = "2" ] ; then + dirs=$progdirs +elif [ "$1" = "3" ] ; then + dirs=$3 +fi + +for d in $dirs ; do + if [ ! -d $d ] ; then + continue + fi + files=`/usr/bin/find $d -name "$2" -type f 2>/dev/null` + for f in $files + do + syms=`/usr/bin/readelf -s $f 2>/dev/null | egrep ' chroot@.*GLIBC'` + if [ x"$syms" != "x" ] ; then + syms=`/usr/bin/readelf -s $f 2>/dev/null | egrep ' chdir@.*GLIBC'` + if [ x"$syms" = "x" ] ; then + if [ $FOUND = 0 ] ; then + printf "%-44s%s\n" "FILE" " PACKAGE" + FOUND=1 + fi + # Red + printf "\033[31m%-44s\033[m" $f + #rpm -qf --queryformat "%{NAME}-%{VERSION}" $f + rpm -qf --queryformat " %{SOURCERPM}" $f + echo + else + # One last test to see if chdir is within 3 + # lines of chroot + syms=`objdump -d $f | egrep callq | egrep 'chroot@plt' -A2 | egrep 'chroot|chdir'` + if [ x"$syms" = "x" ] ; then + syms=`echo $f | egrep -v 'libc-2|libc.so'` + if [ x"$syms" != "x" ] ; then + if [ $FOUND = 0 ] ; then + printf "%-44s%s\n" "FILE" "PACKAGE" + FOUND=1 + fi + printf "\033[31m%-44s\033[m" $f + rpm -qf --queryformat " %{SOURCERPM}" $f + echo + fi + fi + fi + fi + done +done +} + +if [ $# -eq 1 ] ; then + if [ -d $1 ] ; then + scan 3 '*' $1 + else + echo "Input is not a directory" + exit 1 + fi +else + scan 2 '*' + scan 1 '*.so' +fi + +if [ $FOUND -eq 0 ] ; then + # Nothing to report, just exit + echo "No problems found" 1>&2 + exit 0 +fi +exit 1 + + diff --git a/meta-security/recipes-security/redhat-security/files/find-elf4tmp.sh b/meta-security/recipes-security/redhat-security/files/find-elf4tmp.sh new file mode 100644 index 000000000..3118a70ec --- /dev/null +++ b/meta-security/recipes-security/redhat-security/files/find-elf4tmp.sh @@ -0,0 +1,84 @@ +#!/bin/sh +# find_elf4tmp utility +# Copyright (c) 2010-12 Steve Grubb. ALL RIGHTS RESERVED. +# sgrubb@redhat.com +# +# This software may be freely redistributed under the terms of the GNU +# public license. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +# This script will search a directory and its subdirectories for all elf +# executables. It will then search for the use of the tmp directory. If it finds +# this is true, it will then check to see if XXX is being used which would +# indicate that the path is going to be randomized. + +if [ $# -ge 2 ] ; then + echo "Usage: find_elf4tmp [directory]" 1>&2 + exit 1 +fi +if [ ! -x /usr/bin/strings ] ; then + echo "Skipping due to missing /usr/bin/eu-strings utility" + exit 1 +fi +if [ -h /bin ] ; then + DIRS="/usr/bin /usr/sbin /usr/libexec /usr/kerberos /usr/games /usr/lib /usr/lib64 /usr/local" +else + DIRS="/bin /sbin /usr/bin /usr/sbin /usr/libexec /usr/kerberos /usr/games /lib /lib64 /usr/lib /usr/lib64 /usr/local" +fi +if [ $# -eq 1 ] ; then + if [ -d "$1" ] ; then + DIRS="$1" + else + echo "Option passed in was not a directory" 1>&2 + exit 1 + fi +fi + +FOUND=0 +for d in $DIRS +do + if [ ! -d $d ] ; then + continue + fi +# echo "Scanning files in $d..." + for f in `/usr/bin/find $d -type f 2>/dev/null` + do + # Get just the elf executables + testf=`echo $f | /usr/bin/file -n -f - 2>/dev/null | grep ELF` + if [ x"$testf" != "x" ] ; then + test_res=`/usr/bin/strings $f | /bin/grep '/tmp/' | /bin/egrep -v 'XX|/tmp/$|[ .,:]/tmp/'` + if [ x"$test_res" = "x" ] ; then + continue + fi + + # Do further examination... + syms=`/usr/bin/readelf -s $f 2>/dev/null | egrep ' mkstemp@.*GLIBC| tempnam@.*GLIBC| tmpfile@.*GLIBC'` + if [ x"$syms" != "x" ] ; then + continue + fi + + # Well its a bad one...out with it + FOUND=1 + + # Get the package + RPM=`/bin/rpm -qf --queryformat "%{NAME}-%{VERSION}" $f 2>/dev/null | /bin/grep -v 'not owned' | /usr/bin/sort | /usr/bin/uniq` + if [ x"$RPM" = "x" ] ; then + RPM="<unowned>" + fi + + # For each tmp string, output the line + echo $test_res | /usr/bin/tr '\b' '\n' | /usr/bin/awk 'NF >= 1 { printf "%-46s\t%-30s\t%s\n", f, r, $1 }' r=$RPM f=$f + fi + done +done +if [ $FOUND -eq 0 ] ; then + # Nothing to report, just exit + echo "No problems found" 1>&2 + exit 0 +fi +exit 1 + + diff --git a/meta-security/recipes-security/redhat-security/files/find-execstack.sh b/meta-security/recipes-security/redhat-security/files/find-execstack.sh new file mode 100644 index 000000000..85f16de6d --- /dev/null +++ b/meta-security/recipes-security/redhat-security/files/find-execstack.sh @@ -0,0 +1,72 @@ +#!/bin/sh +# +# find-execstack utility +# Copyright (c) 2007 Steve Grubb. ALL RIGHTS RESERVED. +# sgrubb@redhat.com +# +# This software may be freely redistributed under the terms of the GNU +# public license. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# This program looks for executable stacks +# + +libdirs="/lib /lib64 /usr/lib /usr/lib64" +progdirs="/bin /sbin /usr/bin /usr/sbin /usr/libexec" +FOUND=0 + +# First param is which list to use, second is search pattern +scan () { +if [ "$1" = "1" ] ; then + dirs=$libdirs +elif [ "$1" = "2" ] ; then + dirs=$progdirs +fi + +for d in $dirs ; do + if [ ! -d $d ] ; then + continue + fi + files=`/usr/bin/find $d -name "$2" -type f 2>/dev/null` + for f in $files + do + FOUND_ONE=0 + stacks=`/usr/bin/eu-readelf -l $f 2>/dev/null | grep STACK` + if [ x"$stacks" != "x" ] ; then + perms=`echo $stacks | /bin/awk '{ print $7 }'` + if [ x"$perms" != x -a "$perms" != "RW" ] ; then + FOUND_ONE=1 + fi + fi + old_stacks=`echo $stacks | /bin/grep -v GNU_STACK` + if [ x"$old_stacks" != "x" ] ; then + FOUND_ONE=1 + fi + heaps=`/usr/bin/eu-readelf -l $f 2>/dev/null | grep GNU_HEAP` + if [ x"$heaps" != "x" ] ; then + FOUND_ONE=1 + fi + if [ $FOUND_ONE = 1 ] ; then + printf "%-42s" $f + rpm -qf --queryformat "%{SOURCERPM}" $f + echo + FOUND=1 + fi + done +done +} + +scan 1 '*.so' +scan 2 '*' + +if [ $FOUND -eq 0 ] ; then + # Nothing to report, just exit + echo "No problems found" 1>&2 + exit 0 +fi +exit 1 + + diff --git a/meta-security/recipes-security/redhat-security/files/find-hidden-exec.sh b/meta-security/recipes-security/redhat-security/files/find-hidden-exec.sh new file mode 100644 index 000000000..f799fca8f --- /dev/null +++ b/meta-security/recipes-security/redhat-security/files/find-hidden-exec.sh @@ -0,0 +1,21 @@ +#!/bin/sh +# +# +# This software may be freely redistributed under the terms of the GNU +# public license. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# This program looks for hidden executables + +find / -name '.*' -type f -perm /00111 2>/dev/null + +# Also need to find hidden dirs and see if anything below it is hidden +hidden_dirs=`find / -name '.*' -type d 2>/dev/null` +for d in $hidden_dirs +do + find $d -name '.*' -type f -perm /00111 2>/dev/null +done + diff --git a/meta-security/recipes-security/redhat-security/files/find-nodrop-groups.sh b/meta-security/recipes-security/redhat-security/files/find-nodrop-groups.sh new file mode 100644 index 000000000..249eacd2f --- /dev/null +++ b/meta-security/recipes-security/redhat-security/files/find-nodrop-groups.sh @@ -0,0 +1,85 @@ +#!/bin/sh +# +# find-nodrop-groups utility +# Copyright (c) 2011 Steve Grubb. ALL RIGHTS RESERVED. +# sgrubb@redhat.com +# +# This software may be freely redistributed under the terms of the GNU +# public license. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# This program looks for apps that use setgid(2) without using initgroups(3) +# or setgroups(2). +# +# To save to file: ./find-nodrop-groups | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" | tee findings.txt + +libdirs="/lib /lib64 /usr/lib /usr/lib64" +progdirs="/bin /sbin /usr/bin /usr/sbin /usr/libexec" +FOUND=0 + +# First param is which list to use, second is search pattern +scan () { +if [ "$1" = "1" ] ; then + dirs=$libdirs +elif [ "$1" = "2" ] ; then + dirs=$progdirs +elif [ "$1" = "3" ] ; then + dirs=$3 +fi + +for d in $dirs ; do + if [ ! -d $d ] ; then + continue + fi + files=`/usr/bin/find $d -name "$2" -type f 2>/dev/null` + for f in $files + do + syms=`/usr/bin/readelf -s $f 2>/dev/null | egrep ' setgid@.*GLIBC| setegid@.*GLIBC| setresgid@.*GLIBC'` + if [ x"$syms" != "x" ] ; then + syms=`/usr/bin/readelf -s $f 2>/dev/null | egrep ' setuid@.*GLIBC| seteuid@.*GLIBC| setresuid@.*GLIBC'` + if [ x"$syms" != "x" ] ; then + syms=`/usr/bin/readelf -s $f 2>/dev/null | egrep ' setgroups@.*GLIBC| initgroups@.*GLIBC'` + if [ x"$syms" = "x" ] ; then + if [ $FOUND = 0 ] ; then + printf "%-44s%s\n" "FILE" "PACKAGE" + fi + syms=`find $f \( -perm -004000 -o -perm -002000 \) -type f -print` + if [ x"$syms" = "x" ] ; then + printf "\033[31m%-44s\033[m" $f + rpm -qf --queryformat "%{SOURCERPM}" $f + echo + FOUND=1 +# else +# printf "\033[33m%-44s\033[m" $f + fi + #rpm -qf --queryformat "%{NAME}-%{VERSION}" $f + fi + fi + fi + done +done +} + +if [ $# -eq 1 ] ; then + if [ -d $1 ] ; then + scan 3 '*' $1 + else + echo "Input is not a directory" + exit 1 + fi +else + scan 1 '*.so' + scan 2 '*' +fi + +if [ $FOUND -eq 0 ] ; then + # Nothing to report, just exit + echo "No problems found" 1>&2 + exit 0 +fi +exit 1 + + diff --git a/meta-security/recipes-security/redhat-security/files/find-sh4errors.sh b/meta-security/recipes-security/redhat-security/files/find-sh4errors.sh new file mode 100644 index 000000000..0054a6a75 --- /dev/null +++ b/meta-security/recipes-security/redhat-security/files/find-sh4errors.sh @@ -0,0 +1,132 @@ +#!/bin/sh +# find_sh4errors utility +# Copyright (c) 2004 Steve Grubb. ALL RIGHTS RESERVED. +# sgrubb@redhat.com +# +# This software may be freely redistributed under the terms of the GNU +# public license. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +# This script will search a directory and its subdirectories for every shell +# script. It then runs sh -n to see if bash can determine if there are obvious +# parsing errors. It does have a bug in that bash -n does not take into +# account someone may program an unconditional exit and then include man page +# generation information. It also fails to notice the exec command. When you +# run across files that do either of the above, add it to the KNOWN_BAD list. + +if [ $# -ge 2 ] ; then + echo "Usage: find_sh4errors [directory]" 1>&2 + exit 1 +fi +INTERPRETERS="wish wishx tclsh guile rep itkwish expect /etc/kde/kdm/Xsession /etc/X11/xdm/Xsession /usr/bin/festival perl hfssh" +SKIP_DIRS="/opt /home /root" +KNOWN_BAD="/usr/bin/kde-build /usr/bin/cvsversion samples/copifuncs/copi.sendifm1 bashdb bash_completion_test" +DIR="/" +if [ $# -eq 1 ] ; then + if [ -d "$1" ] ; then + DIR="$1" + else + echo "Option passed in was not a directory" 1>&2 + exit 1 + fi +fi +tempfile=`mktemp /tmp/sh4.XXXXXX` +tempfile2=`mktemp /tmp/sh4.XXXXXX` +if [ -z "$tempfile" -o -z "$tempfile2" ] ; then + echo ; echo "Unable to create tempfiles...aborting." 1>&2 ; echo + exit 1 +fi +trap "rm -f $tempfile; rm -f $tempfile2; exit 2" 1 2 3 5 15 + +# Get executable files +#echo "Locating executables..." +/usr/bin/find $DIR -type f -perm /0111 -print >> $tempfile 2>/dev/null +FOUND=0 +#echo "Refining list to shell scripts..." +while read f +do + # Get just the shell scripts + testf=`echo $f | /usr/bin/file -n -f - | egrep 'ourne|POSIX shell'` + if [ x"$testf" != x ] ; then + echo $f >> $tempfile2 + FOUND=1 + fi +done < $tempfile +/bin/rm -f $tempfile +if [ $FOUND -eq 0 ] ; then + # Nothing to report, just exit +# echo "Examining shell scripts in $DIR" +# echo "No problems found" + /bin/rm -f $tempfile2 + exit 0 +fi +#echo "Examining shell scripts in $DIR" +FOUND=0 +while read i +do + # First see if the script calls an interpreter + SKIP=0 + for lang in $INTERPRETERS + do + if `/bin/cat "$i" 2>/dev/null | \ + grep "exec[ \t].*$lang" >/dev/null` ; then + SKIP=1 + break + fi + done + + if [ $SKIP -eq 1 ] ; then + continue + fi + + # See if this is in a dir we want to ignore + for d in $SKIP_DIRS + do + if `echo "$i" | /bin/grep "^\$d" >/dev/null`; then + SKIP=1 + break + fi + done + + if [ $SKIP -eq 1 ] ; then + continue + fi + + # Don't do the known naughty files + for bad in $KNOWN_BAD + do + if `echo "$i" | /bin/grep "$bad" >/dev/null`; then + SKIP=1 + break + fi + done + + if [ $SKIP -eq 1 ] ; then + continue + fi + + # Now examine them for correctness + interp=`/usr/bin/head -n 1 "$i" | /bin/awk '{ print $1 }' | \ + /usr/bin/tr -d '#!'` + if [ x"$interp" = "x" -o ! -x "$interp" ] ; then + interp="/bin/sh" + fi + $interp -n "$i" 2>/dev/null + if [ $? -ne 0 ] ; then + printf "%-44s" "$i" + rpm -qf --queryformat "%{NAME}-%{VERSION}" $i + echo + FOUND=1 + fi +done < $tempfile2 +/bin/rm -f $tempfile2 +if [ $FOUND -eq 0 ] ; then + # Nothing to report, just exit +# echo "No problems found" + exit 0 +fi +exit 1 + diff --git a/meta-security/recipes-security/redhat-security/files/find-sh4tmp.sh b/meta-security/recipes-security/redhat-security/files/find-sh4tmp.sh new file mode 100644 index 000000000..7fd1af715 --- /dev/null +++ b/meta-security/recipes-security/redhat-security/files/find-sh4tmp.sh @@ -0,0 +1,116 @@ +#!/bin/sh +# find_sh4tmp utility +# Copyright (c) 2005 Steve Grubb. ALL RIGHTS RESERVED. +# sgrubb@redhat.com +# +# This software may be freely redistributed under the terms of the GNU +# public license. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +# This script will search a directory and its subdirectories for all shell +# scripts. It will then search for the use of the tmp directory. If it finds +# this is true, it will then try to determine if mktemp or something +# reasonable was used and exclude it. It has a bug in that it does not handle +# rm -f /tmp/ or mkdir /tmp/ correctly. If you run across files that do that, +# add them to the KNOWN_BAD list to ignore them. + +if [ $# -ge 2 ] ; then + echo "Usage: find_sh4tmp [directory]" 1>&2 + exit 1 +fi +INTERPRETERS="wish wishx tclsh guile rep itkwish expect /etc/kde/kdm/Xsession /etc/X11/xdm/Xsession /usr/bin/festival perl hfssh" +SKIP_DIRS="/opt /home /root /mnt /media /dev /proc /selinux /sys /usr/share/doc" +KNOWN_BAD="kopete_latexconvert.sh cvs2dist fixfiles mysqlbug build/scripts/package/mkspec py-compile rc.sysinit init.d/xfs diff-jars grub-install mailshar vncserver Xsession sysreport cross-build vpkg rcs-to-cvs debug_check_log cvs2vendor tmpwatch ps2epsi mkdumprd xdg-open xdg-mime xdg-email gzexe" +DIR="/" +if [ $# -eq 1 ] ; then + if [ -d "$1" ] ; then + DIR="$1" + else + echo "Option passed in was not a directory" 1>&2 + exit 1 + fi +fi +tempfile=`mktemp /tmp/sh4.XXXXXX` +tempfile2=`mktemp /tmp/sh4.XXXXXX` +if [ -z "$tempfile" -o -z "$tempfile2" ] ; then + echo ; echo "Unable to create tempfiles...aborting." 1>&2 ; echo + exit 1 +fi +trap "rm -f $tempfile; rm -f $tempfile2; exit 2" 1 2 3 5 15 + +# Get executable files +#echo "Scanning shell scripts in $DIR..." +find $DIR -type f -perm /0111 -print >> $tempfile 2>/dev/null +FOUND=0 +while read f +do + # Get just the shell scripts + testf=`echo $f | file -n -f - | egrep 'ourne|POSIX shell'` + if [ x"$testf" != x ] ; then +# FIXME: need to do something to get rid of echo, rm, or mkdir "/tmp/" + test_res=`cat $f 2>/dev/null | grep '\/tmp\/' | grep -v 'mktemp' | grep -v '^#'` + if [ x"$test_res" = x ] ; then + continue + fi + + # Do further examination... + # First see if the script calls an interpreter + SKIP=0 + for lang in $INTERPRETERS + do + if `cat "$f" | grep "exec[ \t].*$lang" >/dev/null` ; then + SKIP=1 + break + fi + done + + if [ $SKIP -eq 1 ] ; then + continue + fi + + # See if this is in a dir we want to ignore + for d in $SKIP_DIRS + do + if `echo "$f" | grep "^\$d" >/dev/null`; then + SKIP=1 + break + fi + done + + if [ $SKIP -eq 1 ] ; then + continue + fi + + # Don't do the known naughty files + for bad in $KNOWN_BAD + do + if `echo "$f" | grep "$bad" >/dev/null`; then + SKIP=1 + break + fi + done + + if [ $SKIP -eq 1 ] ; then + continue + fi + + # Well its a bad one...out with it + printf "%-44s" $f + rpm -qf --queryformat "%{NAME}-%{VERSION}" $f + echo + FOUND=1 + fi +done < $tempfile +rm -f $tempfile +if [ $FOUND -eq 0 ] ; then + # Nothing to report, just exit +# echo "No problems found" + rm -f $tempfile2 + exit 0 +fi +exit 1 + + diff --git a/meta-security/recipes-security/redhat-security/files/lib-bin-check.sh b/meta-security/recipes-security/redhat-security/files/lib-bin-check.sh new file mode 100644 index 000000000..1e2d930b4 --- /dev/null +++ b/meta-security/recipes-security/redhat-security/files/lib-bin-check.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +# This software may be freely redistributed under the terms of the GNU +# public license. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +found=0 +list=`rpm -qa --queryformat "%{NAME}-%{VERSION}.%{ARCH}\n" | grep '^lib' | egrep -v '\-utils\-|\-bin\-|\-tools\-|\-client\-|libreoffice|\-plugin\-'` +for p in $list +do + bin=`rpm -ql $p | egrep '^/bin|^/sbin|^/usr/bin|^/usr/sbin' | grep -v '\-config'` + if [ "x$bin" != "x" ]; then + testf=`echo $bin | /usr/bin/file -n -f - 2>/dev/null | grep ELF` + if [ x"$testf" != "x" ] ; then + found=1 + echo "$p could be split into a utils package" + fi + fi +done + +if [ $found = 0 ]; then + echo "No problems found" + exit 0 +fi + +exit 1 + + diff --git a/meta-security/recipes-security/redhat-security/files/rpm-chksec.sh b/meta-security/recipes-security/redhat-security/files/rpm-chksec.sh new file mode 100644 index 000000000..a0e8bb1a5 --- /dev/null +++ b/meta-security/recipes-security/redhat-security/files/rpm-chksec.sh @@ -0,0 +1,279 @@ +#!/bin/sh +# rpm-chksec +# +# Copyright (c) 2011-2013 Steve Grubb. ALL RIGHTS RESERVED. +# sgrubb@redhat.com +# +# This software may be freely redistributed under the terms of the GNU +# public license. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Given an rpm, it will look at each file to check that its compiled with +# the intended flags to make it more secure. Things that are green are OK. +# Anything in yellow could be better but is passable. Anything in red needs +# attention. +# +# If the --all option is given, it will generate a list of rpms and then +# summarize the rpm's state. For yes, then all files are in the expected +# state. Just one file not compiled with the right flags can turn the +# answer to no. Re-run passing that package (instead of --all) for the details. +# +# To save to file: ./rpm-chksec | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" | tee output.txt + +VERSION="0.5.2" + +usage () { + echo "rpm-chksec [--version|--all|<rpmname>...]" + if [ ! -x /usr/bin/filecap ] ; then + echo "You need to install libcap-ng-utils to test capabilities" + fi + if [ $EUID != 0 ] ; then + echo "You might need to be root to read some files" + fi + exit 0 +} + +if [ "$1" = "--help" -o $# -eq 0 ] ; then + usage +fi +if [ "$1" = "--version" ] ; then + echo "rpm-chksec $VERSION" + exit 0 +fi +if [ "$1" = "--all" ] ; then + MODE="all" +else + MODE="single" +fi + +do_one () { +if ! rpm -q $1 >/dev/null 2>&1 ; then + if [ "$MODE" = "single" ] ; then + echo "$1 is not installed" + exit 1 + else + echo "not installed" + return + fi +fi +files=`rpm -ql $1` + +# Look for daemons, need this for later... +DAEMON="" +for f in $files +do + if [ ! -f "$f" ] ; then + continue + fi + if [ `echo "$f" | grep '\/etc\/rc.d\/init.d'` ] ; then + n=`basename "$f"` + t=`which "$n" 2>/dev/null` + if [ x"$t" != "x" ] ; then + DAEMON="$DAEMON $t" + continue + fi + t=`which "$n"d 2>/dev/null` + if [ x"$t" != "x" ] ; then + DAEMON="$DAEMON $t" + continue + fi + t=`cat "$f" 2>/dev/null | grep 'bin' | grep 'exit 5' | grep -v '\$'` + if [ x"$t" != "x" ] ; then + DAEMON="$DAEMON $t" + continue + fi + if [ "$MODE" = "single" ] ; then + echo "Can't find the executable in $f but daemon rules would apply" + fi + elif [ `echo "$f" | grep '\/lib\/systemd\/'` ] ; then + t=`cat "$f" | grep -i '^ExecStart=' | tr '=' ' ' | awk '{ print $2 }'` + if [ x"$t" != "x" ] ; then + DAEMON="$DAEMON $t" + continue + fi + fi +done + +# Prevent garbled output when doing --all. +skip_current=0 + +for f in $files +do + if [ ! -f "$f" ] ; then + continue + fi + # Some packages have files with ~ in them. This avoids it. + if ! echo "$f" | grep '^/' >/dev/null ; then + continue + fi + if [ ! -r "$f" ] && [ $EUID != 0 ] ; then + if [ $MODE = "single" ] ; then + echo "Please re-test $f as the root user" + else + # Don't print results. + skip_current=1 + echo "Please re-test $1 as the root user" + fi + continue + fi + if ! file "$f" | grep -qw 'ELF'; then + continue + fi + RELRO="no" + if readelf -l "$f" 2>/dev/null | grep -q 'GNU_RELRO'; then + RELRO="partial" + fi + if readelf -d "$f" 2>/dev/null | grep -q 'BIND_NOW'; then + RELRO="full" + fi + PIE="no" + if readelf -h "$f" 2>/dev/null | grep -q 'Type:[[:space:]]*DYN'; then + PIE="DSO" + if readelf -d "$f" 2>/dev/null | grep -q '(DEBUG)'; then + PIE="yes" + fi + fi + APP="" + if [ x"$DAEMON" != "x" ] ; then + for d in $DAEMON + do + if [ "$f" = "$d" ] ; then + APP="daemon" + break + fi + done + fi + if [ x"$APP" = "x" ] ; then + # See if this is a library or a setuid app + if [ `echo "$f" | grep '\/lib' | grep '\.so'` ] ; then + APP="library" + elif [ `find "$f" -perm -004000 -type f -print` ] ; then + APP="setuid" + elif [ `find "$f" -perm -002000 -type f -print` ] ; then + APP="setgid" + elif [ -x /usr/bin/filecap ] && [ `filecap "$f" 2> /dev/null | wc -w` -gt 0 ] ; then + APP="setcap" + else + syms1=`/usr/bin/readelf -s "$f" 2>/dev/null | egrep ' connect@.*GLIBC| listen@.*GLIBC| accept@.*GLIBC|accept4@.*GLIBC'` + syms2=`/usr/bin/readelf -s "$f" 2>/dev/null | egrep ' getaddrinfo@.*GLIBC| getnameinfo@.*GLIBC| getservent@.*GLIBC| getservbyname@.*GLIBC| getservbyport@.*GLIBC|gethostbyname@.*GLIBC| gethostbyname2@.*GLIBC| gethostbyaddr@.*GLIBC| gethostbyaddr2@.*GLIBC'` + if [ x"$syms1" != "x" ] ; then + if [ x"$syms2" != "x" ] ; then + APP="network-ip" + else + APP="network-local" + fi + fi + fi + fi + if [ x"$APP" = "x" ] ; then + APP="exec" + fi + + # OK, ready for the output + if [ "$MODE" = "single" ] ; then + printf "%-56s %-10s " "$f" $APP + if [ "$APP" = "daemon" -o "$APP" = "setuid" -o "$APP" = "setgid" -o "$APP" = "setcap" -o "$APP" = "network-ip" -o "$APP" = "network-local" ] ; then + if [ "$RELRO" = "full" ] ; then + printf "\033[32m%-7s\033[m " $RELRO + elif [ "$RELRO" = "partial" ] ; then + printf "\033[33m%-7s\033[m " $RELRO + else + printf "\033[31m%-7s\033[m " $RELRO + fi + if [ "$PIE" = "yes" ] ; then + printf "\033[32m%-4s\033[m" $PIE + else + printf "\033[31m%-4s\033[m" $PIE + fi + elif [ "$APP" = "library" ] ; then + if [ "$RELRO" = "full" -o "$RELRO" = "partial" ] ; then + printf "\033[32m%-7s\033[m " $RELRO + else + printf "\033[31m%-7s\033[m " $RELRO + fi + printf "\033[32m%-4s\033[m" $PIE + else + # $APP = exec - we want partial relro + if [ "$RELRO" = "no" ] ; then + printf "\033[31m%-7s\033[m " $RELRO + else + printf "\033[32m%-7s\033[m " $RELRO + fi + printf "\033[32m%-4s\033[m" $PIE + fi + echo + else + if [ "$APP" = "daemon" -o "$APP" = "setuid" -o "$APP" = "setgid" -o "$APP" = "setcap" -o "$APP" = "network-ip" -o "$APP" = "network-local" ] ; then + if [ "$RELRO" = "no" ] ; then + RELRO_SUM="no" + APP_SUM="$APP" + fi + if [ "$PIE" = "no" ] ; then + PIE_SUM="no" + APP_SUM="$APP" + fi + elif [ "$APP" = "library" ] ; then + if [ "$RELRO" = "no" ] ; then + RELRO_SUM="no" + APP_SUM="$APP" + fi + # $APP = exec - must have partial or full relro + elif [ "$RELRO" = "no" ] ; then + RELRO_SUM="no" + APP_SUM="$APP" + fi + fi +done +} + +if [ "$MODE" = "single" ] ; then + printf "%-56s %-10s %-7s %-4s" "FILE" "TYPE" "RELRO" "PIE" + echo + for i; do + f=$(basename $1) + # Strip the .rpm extension, if present. + do_one ${f%%.rpm} + shift + done + exit 0 +fi + +# Skip the kernel as its special +packages=`rpm -qa | egrep -v 'kernel.|debuginfo.|.noarch|gpg-pubkey' | sort` +printf "%-50s %-5s %-4s %-14s" "PACKAGE" "RELRO" "PIE" "CLASS" +echo +for p in $packages +do + RELRO_SUM="yes" + PIE_SUM="yes" + APP_SUM="" + printf "%-50s " $p + do_one $p + if [[ $skip_current -eq 1 ]] ; then + continue + fi + if [ "$RELRO_SUM" = "yes" ] ; then + printf "\033[32m%-5s\033[m " "$RELRO_SUM" + else + printf "\033[31m%-5s\033[m " "$RELRO_SUM" + fi + if [ "$PIE_SUM" = "yes" ] ; then + printf "\033[32m%-4s\033[m" "$PIE_SUM" + if [ "$RELRO_SUM" = "no" ] ; then + printf " %-14s" "$APP_SUM" + fi + else + if [ "$APP_SUM" = "network-local" ] ; then + printf "\033[33m%-4s\033[m %-14s" "$PIE_SUM" "$APP_SUM" + else + printf "\033[31m%-4s\033[m %-14s" "$PIE_SUM" "$APP_SUM" + fi + fi + echo +done +exit 0 + + diff --git a/meta-security/recipes-security/redhat-security/files/rpm-drop-groups.sh b/meta-security/recipes-security/redhat-security/files/rpm-drop-groups.sh new file mode 100644 index 000000000..8c757834b --- /dev/null +++ b/meta-security/recipes-security/redhat-security/files/rpm-drop-groups.sh @@ -0,0 +1,131 @@ +#!/bin/sh +# rpm-drop-groups +# +# Copyright (c) 2011 Steve Grubb. ALL RIGHTS RESERVED. +# sgrubb@redhat.com +# +# This software may be freely redistributed under the terms of the GNU +# public license. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Given an rpm, it will look at each file to check if it tries to change +# group and user credentials. If so, it further tries to determine if +# it also calls setgroups or initgroups. To correctly change groups, the +# program must drop supplemntal groups. Programs are classified into: n/a +# meaning no group dropping occurs, yes its done correctly, and no meaning +# there seems to be a problem. +# +# If the --all option is given, it will generate a list of rpms and then +# summarize the rpm's state. For yes, then all files are in the expected +# state. Just one program failing can turn the package's summary to no. +# Re-run passing that package (instead of --all) for the details. +# +# To save to file: ./rpm-drop-groups | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" | tee output.txt + +VERSION="0.1" + +usage () { + echo "rpm-drop-groups [--all|<rpmname>|--version]" + exit 0 +} + +if [ "$1" = "--help" -o $# -eq 0 ] ; then + usage +fi +if [ "$1" = "--version" ] ; then + echo "rpm-drop-groups $VERSION" + exit 0 +fi +if [ "$1" = "--all" ] ; then + MODE="all" +else + MODE="single" +fi + +do_one () { +if ! rpm -q $1 >/dev/null 2>&1 ; then + if [ "$MODE" = "single" ] ; then + echo "$1 is not installed" + exit 1 + else + echo "not installed" + return + fi +fi +files=`rpm -ql $1` + +for f in $files +do + if [ ! -f $f ] ; then + continue + fi + if ! file $f | grep -q 'ELF'; then + continue + fi + + CORRECT="n/a" + syms=`/usr/bin/readelf -s $f 2>/dev/null | egrep ' setgid@.*GLIBC| setegid@.*GLIBC| setresgid@.*GLIBC'` + if [ x"$syms" != "x" ] ; then + CORRECT="yes" + syms=`/usr/bin/readelf -s $f 2>/dev/null | egrep ' setuid@.*GLIBC| seteuid@.*GLIBC| setresuid@.*GLIBC'` + if [ x"$syms" != "x" ] ; then + syms=`/usr/bin/readelf -s $f 2>/dev/null | egrep ' setgroups@.*GLIBC| initgroups@.*GLIBC'` + if [ x"$syms" = "x" ] ; then + syms=`find $f \( -perm -004000 -o -perm -002000 \) -type f -print` + if [ x"$syms" = "x" ] ; then + CORRECT="no" + fi + fi + fi + fi + + # OK, ready for the output + if [ "$MODE" = "single" ] ; then + printf "%-60s " $f + if [ "$CORRECT" = "yes" ] ; then + printf "\033[32m%-7s\033[m " $CORRECT + elif [ "$CORRECT" = "no" ] ; then + printf "\033[31m%-7s\033[m " $CORRECT + else + printf "\033[33m%-7s\033[m " $CORRECT + fi + echo + else + if [ "$CORRECT" = "no" ] ; then + CORRECT_SUM="no" + fi + fi +done +} + +if [ "$MODE" = "single" ] ; then + printf "%-60s%-7s" "FILE" "CORRECT" + echo + for i; do + do_one $1 + shift + done + exit 0 +fi + +packages=`rpm -qa --queryformat "%{NAME}.%{ARCH}\n" | sort` +printf "%-50s %-7s" "PACKAGE" "CORRECT" +echo +for p in $packages +do + CORRECT_SUM="yes" + printf "%-50s " $p + do_one $p + if [ "$CORRECT_SUM" = "yes" ] ; then + printf "\033[32m%-7s\033[m " $CORRECT_SUM + else + printf "\033[31m%-7s\033[m " $CORRECT_SUM + fi + echo +done +exit 0 + + diff --git a/meta-security/recipes-security/redhat-security/files/selinux-check-devices.sh b/meta-security/recipes-security/redhat-security/files/selinux-check-devices.sh new file mode 100644 index 000000000..ef996d787 --- /dev/null +++ b/meta-security/recipes-security/redhat-security/files/selinux-check-devices.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# This software may be freely redistributed under the terms of the GNU +# public license. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +find /dev -context *:device_t:* \( -type c -o -type b \) -printf "%p %Z\n" + + diff --git a/meta-security/recipes-security/redhat-security/files/selinux-ls-unconfined.sh b/meta-security/recipes-security/redhat-security/files/selinux-ls-unconfined.sh new file mode 100644 index 000000000..68684133c --- /dev/null +++ b/meta-security/recipes-security/redhat-security/files/selinux-ls-unconfined.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +# This software may be freely redistributed under the terms of the GNU +# public license. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +# This checks for unconfined apps running, initrc and inetd are signs +# of missing transitions. + +pidof xinetd >/dev/null +if [ $? -eq 0 ] ; then +ps -eZ | egrep "initrc|inetd" | egrep -v `pidof xinetd` | tr ':' ' ' | awk '{ printf "%s %s\n", $3, $NF }' +else +ps -eZ | egrep "initrc" | tr ':' ' ' | awk '{ printf "%s %s\n", $3, $NF }' +fi + diff --git a/meta-security/recipes-security/redhat-security/redhat-security_1.0.bb b/meta-security/recipes-security/redhat-security/redhat-security_1.0.bb new file mode 100644 index 000000000..56f734cb3 --- /dev/null +++ b/meta-security/recipes-security/redhat-security/redhat-security_1.0.bb @@ -0,0 +1,40 @@ +SUMMARY = "redhat security tools" +DESCRIPTION = "Tools used by redhat linux distribution for security checks" +SECTION = "security" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6" + +SRC_URI = "file://find-chroot-py.sh \ + file://find-chroot.sh \ + file://find-elf4tmp.sh \ + file://find-execstack.sh \ + file://find-hidden-exec.sh \ + file://find-nodrop-groups.sh \ + file://find-sh4errors.sh \ + file://find-sh4tmp.sh \ + file://lib-bin-check.sh \ + file://rpm-chksec.sh \ + file://rpm-drop-groups.sh \ + file://selinux-check-devices.sh \ + file://selinux-ls-unconfined.sh" + +S = "${WORKDIR}" + +do_install() { + install -d ${D}${bindir} + install -m 0755 ${WORKDIR}/find-chroot-py.sh ${D}${bindir} + install -m 0755 ${WORKDIR}/find-chroot.sh ${D}${bindir} + install -m 0755 ${WORKDIR}/find-elf4tmp.sh ${D}${bindir} + install -m 0755 ${WORKDIR}/find-execstack.sh ${D}${bindir} + install -m 0755 ${WORKDIR}/find-hidden-exec.sh ${D}${bindir} + install -m 0755 ${WORKDIR}/find-nodrop-groups.sh ${D}${bindir} + install -m 0755 ${WORKDIR}/find-sh4errors.sh ${D}${bindir} + install -m 0755 ${WORKDIR}/find-sh4tmp.sh ${D}${bindir} + install -m 0755 ${WORKDIR}/lib-bin-check.sh ${D}${bindir} + install -m 0755 ${WORKDIR}/rpm-chksec.sh ${D}${bindir} + install -m 0755 ${WORKDIR}/rpm-drop-groups.sh ${D}${bindir} + install -m 0755 ${WORKDIR}/selinux-check-devices.sh ${D}${bindir} + install -m 0755 ${WORKDIR}/selinux-ls-unconfined.sh ${D}${bindir} +} + +RDEPENDS_${PN} = "file libcap-ng procps findutils" diff --git a/meta-security/recipes-security/samhain/files/run-ptest b/meta-security/recipes-security/samhain/files/run-ptest new file mode 100755 index 000000000..2a4a76530 --- /dev/null +++ b/meta-security/recipes-security/samhain/files/run-ptest @@ -0,0 +1,3 @@ +#!/bin/sh +current_dir=$(dirname $(readlink -f $0)) +$current_dir/cutest diff --git a/meta-security/recipes-security/samhain/files/samhain-add-LDFLAGS-variable-for-samhain_setpwd.patch b/meta-security/recipes-security/samhain/files/samhain-add-LDFLAGS-variable-for-samhain_setpwd.patch new file mode 100644 index 000000000..088a938e3 --- /dev/null +++ b/meta-security/recipes-security/samhain/files/samhain-add-LDFLAGS-variable-for-samhain_setpwd.patch @@ -0,0 +1,28 @@ +From ae79606a6745dbbd429d1d4671dfe3045d735057 Mon Sep 17 00:00:00 2001 +From: Jackie Huang <jackie.huang@windriver.com> +Date: Thu, 14 Sep 2017 13:26:55 +0800 +Subject: [PATCH] Add LDFLAGS variable for compiling samhain_setpwd + +Upstream-Status: Pending + +Signed-off-by: Jackie Huang <jackie.huang@windriver.com> +--- + Makefile.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile.in b/Makefile.in +index 01de987..49356cf 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -1128,7 +1128,7 @@ sh_tiger_i.o: $(srcsrc)/$(TIGER_SRC) Makefile config_xor.h + samhain_setpwd: encode config_xor.h $(srcsrc)/samhain_setpwd.c + @echo '$(COMPILE) -o samhain_setpwd $(srcsrc)/samhain_setpwd.c'; \ + ./encode $(XOR_CODE) $(srcsrc)/samhain_setpwd.c; \ +- $(COMPILE) -o samhain_setpwd x_samhain_setpwd.c; \ ++ $(COMPILE) $(LDFLAGS) -o samhain_setpwd x_samhain_setpwd.c; \ + rm x_samhain_setpwd.c + + samhain_stealth: encode config_xor.h $(srcsrc)/samhain_stealth.c +-- +2.11.0 + diff --git a/meta-security/recipes-security/samhain/files/samhain-avoid-searching-host-for-postgresql.patch b/meta-security/recipes-security/samhain/files/samhain-avoid-searching-host-for-postgresql.patch new file mode 100644 index 000000000..6bf67e09b --- /dev/null +++ b/meta-security/recipes-security/samhain/files/samhain-avoid-searching-host-for-postgresql.patch @@ -0,0 +1,134 @@ +From 3e2ca7e06b16ceff6d12beb5113312f6525df595 Mon Sep 17 00:00:00 2001 +From: Jackie Huang <jackie.huang@windriver.com> +Date: Thu, 14 Sep 2017 11:02:12 +0800 +Subject: [PATCH] configure.ac: avoid searching host for postgresql + +Upstream-Status: Inappropriate [cross compile specific] + +Signed-off-by: Jackie Huang <jackie.huang@windriver.com> +--- + configure.ac | 101 +++-------------------------------------------------------- + 1 file changed, 5 insertions(+), 96 deletions(-) + +diff --git a/configure.ac b/configure.ac +index a224c68..f658d53 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1278,90 +1278,11 @@ AC_ARG_WITH(database, + AC_DEFINE(WITH_POSTGRES) + AC_DEFINE(WITH_DATABASE) + # +- PGCONF="no" +- MY_PATH="${PATH}:/usr/local/bin:/usr/local/pgsql/bin" +- OLD_IFS="$IFS" +- IFS=":" +- for ff in ${MY_PATH} +- do +- if test -f "$ff/pg_config" +- then +- PGCONF="$ff/pg_config" +- fi +- done +- IFS="${OLD_IFS}" +- # +- # +- if test "x${PGCONF}" = "xno" +- then +- AC_MSG_CHECKING(for PostgreSQL in /usr/local/pgsql /usr/pgsql /usr/local /usr PGSQL_HOME) +- pgsql_directory="/usr/local/pgsql /usr/pgsql /usr/local /usr ${PGSQL_HOME}" +- for i in $pgsql_directory; do +- if test -r $i/include/pgsql/libpq-fe.h; then +- PGSQL_INC_DIR=$i/include +- PGSQL_DIR=$i +- # use AC_CHECK_HEADERS to check for pgsql/libpq-fe.h +- fi +- done +- if test -z "$PGSQL_DIR"; then +- for i in $pgsql_directory; do +- if test -r $i/include/postgresql/libpq-fe.h; then +- PGSQL_INC_DIR=$i/include +- PGSQL_DIR=$i +- fi +- done +- fi +- if test -z "$PGSQL_DIR"; then +- for i in $pgsql_directory; do +- if test -r $i/include/libpq-fe.h; then +- PGSQL_INC_DIR=$i/include +- PGSQL_DIR=$i +- fi +- done +- fi +- +- if test -z "$PGSQL_DIR"; then +- tmp="" +- for i in $pgsql_directory; do +- tmp="$tmp $i/include $i/include/pgsql $i/include/postgresql" +- done +- FAIL_MESSAGE("PostgreSQL header file (libpq-fe.h)", $tmp) +- fi +- +- for i in lib lib/pgsql lib/postgresql; do +- str="$PGSQL_DIR/$i/libpq.*" +- for j in `echo $str`; do +- if test -r $j; then +- PGSQL_LIB_DIR="$PGSQL_DIR/$i" +- break 2 +- fi +- done +- done +- +- if test -z "$PGSQL_LIB_DIR"; then +- for ff in $pgsql_directory; do +- for i in lib lib/pgsql lib/postgresql; do +- str="$ff/$i/libpq.*" +- for j in `echo $str`; do +- if test -r $j; then +- PGSQL_LIB_DIR="$ff/$i" +- break 3 +- fi +- done +- done +- done +- fi +- +- if test -z "$PGSQL_LIB_DIR"; then +- tmp="" +- for i in $pgsql_directory; do +- tmp="$i/lib $i/lib/pgsql $i/lib/postgresql" +- done +- FAIL_MESSAGE("postgresql library libpq", $tmp) +- fi +- +- AC_MSG_RESULT(yes) +- ++ if test -z "${PGSQL_LIB_DIR}" ; then ++ FAIL_MESSAGE("PGSQL_LIB_DIR is not set!") ++ elif test -z "${PGSQL_INC_DIR}" ; then ++ FAIL_MESSAGE("PGSQL_INC_DIR is not set!") ++ else + LIBS="$LIBS -L${PGSQL_LIB_DIR} -lpq -lm" + if test x"$enable_static" = xyes; then + LIBS="$LIBS -L${PGSQL_LIB_DIR} -lpq -lcrypt -lm" +@@ -1370,18 +1291,6 @@ AC_ARG_WITH(database, + fi + # CFLAGS="$CFLAGS -I${PGSQL_INC_DIR}" + CPPFLAGS="$CPPFLAGS -I${PGSQL_INC_DIR}" +- AC_CHECK_HEADERS(pgsql/libpq-fe.h) +- AC_CHECK_HEADERS(postgresql/libpq-fe.h) +- else +- pg_lib_dir=`${PGCONF} --libdir` +- if test x"$enable_static" = xyes; then +- LIBS="$LIBS -L${pg_lib_dir} -lpq -lcrypt -lm" +- else +- LIBS="$LIBS -L${pg_lib_dir} -lpq -lm" +- fi +- pg_inc_dir=`${PGCONF} --includedir` +- # CFLAGS="$CFLAGS -I${pg_inc_dir}" +- CPPFLAGS="$CPPFLAGS -I${pg_inc_dir}" + fi + elif test "x${withval}" = "xodbc"; then + AC_MSG_CHECKING(for odbc in /usr /usr/local ODBC_HOME) +-- +2.11.0 + diff --git a/meta-security/recipes-security/samhain/files/samhain-client.default b/meta-security/recipes-security/samhain/files/samhain-client.default new file mode 100644 index 000000000..9899577ae --- /dev/null +++ b/meta-security/recipes-security/samhain/files/samhain-client.default @@ -0,0 +1,3 @@ +# Set this to "yes" to start the server, after you configure it, of +# course. +SAMHAIN_CLIENT_START="no"
\ No newline at end of file diff --git a/meta-security/recipes-security/samhain/files/samhain-client.init b/meta-security/recipes-security/samhain/files/samhain-client.init new file mode 100644 index 000000000..d5fabeded --- /dev/null +++ b/meta-security/recipes-security/samhain/files/samhain-client.init @@ -0,0 +1,122 @@ +#!/bin/bash +# chkconfig: 2345 99 10 +# description: File Integrity Checking Daemon +# +# processname: samhain +# config : /etc/samhainrc +# logfile : /var/log/samhain_log +# database: /var/lib/samhain/samhain_file +# + +NAME=samhain +DAEMON=/usr/sbin/samhain +RETVAL=0 +PIDFILE=/var/run/samhain.pid + +. /etc/default/rcS + +. /etc/default/samhain-client + +if [ "x$SAMHAIN_CLIENT_START" != "xyes" ]; then + echo "${0}: client disabled in /etc/default/samhain-client" + exit 0 +fi + +if [ -x $DAEMON ]; then + : +else + echo "${0}: executable ${DAEMON} not found" + exit 1 +fi + +if [ ! -e /var/lib/samhain/samhain_file ]; then + echo "${0}: /var/lib/samhain/samhain_file does not exist. You must" + echo " run 'samhain -t init' before samhian-client can start." + exit 1 +fi + +samhain_done() +{ + if [ $RETVAL -eq 0 ]; then + echo "." + else + echo " failed." + fi +} + +log_stat_msg () { +case "$1" in + 0) + echo "Service $NAME: Running"; + ;; + 1) + echo "Service $NAME: Stopped and /var/run pid file exists"; + ;; + 3) + echo "Service $NAME: Stopped"; + ;; + *) + echo "Service $NAME: Status unknown"; + ;; +esac +} + +case "$1" in + start) + # + # Remove a stale PID file, if found + # + if test -f ${PIDFILE}; then + /bin/rm -f ${PIDFILE} + fi + # + echo -n "Starting ${NAME}" + start-stop-daemon --start --quiet --exec $DAEMON + RETVAL=$? + samhain_done + ;; + + stop) + echo -n "Stopping $NAME" + start-stop-daemon --stop --quiet --exec $DAEMON + RETVAL=$? + + # + # Remove a stale PID file, if found + # + if test -f ${PIDFILE}; then + /bin/rm -f ${PIDFILE} + fi + if test -S /var/run/${NAME}.sock; then + /bin/rm -f /var/run/${NAME}.sock + fi + samhain_done + ;; + + restart) + $0 stop + sleep 3 + $0 start + RETVAL=$? + ;; + + reload|force-reload) + echo -n "Reloading $NAME configuration files" + start-stop-daemon --stop --signal 1 --quiet --exec $DAEMON + RETVAL=$? + samhain_done + ;; + + status) + $DAEMON status + RETVAL=$? + log_stat_msg ${RETVAL} + ;; + + *) + echo "$0 usage: {start|stop|status|restart|reload}" + exit 1 + ;; +esac + +exit $RETVAL diff --git a/meta-security/recipes-security/samhain/files/samhain-configure-add-option-for-ps.patch b/meta-security/recipes-security/samhain/files/samhain-configure-add-option-for-ps.patch new file mode 100644 index 000000000..8de0735fc --- /dev/null +++ b/meta-security/recipes-security/samhain/files/samhain-configure-add-option-for-ps.patch @@ -0,0 +1,108 @@ +From 02a143f0068cbc6cea71359169210fbb3606d4bb Mon Sep 17 00:00:00 2001 +From: Jackie Huang <jackie.huang@windriver.com> +Date: Mon, 18 Jan 2016 00:24:57 -0500 +Subject: [PATCH] configure: add option for ps + +The configure searches hardcoded host paths for PSPATH +and run ps commands to decide PSARG which will fail +on host without ps: +| configure: error: Cannot find ps in any of /usr/ucb /bin /usr/bin + +So add an option so we can specify the ps at configure +to avoid host contamination. + +Upstream-Status: Inappropriate [cross compile specific] + +Signed-off-by: Jackie Huang <jackie.huang@windriver.com> +--- + aclocal.m4 | 2 +- + configure.ac | 60 ++++++++++-------------------------------------------------- + 2 files changed, 11 insertions(+), 51 deletions(-) + +diff --git a/aclocal.m4 b/aclocal.m4 +index a2e59a6..cd20a2f 100644 +--- a/aclocal.m4 ++++ b/aclocal.m4 +@@ -409,7 +409,7 @@ x_includes=NONE + x_libraries=NONE + DESTDIR= + SH_ENABLE_OPTS="selinux posix-acl asm ssp db-reload xml-log message-queue login-watch process-check port-check mounts-check logfile-monitor userfiles debug ptrace static network udp nocl stealth micro-stealth install-name identity khide suidcheck base largefile mail external-scripts encrypt srp dnmalloc ipv6 shellexpand suid" +-SH_WITH_OPTS="prelude libprelude-prefix database libwrap cflags libs console altconsole timeserver alttimeserver rnd egd-socket port logserver altlogserver kcheck gpg keyid checksum fp recipient sender trusted tmp-dir config-file log-file pid-file state-dir data-file html-file" ++SH_WITH_OPTS="prelude libprelude-prefix database libwrap cflags libs console altconsole timeserver alttimeserver rnd egd-socket port logserver altlogserver kcheck gpg keyid checksum fp recipient sender trusted tmp-dir config-file log-file pid-file state-dir data-file html-file ps-path" + + # Installation directory options. + # These are left unexpanded so users can "make install exec_prefix=/foo" +diff --git a/configure.ac b/configure.ac +index 5910b1f..8c3e087 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -730,56 +730,16 @@ then + fi + AC_CHECK_HEADERS(gmp.h) + +-AC_MSG_CHECKING([for ps]) +-PS= +-for ff in /usr/ucb /bin /usr/bin; do +- if test -x "$ff/ps"; then +- PS="$ff/ps" +- AC_MSG_RESULT([$PS]) +- break +- fi +-done +-if test x$PS = x +-then +- AC_MSG_RESULT([no]) +- AC_MSG_ERROR([Cannot find ps in any of /usr/ucb /bin /usr/bin]) +-fi +-AC_DEFINE_UNQUOTED([PSPATH], _("$PS"), [Path to ps]) +- +-AC_MSG_CHECKING([how to use ps]) +-$PS ax >/dev/null 2>&1 +-if test $? -eq 0; then +- case "$host_os" in +- *openbsd*) +- one=`$PS akx | wc -l` +- ;; +- *) +- one=`$PS ax | wc -l` +- ;; +- esac +-else +- one=0 +-fi +-$PS -e >/dev/null 2>&1 +-if test $? -eq 0; then +- two=`$PS -e | wc -l` +-else +- two=0 +-fi +-if test $one -ge $two +-then +- case "$host_os" in +- *openbsd*) +- PSARG="akx" +- ;; +- *) +- PSARG="ax" +- ;; +- esac +-else +- PSARG="-e" +-fi +-AC_DEFINE_UNQUOTED([PSARG], _("$PSARG"), [Argument for ps]) ++AC_ARG_WITH(ps-path, ++ [ --with-ps-path=PATH set path to ps command ], ++ [ ++ if test "x${withval}" != xno; then ++ pspath="${withval}" ++ AC_DEFINE_UNQUOTED([PSPATH], _("${pspath}"), [Path to ps]) ++ AC_DEFINE_UNQUOTED([PSARG], _("ax"), [Argument for ps]) ++ fi ++ ]) ++ + AC_MSG_RESULT([$PS $PSARG]) + + dnl ***************************************** +-- +1.9.1 + diff --git a/meta-security/recipes-security/samhain/files/samhain-cross-compile.patch b/meta-security/recipes-security/samhain/files/samhain-cross-compile.patch new file mode 100644 index 000000000..7f80a5c61 --- /dev/null +++ b/meta-security/recipes-security/samhain/files/samhain-cross-compile.patch @@ -0,0 +1,51 @@ +From f63908427b2adb1792c59edbe38618e14ef5bc7b Mon Sep 17 00:00:00 2001 +From: Jackie Huang <jackie.huang@windriver.com> +Date: Fri, 15 Jan 2016 00:48:58 -0500 +Subject: [PATCH] Enable obfuscating binaries natively. + +Enable obfuscating binaries natively. + +The samhain build process involves an obfuscation step that attempts to +defeat decompilation or other binary analysis techniques which might reveal +secret information that should be known only to the system administrator. +The obfuscation step builds several applications which run on the build host +and then generate target code, which is then built into target binaries. + +This patch creates a basic infrastructure that supports building the +obfuscation binaries natively then cross-compiling the target code by adding +a special configure option. In the absence of this option the old behaviour +is preserved. + +Upstream-Status: Inappropriate [cross compile specific] + +Signed-off-by: Aws Ismail <aws.ismail@windriver.com> +Signed-off-by: Jackie Huang <jackie.huang@windriver.com> +--- + Makefile.in | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/Makefile.in b/Makefile.in +index 684e92b..fb090e2 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -54,7 +54,7 @@ selectconfig = @selectconfig@ + top_builddir = . + + INSTALL = @INSTALL@ +-INSTALL_PROGRAM = @INSTALL@ -s -m 700 ++INSTALL_PROGRAM = @INSTALL@ -m 700 + INSTALL_SHELL = @INSTALL@ -m 700 + INSTALL_DATA = @INSTALL@ -m 600 + INSTALL_MAN = @INSTALL@ -m 644 +@@ -525,8 +525,6 @@ install-program: $(PROGRAMS) sstrip + echo " $(INSTALL_PROGRAM) $$p $$target"; \ + $(INSTALL_PROGRAM) $$p $$target; \ + chmod 0700 $$target; \ +- echo " ./sstrip $$target"; \ +- ./sstrip $$target; \ + else \ + echo " $(INSTALL_SHELL) $$p $$target"; \ + $(INSTALL_SHELL) $$p $$target; \ +-- +1.9.1 + diff --git a/meta-security/recipes-security/samhain/files/samhain-mips64-aarch64-dnmalloc-hash-fix.patch b/meta-security/recipes-security/samhain/files/samhain-mips64-aarch64-dnmalloc-hash-fix.patch new file mode 100644 index 000000000..060866068 --- /dev/null +++ b/meta-security/recipes-security/samhain/files/samhain-mips64-aarch64-dnmalloc-hash-fix.patch @@ -0,0 +1,44 @@ +commit 0f6bdc219e598de08a3f37887efa5dfa50e2b996 +Author: Aws Ismail <aws.ismail@windriver.com> +Date: Fri Jun 22 15:47:08 2012 -0400 + +Hash fix for MIPS64 and AARCH64 + +Samhain uses the addresses of local variables in generating hash +values. The hashing function is designed only for 32-bit values. +For MIPS64 when a 64-bit address is passed in the resulting hash +exceeds the limits of the underlying mechanism and samhain +ultimately fails. The solution is to simply take the lower +32-bits of the address and use that in generating hash values. + +Signed-off-by: Greg Moffatt <greg.moffatt@windriver.com> + +Upstream-Status: Pending + +Signed-off-by: Aws Ismail <aws.ismail@windriver.com> +Signed-off-by: Jackie Huang <jackie.huang@windriver.com> + +diff --git a/src/dnmalloc.c b/src/dnmalloc.c +index da9a5c5..fc91400 100644 +--- a/src/dnmalloc.c ++++ b/src/dnmalloc.c +@@ -2703,11 +2703,19 @@ static void freecilst_add(chunkinfoptr p) { + } + + /* Calculate the hash table entry for a chunk */ ++#if defined(CONFIG_ARCH_MIPS64) || defined(CONFIG_ARCH_AARCH64) ++#ifdef STARTHEAP_IS_ZERO ++#define hash(p) ((((unsigned long) p) & 0x7fffffff) >> 7) ++#else ++#define hash(p) ((((unsigned long) p - (unsigned long) startheap) & 0x7fffffff) >> 7) ++#endif ++#else + #ifdef STARTHEAP_IS_ZERO + #define hash(p) (((unsigned long) p) >> 7) + #else + #define hash(p) (((unsigned long) p - (unsigned long) startheap) >> 7) + #endif ++#endif /* CONFIG_ARCH_MIPS64 */ + + static void + hashtable_add (chunkinfoptr ci) diff --git a/meta-security/recipes-security/samhain/files/samhain-not-run-ptest-on-host.patch b/meta-security/recipes-security/samhain/files/samhain-not-run-ptest-on-host.patch new file mode 100644 index 000000000..528431311 --- /dev/null +++ b/meta-security/recipes-security/samhain/files/samhain-not-run-ptest-on-host.patch @@ -0,0 +1,24 @@ +not run test on host, since we are doing cross-compile + +Upstream-status: Inappropriate [cross compile specific] + +Signed-off-by: Roy Li <rongqing.li@windriver.com> +--- + Makefile.in | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/Makefile.in b/Makefile.in +index e1b32a8..74bfdc9 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -1234,7 +1234,6 @@ intcutest: internal.h $(OBJECTS) $(CUTEST_OBJECTS) sh_tiger_i.o $(srcsrc)/CuTest + rm x_samhain.c; \ + $(LINK) sh_tiger_i.o $(CUTEST_OBJECTS) CuTestMain.o CuTest.o $(OBJECTS) $(LIBS_TRY); \ + test -f ./intcutest && mv ./intcutest ./cutest; \ +- ./cutest + + runcutest: + gdb ./cutest +-- +1.7.10.4 + diff --git a/meta-security/recipes-security/samhain/files/samhain-pid-path.patch b/meta-security/recipes-security/samhain/files/samhain-pid-path.patch new file mode 100644 index 000000000..592bd165f --- /dev/null +++ b/meta-security/recipes-security/samhain/files/samhain-pid-path.patch @@ -0,0 +1,27 @@ +commit a932b03b65edeb02ccad2fce06bfa68a8f2fbb04 +Author: Aws Ismail <aws.ismail@windriver.com> +Date: Thu Jan 10 16:29:05 2013 -0500 + + Set the PID Lock path for samhain.pid + + The explicit path for samhain.pid inorder + for samhain to work properly after it initial + database build. + + Upstream-Status: Inappropriate [configuration] + + Signed-off-by: Aws Ismail <aws.ismail@windriver.com> + +diff --git a/samhainrc.linux b/samhainrc.linux +index 10a8176..a7b06e6 100644 +--- a/samhainrc.linux ++++ b/samhainrc.linux +@@ -639,7 +639,7 @@ SetFileCheckTime = 86400 + + ## Path to the PID file + # +-# SetLockfilePath = (default: compiled-in) ++SetLockfilePath = /run/samhain.pid + + + ## The digest/checksum/hash algorithm diff --git a/meta-security/recipes-security/samhain/files/samhain-samhainrc-fix-files-dirs-path.patch b/meta-security/recipes-security/samhain/files/samhain-samhainrc-fix-files-dirs-path.patch new file mode 100644 index 000000000..dad6b150e --- /dev/null +++ b/meta-security/recipes-security/samhain/files/samhain-samhainrc-fix-files-dirs-path.patch @@ -0,0 +1,61 @@ +From 00fb527e45da42550156197647e01de9a6b1ad52 Mon Sep 17 00:00:00 2001 +From: Wenzong Fan <wenzong.fan@windriver.com> +Date: Mon, 3 Mar 2014 01:50:01 -0500 +Subject: [PATCH] fix real path for some files/dirs + +Upstream-Status: Inappropriate [configuration] + +Signed-off-by: Wenzong Fan <wenzong.fan@windriver.com> +--- + samhainrc.linux | 15 +++++++-------- + 1 file changed, 7 insertions(+), 8 deletions(-) + +diff --git a/samhainrc.linux b/samhainrc.linux +index e9727b4..7775d83 100644 +--- a/samhainrc.linux ++++ b/samhainrc.linux +@@ -93,7 +93,6 @@ dir = 99/etc + ## + file = /etc/mtab + file = /etc/fstab +-file = /etc/adjtime + file = /etc/motd + file = /etc/lvm/lvm.conf + +@@ -153,11 +152,11 @@ dir = 99/var + + [IgnoreAll] + dir = -1/var/cache +-dir = -1/var/lock +-dir = -1/var/mail +-dir = -1/var/run ++dir = -1/run/lock ++dir = -1/var/spool/mail ++dir = -1/run + dir = -1/var/spool +-dir = -1/var/tmp ++dir = -1/var/volatile/tmp + + + [Attributes] +@@ -167,7 +166,7 @@ dir = -1/var/tmp + file = /var/lib/rpm/__db.00? + + file = /var/lib/logrotate.status +-file = /var/lib/random-seed ++file = /var/lib/urandom/random-seed + + + [GrowingLogFiles] +@@ -176,7 +175,7 @@ file = /var/lib/random-seed + ## are ignored. Logfile rotation will cause a report because of shrinking + ## size and different inode. + ## +-dir = 99/var/log ++dir = 99/var/volatile/log + + [Attributes] + # +-- +1.7.9.5 + diff --git a/meta-security/recipes-security/samhain/files/samhain-samhainrc.patch b/meta-security/recipes-security/samhain/files/samhain-samhainrc.patch new file mode 100644 index 000000000..145700a0e --- /dev/null +++ b/meta-security/recipes-security/samhain/files/samhain-samhainrc.patch @@ -0,0 +1,158 @@ +commit 4c6658441eb3ffc4e51ed70f78cbdab046957580 +Author: Aws Ismail <aws.ismail@windriver.com> +Date: Fri Jun 22 16:38:20 2012 -0400 + +Make samhainrc OE-friendly. + +Patch the samhainrc that will be installed +as part of the 'make install' step to more +accurately reflect what will be found, and +what will be of concern, on a OE install. + +Upstream-Status: Inappropriate [configuration] + +Signed-off-by: Aws Ismail <aws.ismail@windriver.com> + +diff --git a/samhainrc.linux b/samhainrc.linux +index 9bc5ca4..10a8176 100644 +--- a/samhainrc.linux ++++ b/samhainrc.linux +@@ -74,7 +74,6 @@ dir = 0/ + [Attributes] + file = /tmp + file = /dev +-file = /media + file = /proc + file = /sys + +@@ -93,19 +92,10 @@ dir = 99/etc + ## check permission and ownership + ## + file = /etc/mtab ++file = /etc/fstab + file = /etc/adjtime + file = /etc/motd +-file = /etc/lvm/.cache +- +-# On Ubuntu, these are in /var/lib rather than /etc +-file = /etc/cups/certs +-file = /etc/cups/certs/0 +- +-# managed by fstab-sync on Fedora Core +-file = /etc/fstab +- +-# modified when booting +-file = /etc/sysconfig/hwconf ++file = /etc/lvm/lvm.conf + + # There are files in /etc that might change, thus changing the directory + # timestamps. Put it here as 'file', and in the ReadOnly section as 'dir'. +@@ -147,10 +137,6 @@ dir = 99/dev + ## + dir = -1/dev/pts + +-# dir = -1/dev/.udevdb +- +-file = /dev/ppp +- + # + # --------- /usr ----------- + # +@@ -167,50 +153,21 @@ dir = 99/var + + [IgnoreAll] + dir = -1/var/cache +-dir = -1/var/backups +-dir = -1/var/games +-dir = -1/var/gdm + dir = -1/var/lock + dir = -1/var/mail + dir = -1/var/run + dir = -1/var/spool + dir = -1/var/tmp +-dir = -1/var/lib/texmf +-dir = -1/var/lib/scrollkeeper + + + [Attributes] + +-dir = /var/lib/nfs +-dir = /var/lib/pcmcia +- + # /var/lib/rpm changes if packets are installed; + # /var/lib/rpm/__db.00[123] even more frequently + file = /var/lib/rpm/__db.00? + +-file = /var/lib/acpi-support/vbestate +-file = /var/lib/alsa/asound.state +-file = /var/lib/apt/lists/lock +-file = /var/lib/apt/lists/partial +-file = /var/lib/cups/certs +-file = /var/lib/cups/certs/0 +-file = /var/lib/dpkg/lock +-file = /var/lib/gdm +-file = /var/lib/gdm/.cookie +-file = /var/lib/gdm/.gdmfifo +-file = /var/lib/gdm/:0.Xauth +-file = /var/lib/gdm/:0.Xservers +-file = /var/lib/logrotate/status +-file = /var/lib/mysql +-file = /var/lib/mysql/ib_logfile0 +-file = /var/lib/mysql/ibdata1 +-file = /var/lib/slocate +-file = /var/lib/slocate/slocate.db +-file = /var/lib/slocate/slocate.db.tmp +-file = /var/lib/urandom +-file = /var/lib/urandom/random-seed ++file = /var/lib/logrotate.status + file = /var/lib/random-seed +-file = /var/lib/xkb + + + [GrowingLogFiles] +@@ -325,7 +282,7 @@ IgnoreMissing = /var/lib/slocate/slocate.db.tmp + + ## Console + ## +-# PrintSeverity=info ++PrintSeverity=warn + + ## Logfile + ## +@@ -333,7 +290,7 @@ IgnoreMissing = /var/lib/slocate/slocate.db.tmp + + ## Syslog + ## +-# SyslogSeverity=none ++SyslogSeverity=info + + ## Remote server (yule) + ## +@@ -556,7 +513,8 @@ ChecksumTest=check + ## and I/O limit (kilobytes per second; 0 == off) + ## to reduce load on host. + # +-# SetNiceLevel = 0 ++# By default we configure samhain to be nice with everything else on the system ++SetNiceLevel = 10 + # SetIOLimit = 0 + + ## The version string to embed in file signature databases +@@ -565,13 +523,14 @@ ChecksumTest=check + + ## Interval between time stamp messages + # +-# SetLoopTime = 60 +-SetLoopTime = 600 ++# Log a timestamp every hour ++SetLoopTime = 3600 + + ## Interval between file checks + # + # SetFileCheckTime = 600 +-SetFileCheckTime = 7200 ++# One file system check per day ++SetFileCheckTime = 86400 + + ## Alternative: crontab-like schedule + # diff --git a/meta-security/recipes-security/samhain/files/samhain-server-volatiles b/meta-security/recipes-security/samhain/files/samhain-server-volatiles new file mode 100644 index 000000000..6b8070936 --- /dev/null +++ b/meta-security/recipes-security/samhain/files/samhain-server-volatiles @@ -0,0 +1 @@ +d daemon daemon 0775 /var/log/yule none diff --git a/meta-security/recipes-security/samhain/files/samhain-server.default b/meta-security/recipes-security/samhain/files/samhain-server.default new file mode 100644 index 000000000..bc3d67cde --- /dev/null +++ b/meta-security/recipes-security/samhain/files/samhain-server.default @@ -0,0 +1,3 @@ +# Set this to "yes" to start the server, after you configure it, of +# course. +SAMHAIN_SERVER_START="no"
\ No newline at end of file diff --git a/meta-security/recipes-security/samhain/files/samhain-server.init b/meta-security/recipes-security/samhain/files/samhain-server.init new file mode 100644 index 000000000..c456e51c9 --- /dev/null +++ b/meta-security/recipes-security/samhain/files/samhain-server.init @@ -0,0 +1,116 @@ +#!/bin/bash +# chkconfig: 2345 98 11 +# description: File Integrity Checking Daemon +# +# processname: yule +# config : /etc/yulerc +# logfile : /var/log/yule/yule_log +# database: /var/lib/yule/yule_file +# + +NAME=yule +DAEMON=/usr/sbin/yule +RETVAL=0 +PIDFILE=/var/run/yule.pid + +. /etc/default/rcS + +. /etc/default/samhain-server + +if [ "x$SAMHAIN_SERVER_START" != "xyes" ]; then + echo "${0}: server disabled in /etc/default/samhain-server" + exit 0 +fi + +if [ -x $DAEMON ]; then + : +else + echo "${0}: executable ${DAEMON} not found" + exit 1 +fi + +samhain_done() +{ + if [ $RETVAL -eq 0 ]; then + echo "." + else + echo " failed." + fi +} + +log_stat_msg () { +case "$1" in + 0) + echo "Service $NAME: Running"; + ;; + 1) + echo "Service $NAME: Stopped and /var/run pid file exists"; + ;; + 3) + echo "Service $NAME: Stopped"; + ;; + *) + echo "Service $NAME: Status unknown"; + ;; +esac +} + +case "$1" in + start) + # + # Remove a stale PID file, if found + # + if test -f ${PIDFILE}; then + /bin/rm -f ${PIDFILE} + fi + # + echo -n "Starting ${NAME}" + start-stop-daemon --start --quiet --exec $DAEMON + RETVAL=$? + samhain_done + ;; + + stop) + echo -n "Stopping $NAME" + start-stop-daemon --stop --quiet --exec $DAEMON + RETVAL=$? + + # + # Remove a stale PID file, if found + # + if test -f ${PIDFILE}; then + /bin/rm -f ${PIDFILE} + fi + if test -S /var/run/${NAME}.sock; then + /bin/rm -f /var/run/${NAME}.sock + fi + samhain_done + ;; + + restart) + $0 stop + sleep 3 + $0 start + RETVAL=$? + ;; + + reload|force-reload) + echo -n "Reloading $NAME configuration files" + start-stop-daemon --stop --signal 1 --quiet --exec $DAEMON + RETVAL=$? + samhain_done + ;; + + status) + $DAEMON status + RETVAL=$? + log_stat_msg ${RETVAL} + ;; + + *) + echo "$0 usage: {start|stop|status|restart|reload}" + exit 1 + ;; +esac + +exit $RETVAL diff --git a/meta-security/recipes-security/samhain/files/samhain-sha256-big-endian.patch b/meta-security/recipes-security/samhain/files/samhain-sha256-big-endian.patch new file mode 100644 index 000000000..3065c7309 --- /dev/null +++ b/meta-security/recipes-security/samhain/files/samhain-sha256-big-endian.patch @@ -0,0 +1,22 @@ +samhain: fix sha256 for big-endian machines + +After computing the digest, big-endian machines would +memset() the digest to the first byte of state instead +of using memcpy() to transfer it. + +Upstream-Status: Pending + +Signed-off-by: Joe Slater <jslater@windriver.com> + + +--- a/src/sh_checksum.c ++++ b/src/sh_checksum.c +@@ -468,7 +468,7 @@ void SHA256_Final(sha2_byte digest[], SH + } + } + #else +- memset(d, context->state, SHA256_DIGEST_LENGTH); ++ memcpy(d, context->state, SHA256_DIGEST_LENGTH); + /* bcopy(context->state, d, SHA256_DIGEST_LENGTH); */ + #endif + } diff --git a/meta-security/recipes-security/samhain/files/samhain-standalone.default b/meta-security/recipes-security/samhain/files/samhain-standalone.default new file mode 100644 index 000000000..507a59f29 --- /dev/null +++ b/meta-security/recipes-security/samhain/files/samhain-standalone.default @@ -0,0 +1,3 @@ +# Set this to "yes" to start the server, after you configure it, of +# course. +SAMHAIN_STANDALONE_START="no" diff --git a/meta-security/recipes-security/samhain/files/samhain-standalone.init b/meta-security/recipes-security/samhain/files/samhain-standalone.init new file mode 100644 index 000000000..2f23bffd9 --- /dev/null +++ b/meta-security/recipes-security/samhain/files/samhain-standalone.init @@ -0,0 +1,123 @@ +#!/bin/sh +# chkconfig: 2345 99 10 +# description: File Integrity Checking Daemon +# +# processname: samhain +# config : /etc/samhainrc +# logfile : /var/log/samhain_log +# database: /var/lib/samhain/samhain_file +# + +NAME=samhain +DAEMON=/usr/sbin/samhain +RETVAL=0 +VERBOSE=yes +PIDFILE=/var/run/samhain.pid + +. /etc/default/samhain-standalone + +if [ "x$SAMHAIN_STANDALONE_START" != "xyes" ]; then + echo "${0}: samhain disabled in /etc/default/samhain-standalone" + exit 0 +fi + +if [ -x $DAEMON ]; then + : +else + echo "${0}: executable ${DAEMON} not found" + exit 1 +fi + +if [ ! -e /var/lib/samhain/samhain_file ]; then + echo "${0}: /var/lib/samhain/samhain_file does not exist. You must" + echo " run 'samhain -t init' before samhian can start." + exit 1 +fi + +samhain_done() +{ + if [ $RETVAL -eq 0 ]; then + echo "." + else + echo " failed." + fi +} + +log_stat_msg () { +case "$1" in + 0) + echo "Service $NAME: Running"; + ;; + 1) + echo "Service $NAME: Stopped and /var/run pid file exists"; + ;; + 3) + echo "Service $NAME: Stopped"; + ;; + *) + echo "Service $NAME: Status unknown"; + ;; +esac +} + +case "$1" in + start) + # + # Remove a stale PID file, if found + # + if test -f ${PIDFILE}; then + /bin/rm -f ${PIDFILE} + fi + + echo -n "Starting ${NAME}" + start-stop-daemon --start --quiet --exec $DAEMON + RETVAL=$? + samhain_done + exit $RETVAL + ;; + stop) + echo -n "Stopping $NAME" + start-stop-daemon --stop --quiet --exec $DAEMON + RETVAL=$? + samhain_done + # + # Remove a stale PID file, if found + # + if test -f ${PIDFILE}; then + /bin/rm -f ${PIDFILE} + fi + if test -S /var/run/${NAME}.sock; then + /bin/rm -f /var/run/${NAME}.sock + fi + ;; + + restart) + $0 stop + sleep 3 + $0 start + RETVAL=$? + ;; + + reload|force-reload) + echo -n "Reloading $NAME configuration files" + start-stop-daemon --stop --signal 1 --quiet --exec $DAEMON + RETVAL=$? + samhain_done + ;; + + status) + if pidof -o %PPID $DAEMON > /dev/null; then + echo "Samhain running" + RETVAL=0 + else + echo "Samhain not running" + RETVAL=1 + fi + ;; + *) + echo "$0 usage: {start|stop|status|restart|reload}" + exit 1 + ;; +esac + +exit $RETVAL diff --git a/meta-security/recipes-security/samhain/files/samhain.service b/meta-security/recipes-security/samhain/files/samhain.service new file mode 100644 index 000000000..e4f216ab4 --- /dev/null +++ b/meta-security/recipes-security/samhain/files/samhain.service @@ -0,0 +1,12 @@ +[Unit] +Description=Samhain @MODE_NAME@ Daemon +After=syslog.target network.target + +[Service] +Type=forking +RemainAfterExit=yes +ExecStart=@LIBDIR@/@SAMHAIN_HELPER@ start +ExecStop=@LIBDIR@/@SAMHAIN_HELPER@ stop + +[Install] +WantedBy=multi-user.target diff --git a/meta-security/recipes-security/samhain/samhain-client_4.2.2.bb b/meta-security/recipes-security/samhain/samhain-client_4.2.2.bb new file mode 100644 index 000000000..812408e5e --- /dev/null +++ b/meta-security/recipes-security/samhain/samhain-client_4.2.2.bb @@ -0,0 +1,11 @@ +INITSCRIPT_PARAMS = "defaults 15 85" + +require samhain.inc + +# Let the default Logserver be 127.0.0.1 +EXTRA_OECONF += " \ + --with-logserver=${SAMHAIN_SERVER} \ + --with-port=${SAMHAIN_PORT} \ + " + +RDEPENDS_${PN} = "acl zlib attr bash" diff --git a/meta-security/recipes-security/samhain/samhain-server_4.2.2.bb b/meta-security/recipes-security/samhain/samhain-server_4.2.2.bb new file mode 100644 index 000000000..9341d4440 --- /dev/null +++ b/meta-security/recipes-security/samhain/samhain-server_4.2.2.bb @@ -0,0 +1,20 @@ +INITSCRIPT_PARAMS = "defaults 14 86" + +require samhain.inc + +DEPENDS = "gmp" + +SRC_URI += "file://samhain-server-volatiles" + +TARGET_CC_ARCH += "${LDFLAGS}" + +do_install_append() { + install -d ${D}${sysconfdir}/default/volatiles + install -m 0644 ${WORKDIR}/samhain-server-volatiles \ + ${D}${sysconfdir}/default/volatiles/samhain-server + + install -m 700 samhain-install.sh init/samhain.startLinux \ + init/samhain.startLSB ${D}/var/lib/samhain +} + +RDEPENDS_${PN} += "gmp bash perl" diff --git a/meta-security/recipes-security/samhain/samhain-standalone_4.2.2.bb b/meta-security/recipes-security/samhain/samhain-standalone_4.2.2.bb new file mode 100644 index 000000000..4fed9e9e9 --- /dev/null +++ b/meta-security/recipes-security/samhain/samhain-standalone_4.2.2.bb @@ -0,0 +1,31 @@ +require samhain.inc + +SRC_URI += "file://samhain-not-run-ptest-on-host.patch \ + file://run-ptest \ +" + +PROVIDES += "samhain" + +SYSTEMD_SERVICE_${PN} = "samhain.service" + +inherit ptest + +do_compile() { + if [ "${@bb.utils.contains('DISTRO_FEATURES', 'ptest', 'yes', 'no', d)}" = "yes" ]; then + oe_runmake cutest + rm -f ${S}*.o config_xor.h internal.h + fi + oe_runmake "$@" +} + +do_install_append() { + ln -sf ${INITSCRIPT_NAME} ${D}${sysconfdir}/init.d/samhain +} + +do_install_ptest() { + mkdir -p ${D}${PTEST_PATH} + install ${S}/cutest ${D}${PTEST_PATH} +} + +RPROVIDES_${PN} += "samhain" +RCONFLICTS_${PN} = "samhain-client samhain-server" diff --git a/meta-security/recipes-security/samhain/samhain.inc b/meta-security/recipes-security/samhain/samhain.inc new file mode 100644 index 000000000..db96264b3 --- /dev/null +++ b/meta-security/recipes-security/samhain/samhain.inc @@ -0,0 +1,159 @@ +DESCRIPTION = "Provides file integrity checking and log file monitoring/analysis" +HOMEPAGE = "http://www.la-samhna.de/samhain/" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://LICENSE;md5=8ca43cbc842c2336e835926c2166c28b" + + +SRC_URI = "http://la-samhna.de/archive/samhain_signed-${PV}.tar.gz \ + file://samhain-cross-compile.patch \ + file://samhain-mips64-aarch64-dnmalloc-hash-fix.patch \ + file://samhain-samhainrc.patch \ + file://samhain-samhainrc-fix-files-dirs-path.patch \ + file://samhain-pid-path.patch \ + file://samhain-sha256-big-endian.patch \ + file://samhain-configure-add-option-for-ps.patch \ + file://samhain-avoid-searching-host-for-postgresql.patch \ + file://samhain-add-LDFLAGS-variable-for-samhain_setpwd.patch \ + file://${INITSCRIPT_NAME}.init \ + file://${INITSCRIPT_NAME}.default \ + file://samhain.service \ + " + +SRC_URI[md5sum] = "f499d5d06bfd1d787073a45bf28dd60f" +SRC_URI[sha256sum] = "0f3e64afb3f00064c9b136d34a72d580cd41248c5941eba0452f364a109003c7" + +S = "${WORKDIR}/samhain-${PV}" + +inherit autotools-brokensep update-rc.d pkgconfig systemd + +SAMHAIN_PORT ??= "49777" +SAMHAIN_SERVER ??= "NULL" + +INITSCRIPT_NAME = "${BPN}" +INITSCRIPT_PARAMS ?= "defaults" + +SYSTEMD_PACKAGES = "${PN}" +SYSTEMD_SERVICE_${PN} = "${INITSCRIPT_NAME}.service" +SYSTEMD_AUTO_ENABLE = "disable" + +# mode mapping: +# BPN MODE_NAME SAMHAIN_MODE +# samhain-standalone standalone no +# samhain-client client client +# samhain-server server server +MODE_NAME = "${@d.getVar('BPN').split('-')[1]}" +SAMHAIN_MODE = "${@oe.utils.ifelse(d.getVar('MODE_NAME') == 'standalone', 'no', '${MODE_NAME}')}" + +# supports mysql|postgresql|oracle|odbc but postgresql is the only one available + +PACKAGECONFIG ??= "postgresql ps \ + ${@bb.utils.contains('DISTRO_FEATURES', 'ipv6', 'ipv6', '', d)} \ + ${@bb.utils.contains('DISTRO_FEATURES', 'selinux', 'selinux audit', '', d)} \ + ${@bb.utils.contains('DISTRO_FEATURES', 'acl', 'acl', '', d)} \ +" + +PACKAGECONFIG[postgresql] = "--with-database=postgresql --enable-xml-log PGSQL_INC_DIR=${STAGING_INCDIR} PGSQL_LIB_DIR=${STAGING_LIBDIR}, , postgresql" +PACKAGECONFIG[suidcheck] = "--enable-suidcheck, , " +PACKAGECONFIG[logwatch] = "--enable-login-watch, , " +PACKAGECONFIG[mounts] = "--enable-mounts-check, , " +PACKAGECONFIG[userfiles] = "--enable-userfiles, , " +PACKAGECONFIG[ipv6] = "--enable-ipv6,--disable-ipv6," +PACKAGECONFIG[selinux] = "--enable-selinux, --disable-selinux, libselinux attr" +PACKAGECONFIG[acl] = " --enable-posix-acl , --disable-posix-acl, acl" +PACKAGECONFIG[audit] = "ac_cv_header_auparse_h=yes,ac_cv_header_auparse_h=no,audit" +PACKAGECONFIG[ps] = "--with-ps-path=${base_bindir}/ps,,,procps" + +do_unpack_samhain() { + cd ${WORKDIR} + tar -xzvf samhain-${PV}.tar.gz +} + +python do_unpack_append() { + bb.build.exec_func('do_unpack_samhain', d) +} + +do_configure_prepend_arm() { + export sh_cv___va_copy=yes +} + +do_configure_prepend_aarch64() { + export sh_cv___va_copy=yes +} + +# If we use oe_runconf in do_configure() it will by default +# use the prefix --oldincludedir=/usr/include which is not +# recognized by Samhain's configure script and would invariably +# throw back the error "unrecognized option: --oldincludedir=/usr/include" +do_configure_prepend () { + cat << EOF > ${S}/config-site.${BP} +ssp_cv_lib=no +sh_cv_va_copy=yes +EOF + export CONFIG_SITE=${S}/config-site.${BP} +} + +do_configure () { + autoconf -f + ./configure \ + --build=${BUILD_SYS} \ + --host=${HOST_SYS} \ + --target=${TARGET_SYS} \ + --prefix=${prefix} \ + --exec_prefix=${exec_prefix} \ + --bindir=${bindir} \ + --sbindir=${sbindir} \ + --libexecdir=${libexecdir} \ + --datadir=${datadir} \ + --sysconfdir=${sysconfdir} \ + --sharedstatedir=${sharedstatedir} \ + --localstatedir=${localstatedir} \ + --libdir=${libdir} \ + --includedir=${includedir} \ + --infodir=${infodir} \ + --mandir=${mandir} \ + --enable-network=${SAMHAIN_MODE} \ + --with-pid-file=${localstatedir}/run/samhain.pid \ + --with-data-file=${localstatedir}/lib/samhain/samhain_file \ + ${EXTRA_OECONF} +} + +do_compile_prepend_libc-musl () { + sed -i 's/^#define HAVE_MALLOC_H.*//' ${B}/config.h +} + +# Install the init script, it's default file, and the extraneous +# documentation. +do_install_append () { + oe_runmake install DESTDIR='${D}' INSTALL=install-boot + + install -D -m 755 ${WORKDIR}/${INITSCRIPT_NAME}.init \ + ${D}${sysconfdir}/init.d/${INITSCRIPT_NAME} + + install -D -m 755 ${WORKDIR}/${INITSCRIPT_NAME}.default \ + ${D}${sysconfdir}/default/${INITSCRIPT_NAME} + + if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then + if [ "${SAMHAIN_MODE}" = "no" ]; then + install -D -m 0644 ${WORKDIR}/samhain.service ${D}/${systemd_system_unitdir}/samhain.service + else + install -D -m 0644 ${WORKDIR}/samhain.service ${D}/${systemd_system_unitdir}/${BPN}.service + fi + install -D -m 0755 ${WORKDIR}/${BPN}.init ${D}/${libexecdir}/${BPN} + sed -i -e 's,@LIBDIR@,${libexecdir},' \ + -e 's,@SAMHAIN_HELPER@,${BPN},' \ + -e 's,@MODE_NAME@,${MODE_NAME},' \ + ${D}${systemd_system_unitdir}/samhain*.service + fi + + install -d ${D}${docdir}/${BPN} + cp -r docs/* ${D}${docdir}/${BPN} + cp -r scripts ${D}${docdir}/${BPN} + install -d -m 755 ${D}${localstatedir}/samhain + + # Prevent QA warnings about installed ${localstatedir}/run + if [ -d ${D}${localstatedir}/run ]; then + rmdir ${D}${localstatedir}/run + fi +} + +FILES_${PN} += "${systemd_system_unitdir}" diff --git a/meta-security/recipes-security/scapy/scapy/run-ptest b/meta-security/recipes-security/scapy/scapy/run-ptest new file mode 100755 index 000000000..91b29f907 --- /dev/null +++ b/meta-security/recipes-security/scapy/scapy/run-ptest @@ -0,0 +1,4 @@ +#!/bin/sh +UTscapy -t regression.uts -f text -l -C \ + -o @PTEST_PATH@/scapy_ptest_$(date +%Y%m%d-%H%M%S).log \ + 2>&1 | sed -e 's/^passed None/PASS:/' -e 's/^failed None/FAIL:/' diff --git a/meta-security/recipes-security/scapy/scapy_2.3.3.bb b/meta-security/recipes-security/scapy/scapy_2.3.3.bb new file mode 100644 index 000000000..1c8685b1a --- /dev/null +++ b/meta-security/recipes-security/scapy/scapy_2.3.3.bb @@ -0,0 +1,24 @@ +SUMMARY = "Network scanning and manipulation tool" +DESCRIPTION = "Scapy is a powerful interactive packet manipulation program. It is able to forge or decode packets of a wide number of protocols, send them on the wire, capture them, match requests and replies, and much more. It can easily handle most classical tasks like scanning, tracerouting, probing, unit tests, attacks or network discovery (it can replace hping, 85% of nmap, arpspoof, arp-sk, arping, tcpdump, tethereal, p0f, etc.). It also performs very well at a lot of other specific tasks that most other tools can't handle, like sending invalid frames, injecting your own 802.11 frames, combining technics (VLAN hopping+ARP cache poisoning, VOIP decoding on WEP encrypted channel, ...), etc." +SECTION = "security" +LICENSE = "GPLv2" + +LIC_FILES_CHKSUM = "file://bin/scapy;beginline=9;endline=13;md5=1d5249872cc54cd4ca3d3879262d0c69" + +SRC_URI = "https://github.com/secdev/${BPN}/archive/v${PV}.tar.gz;downloadfilename=${BP}.tar.gz \ + file://run-ptest \ +" + +SRC_URI[md5sum] = "336d6832110efcf79ad30c9856ef5842" +SRC_URI[sha256sum] = "67642cf7b806e02daeddd588577588caebddc3426db7904e7999a0b0334a63b5" + +inherit setuptools ptest + +do_install_ptest() { + install -m 0644 ${S}/test/regression.uts ${D}${PTEST_PATH} + sed -i 's,@PTEST_PATH@,${PTEST_PATH},' ${D}${PTEST_PATH}/run-ptest +} + +RDEPENDS_${PN} = "tcpdump python-subprocess python-compression python-netclient \ + python-netserver python-pydoc python-pkgutil python-shell \ + python-threading python-numbers python-pycrypto" diff --git a/meta-security/recipes-security/smack/files/run-ptest b/meta-security/recipes-security/smack/files/run-ptest new file mode 100644 index 000000000..049a9b47a --- /dev/null +++ b/meta-security/recipes-security/smack/files/run-ptest @@ -0,0 +1,3 @@ +#!/bin/sh +./tests/make_policies.bash ./tests/generator +./tests/make_policies.bash ./tests/generator labels diff --git a/meta-security/recipes-security/smack/files/smack_generator_make_fixup.patch b/meta-security/recipes-security/smack/files/smack_generator_make_fixup.patch new file mode 100644 index 000000000..4d677e751 --- /dev/null +++ b/meta-security/recipes-security/smack/files/smack_generator_make_fixup.patch @@ -0,0 +1,18 @@ +Upstream-Status: Pending + +Signed-off-by: Armin Kuster <akuster808@gmail.com> + + +Index: git/tests/Makefile +=================================================================== +--- git.orig/tests/Makefile ++++ git/tests/Makefile +@@ -4,7 +4,7 @@ clean: + rm -rf ./out ./generator + + generator: generator.c +- gcc -Wall -O3 generator.c -o ./generator ++ ${CC} ${LDFLAGS} generator.c -o ./generator + + policies: ./generator ./make_policies.bash + ./make_policies.bash ./generator diff --git a/meta-security/recipes-security/smack/smack_1.3.1.bb b/meta-security/recipes-security/smack/smack_1.3.1.bb new file mode 100644 index 000000000..246562afe --- /dev/null +++ b/meta-security/recipes-security/smack/smack_1.3.1.bb @@ -0,0 +1,54 @@ +DESCRIPTION = "Selection of tools for developers working with Smack" +HOMEPAGE = "https://github.com/smack-team/smack" +SECTION = "Security/Access Control" +LICENSE = "LGPL-2.1" + +LIC_FILES_CHKSUM = "file://COPYING;md5=4fbd65380cdd255951079008b364516c" + +SRCREV = "4a102c7584b39ce693995ffb65e0918a9df98dd8" +SRC_URI = " \ + git://github.com/smack-team/smack.git \ + file://smack_generator_make_fixup.patch \ + file://run-ptest" + +PV = "1.3.1" + +inherit autotools update-rc.d pkgconfig ptest ${@bb.utils.contains('VIRTUAL-RUNTIME_init_manager','systemd','systemd','', d)} + +S = "${WORKDIR}/git" + +PACKAGECONFIG ??= "" +PACKAGECONFIG_append = " ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd', '', d)}" + +PACKAGECONFIG[systemd] = "--with-systemdsystemunitdir=${systemd_system_unitdir}, --without-systemdsystemunitdir, systemd" + +do_compile_append () { + oe_runmake -C ${S}/tests generator +} + +do_install_append () { + install -d ${D}${sysconfdir}/init.d + install -d ${D}${sysconfdir}/smack + install -d ${D}${sysconfdir}/smack/accesses.d + install -d ${D}${sysconfdir}/smack/cipso.d + install ${S}/init/smack.rc ${D}/${sysconfdir}/init.d/smack +} + +do_install_ptest () { + install -d ${D}${PTEST_PATH}/tests + install ${S}/tests/generator ${D}/${PTEST_PATH}/tests + install ${S}/tests/generate-rules.sh ${D}${PTEST_PATH}/tests + install ${S}/tests/make_policies.bash ${D}${PTEST_PATH}/tests +} + +INITSCRIPT_PACKAGES = "${PN}" +INITSCRIPT_NAME = "smack" +INITSCRIPT_PARAMS = "start 16 2 3 4 5 . stop 35 0 1 6 ." + +FILES_${PN} += "${sysconfdir}/init.d/smack" +FILES_${PN}-ptest += "generator" + +RDEPENDS_${PN} += "coreutils" +RDEPENDS_${PN}-ptest += "make bash bc" + +BBCLASSEXTEND = "native" diff --git a/meta-security/recipes-security/sssd/files/sssd.conf b/meta-security/recipes-security/sssd/files/sssd.conf new file mode 100644 index 000000000..1709a7afd --- /dev/null +++ b/meta-security/recipes-security/sssd/files/sssd.conf @@ -0,0 +1,8 @@ +[sssd] +services = nss, pam +config_file_version = 2 + +[nss] + +[pam] + diff --git a/meta-security/recipes-security/sssd/sssd_1.16.0.bb b/meta-security/recipes-security/sssd/sssd_1.16.0.bb new file mode 100644 index 000000000..ff5b618bc --- /dev/null +++ b/meta-security/recipes-security/sssd/sssd_1.16.0.bb @@ -0,0 +1,73 @@ +SUMMARY = "system security services daemon" +DESCRIPTION = "SSSD is a system security services daemon" +HOMEPAGE = "https://fedorahosted.org/sssd/" +SECTION = "base" +LICENSE = "GPLv3+" +LIC_FILES_CHKSUM = "file://COPYING;md5=d32239bcb673463ab874e80d47fae504" + +DEPENDS = "openldap cyrus-sasl libtdb ding-libs libpam c-ares krb5 autoconf-archive" +DEPENDS += "libldb dbus libtalloc libpcre glib-2.0 popt e2fsprogs libtevent" + +SRC_URI = "https://releases.pagure.org/SSSD/${BPN}/${BP}.tar.gz\ + file://sssd.conf " + +SRC_URI[md5sum] = "f721ace2ebfa6744cfea55e3ecd2d82f" +SRC_URI[sha256sum] = "c581a6e5365cef87fca419c0c9563cf15eadbb682863d648d85ffcded7a3940f" + +inherit autotools pkgconfig gettext update-rc.d python-dir distro_features_check + +REQUIRED_DISTRO_FEATURES = "pam" + +CACHED_CONFIGUREVARS = "ac_cv_member_struct_ldap_conncb_lc_arg=no \ + ac_cv_path_NSUPDATE=${bindir} \ + ac_cv_path_PYTHON2=${PYTHON_DIR} ac_cv_prog_HAVE_PYTHON3=${PYTHON_DIR} \ + " + +PACKAGECONFIG ?="nss nscd" +PACKAGECONFIG += "${@bb.utils.contains('DISTRO_FEATURES', 'selinux', 'selinux', '', d)}" + +PACKAGECONFIG[ssh] = "--with-ssh, --with-ssh=no, " +PACKAGECONFIG[samba] = "--with-samba, --with-samba=no, samba" +PACKAGECONFIG[selinux] = "--with-selinux, --with-selinux=no --with-semanage=no, libselinux" +PACKAGECONFIG[manpages] = "--with-manpages, --with-manpages=no" +PACKAGECONFIG[python2] = "--with-python2-bindings, --without-python2-bindings" +PACKAGECONFIG[python3] = "--with-python3-bindings, --without-python3-bindings" +PACKAGECONFIG[nss] = "--with-crypto=nss, ,nss," +PACKAGECONFIG[cyrpto] = "--with-crypto=libcrypto, , libcrypto" +PACKAGECONFIG[nscd] = "--with-nscd=${sbindir}, --with-nscd=no " +PACKAGECONFIG[nl] = "--with-libnl, --with-libnl=no, libnl" +PACKAGECONFIG[systemd] = "--with-systemdunitdir=${systemd_unitdir}/system/, --with-systemdunitdir=" +PACKAGECONFIG[http] = "--with-secrets, --without-secrets, apache2" +PACKAGECONFIG[curl] = "--with-secrets --with-kcm, --without-secrets --without-kcm, curl" + +EXTRA_OECONF += "--disable-cifs-idmap-plugin --without-nfsv4-idmapd-plugin --without-ipa-getkeytab" + +do_configure_prepend() { + mkdir -p ${AUTOTOOLS_AUXDIR}/build + cp ${STAGING_DATADIR_NATIVE}/gettext/config.rpath ${AUTOTOOLS_AUXDIR}/build/ + + # libresove has host path, remove it + sed -i -e "s#\$sss_extra_libdir##" ${S}/src/external/libresolv.m4 +} + +do_install () { + oe_runmake install DESTDIR="${D}" + rmdir --ignore-fail-on-non-empty "${D}/${bindir}" + install -d ${D}/${sysconfdir}/${BPN} + install -m 600 ${WORKDIR}/${BPN}.conf ${D}/${sysconfdir}/${BPN} +} + +CONFFILES_${PN} = "${sysconfdir}/${BPN}/${BPN}.conf" + +INITSCRIPT_NAME = "sssd" +INITSCRIPT_PARAMS = "start 02 5 3 2 . stop 20 0 1 6 ." +SYSTEMD_SERVICE_${PN} = "${BPN}.service" +SYSTEMD_AUTO_ENABLE = "disable" + +FILES_${PN} += "${libdir} ${datadir} /run ${libdir}/*.so* " +FILES_${PN}-dev = " ${includedir}/* ${libdir}/*la ${libdir}/*/*la" + +# The package contains symlinks that trip up insane +INSANE_SKIP_${PN} = "dev-so" + +RDEPENDS_${PN} += "bind dbus" diff --git a/meta-security/recipes-security/suricata/files/no_libhtp_build.patch b/meta-security/recipes-security/suricata/files/no_libhtp_build.patch new file mode 100644 index 000000000..2ebf021fc --- /dev/null +++ b/meta-security/recipes-security/suricata/files/no_libhtp_build.patch @@ -0,0 +1,38 @@ +Upstream-Status: Inappropriate [configuration] + +Signed-of_by: Armin Kuster <akuster808@gmail.com> + +Index: suricata-2.0.5/Makefile.am +=================================================================== +--- suricata-2.0.5.orig/Makefile.am ++++ suricata-2.0.5/Makefile.am +@@ -5,7 +5,7 @@ ACLOCAL_AMFLAGS = -I m4 + EXTRA_DIST = ChangeLog COPYING LICENSE suricata.yaml.in \ + classification.config threshold.config \ + reference.config +-SUBDIRS = $(HTP_DIR) src qa rules doc contrib scripts ++SUBDIRS = src qa rules doc contrib scripts + + CLEANFILES = stamp-h[0-9]* + +Index: suricata-2.0.5/Makefile.in +=================================================================== +--- suricata-2.0.5.orig/Makefile.in ++++ suricata-2.0.5/Makefile.in +@@ -229,7 +229,6 @@ HAVE_PCAP_CONFIG = @HAVE_PCAP_CONFIG@ + HAVE_PKG_CONFIG = @HAVE_PKG_CONFIG@ + HAVE_PYTHON_CONFIG = @HAVE_PYTHON_CONFIG@ + HAVE_WGET = @HAVE_WGET@ +-HTP_DIR = @HTP_DIR@ + HTP_LDADD = @HTP_LDADD@ + INSTALL = @INSTALL@ + INSTALL_DATA = @INSTALL_DATA@ +@@ -369,7 +368,7 @@ EXTRA_DIST = ChangeLog COPYING LICENSE s + classification.config threshold.config \ + reference.config + +-SUBDIRS = $(HTP_DIR) src qa rules doc contrib scripts ++SUBDIRS = src qa rules doc contrib scripts + CLEANFILES = stamp-h[0-9]* + all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive diff --git a/meta-security/recipes-security/suricata/files/suricata.yaml b/meta-security/recipes-security/suricata/files/suricata.yaml new file mode 100644 index 000000000..90417b03d --- /dev/null +++ b/meta-security/recipes-security/suricata/files/suricata.yaml @@ -0,0 +1,1326 @@ +%YAML 1.1 +--- + +# Suricata configuration file. In addition to the comments describing all +# options in this file, full documentation can be found at: +# https://redmine.openinfosecfoundation.org/projects/suricata/wiki/Suricatayaml + + +# Number of packets allowed to be processed simultaneously. Default is a +# conservative 1024. A higher number will make sure CPU's/CPU cores will be +# more easily kept busy, but may negatively impact caching. +# +# If you are using the CUDA pattern matcher (mpm-algo: ac-cuda), different rules +# apply. In that case try something like 60000 or more. This is because the CUDA +# pattern matcher buffers and scans as many packets as possible in parallel. +#max-pending-packets: 1024 + +# Runmode the engine should use. Please check --list-runmodes to get the available +# runmodes for each packet acquisition method. Defaults to "autofp" (auto flow pinned +# load balancing). +#runmode: autofp + +# Specifies the kind of flow load balancer used by the flow pinned autofp mode. +# +# Supported schedulers are: +# +# round-robin - Flows assigned to threads in a round robin fashion. +# active-packets - Flows assigned to threads that have the lowest number of +# unprocessed packets (default). +# hash - Flow alloted usihng the address hash. More of a random +# technique. Was the default in Suricata 1.2.1 and older. +# +#autofp-scheduler: active-packets + +# If suricata box is a router for the sniffed networks, set it to 'router'. If +# it is a pure sniffing setup, set it to 'sniffer-only'. +# If set to auto, the variable is internally switch to 'router' in IPS mode +# and 'sniffer-only' in IDS mode. +# This feature is currently only used by the reject* keywords. +host-mode: auto + +# Run suricata as user and group. +#run-as: +# user: suri +# group: suri + +# Default pid file. +# Will use this file if no --pidfile in command options. +#pid-file: /var/run/suricata.pid + +# Daemon working directory +# Suricata will change directory to this one if provided +# Default: "/" +#daemon-directory: "/" + +# Preallocated size for packet. Default is 1514 which is the classical +# size for pcap on ethernet. You should adjust this value to the highest +# packet size (MTU + hardware header) on your system. +#default-packet-size: 1514 + +# The default logging directory. Any log or output file will be +# placed here if its not specified with a full path name. This can be +# overridden with the -l command line parameter. +default-log-dir: /var/log/suricata/ + +# Unix command socket can be used to pass commands to suricata. +# An external tool can then connect to get information from suricata +# or trigger some modifications of the engine. Set enabled to yes +# to activate the feature. You can use the filename variable to set +# the file name of the socket. +unix-command: + enabled: no + #filename: custom.socket + +# Configure the type of alert (and other) logging you would like. +outputs: + + # a line based alerts log similar to Snort's fast.log + - fast: + enabled: yes + filename: fast.log + append: yes + #filetype: regular # 'regular', 'unix_stream' or 'unix_dgram' + + # Extensible Event Format (nicknamed EVE) event log in JSON format + - eve-log: + enabled: yes + type: file #file|syslog|unix_dgram|unix_stream + filename: eve.json + # the following are valid when type: syslog above + #identity: "suricata" + #facility: local5 + #level: Info ## possible levels: Emergency, Alert, Critical, + ## Error, Warning, Notice, Info, Debug + types: + - alert + - http: + extended: yes # enable this for extended logging information + # custom allows additional http fields to be included in eve-log + # the example below adds three additional fields when uncommented + #custom: [Accept-Encoding, Accept-Language, Authorization] + - dns + - tls: + extended: yes # enable this for extended logging information + - files: + force-magic: no # force logging magic on all logged files + force-md5: no # force logging of md5 checksums + #- drop + - ssh + + # alert output for use with Barnyard2 + - unified2-alert: + enabled: yes + filename: unified2.alert + + # File size limit. Can be specified in kb, mb, gb. Just a number + # is parsed as bytes. + #limit: 32mb + + # Sensor ID field of unified2 alerts. + #sensor-id: 0 + + # HTTP X-Forwarded-For support by adding the unified2 extra header that + # will contain the actual client IP address or by overwriting the source + # IP address (helpful when inspecting traffic that is being reversed + # proxied). + xff: + enabled: no + # Two operation modes are available, "extra-data" and "overwrite". Note + # that in the "overwrite" mode, if the reported IP address in the HTTP + # X-Forwarded-For header is of a different version of the packet + # received, it will fall-back to "extra-data" mode. + mode: extra-data + # Header name were the actual IP address will be reported, if more than + # one IP address is present, the last IP address will be the one taken + # into consideration. + header: X-Forwarded-For + + # a line based log of HTTP requests (no alerts) + - http-log: + enabled: yes + filename: http.log + append: yes + #extended: yes # enable this for extended logging information + #custom: yes # enabled the custom logging format (defined by customformat) + #customformat: "%{%D-%H:%M:%S}t.%z %{X-Forwarded-For}i %H %m %h %u %s %B %a:%p -> %A:%P" + #filetype: regular # 'regular', 'unix_stream' or 'unix_dgram' + + # a line based log of TLS handshake parameters (no alerts) + - tls-log: + enabled: no # Log TLS connections. + filename: tls.log # File to store TLS logs. + append: yes + #filetype: regular # 'regular', 'unix_stream' or 'unix_dgram' + #extended: yes # Log extended information like fingerprint + certs-log-dir: certs # directory to store the certificates files + + # a line based log of DNS requests and/or replies (no alerts) + - dns-log: + enabled: no + filename: dns.log + append: yes + #filetype: regular # 'regular', 'unix_stream' or 'unix_dgram' + + # a line based log to used with pcap file study. + # this module is dedicated to offline pcap parsing (empty output + # if used with another kind of input). It can interoperate with + # pcap parser like wireshark via the suriwire plugin. + - pcap-info: + enabled: no + + # Packet log... log packets in pcap format. 2 modes of operation: "normal" + # and "sguil". + # + # In normal mode a pcap file "filename" is created in the default-log-dir, + # or are as specified by "dir". In Sguil mode "dir" indicates the base directory. + # In this base dir the pcaps are created in th directory structure Sguil expects: + # + # $sguil-base-dir/YYYY-MM-DD/$filename.<timestamp> + # + # By default all packets are logged except: + # - TCP streams beyond stream.reassembly.depth + # - encrypted streams after the key exchange + # + - pcap-log: + enabled: no + filename: log.pcap + + # File size limit. Can be specified in kb, mb, gb. Just a number + # is parsed as bytes. + limit: 1000mb + + # If set to a value will enable ring buffer mode. Will keep Maximum of "max-files" of size "limit" + max-files: 2000 + + mode: normal # normal or sguil. + #sguil-base-dir: /nsm_data/ + #ts-format: usec # sec or usec second format (default) is filename.sec usec is filename.sec.usec + use-stream-depth: no #If set to "yes" packets seen after reaching stream inspection depth are ignored. "no" logs all packets + + # a full alerts log containing much information for signature writers + # or for investigating suspected false positives. + - alert-debug: + enabled: no + filename: alert-debug.log + append: yes + #filetype: regular # 'regular', 'unix_stream' or 'unix_dgram' + + # alert output to prelude (http://www.prelude-technologies.com/) only + # available if Suricata has been compiled with --enable-prelude + - alert-prelude: + enabled: no + profile: suricata + log-packet-content: no + log-packet-header: yes + + # Stats.log contains data from various counters of the suricata engine. + # The interval field (in seconds) tells after how long output will be written + # on the log file. + - stats: + enabled: yes + filename: stats.log + interval: 8 + + # a line based alerts log similar to fast.log into syslog + - syslog: + enabled: no + # reported identity to syslog. If ommited the program name (usually + # suricata) will be used. + #identity: "suricata" + facility: local5 + #level: Info ## possible levels: Emergency, Alert, Critical, + ## Error, Warning, Notice, Info, Debug + + # a line based information for dropped packets in IPS mode + - drop: + enabled: no + filename: drop.log + append: yes + #filetype: regular # 'regular', 'unix_stream' or 'unix_dgram' + + # output module to store extracted files to disk + # + # The files are stored to the log-dir in a format "file.<id>" where <id> is + # an incrementing number starting at 1. For each file "file.<id>" a meta + # file "file.<id>.meta" is created. + # + # File extraction depends on a lot of things to be fully done: + # - stream reassembly depth. For optimal results, set this to 0 (unlimited) + # - http request / response body sizes. Again set to 0 for optimal results. + # - rules that contain the "filestore" keyword. + - file-store: + enabled: no # set to yes to enable + log-dir: files # directory to store the files + force-magic: no # force logging magic on all stored files + force-md5: no # force logging of md5 checksums + #waldo: file.waldo # waldo file to store the file_id across runs + + # output module to log files tracked in a easily parsable json format + - file-log: + enabled: no + filename: files-json.log + append: yes + #filetype: regular # 'regular', 'unix_stream' or 'unix_dgram' + + force-magic: no # force logging magic on all logged files + force-md5: no # force logging of md5 checksums + +# Magic file. The extension .mgc is added to the value here. +#magic-file: /usr/share/file/magic +magic-file: /usr/share/misc/magic.mgc + +# When running in NFQ inline mode, it is possible to use a simulated +# non-terminal NFQUEUE verdict. +# This permit to do send all needed packet to suricata via this a rule: +# iptables -I FORWARD -m mark ! --mark $MARK/$MASK -j NFQUEUE +# And below, you can have your standard filtering ruleset. To activate +# this mode, you need to set mode to 'repeat' +# If you want packet to be sent to another queue after an ACCEPT decision +# set mode to 'route' and set next-queue value. +# On linux >= 3.1, you can set batchcount to a value > 1 to improve performance +# by processing several packets before sending a verdict (worker runmode only). +# On linux >= 3.6, you can set the fail-open option to yes to have the kernel +# accept the packet if suricata is not able to keep pace. +nfq: +# mode: accept +# repeat-mark: 1 +# repeat-mask: 1 +# route-queue: 2 +# batchcount: 20 +# fail-open: yes + +#nflog support +nflog: + # netlink multicast group + # (the same as the iptables --nflog-group param) + # Group 0 is used by the kernel, so you can't use it + - group: 2 + # netlink buffer size + buffer-size: 18432 + # put default value here + - group: default + # set number of packet to queue inside kernel + qthreshold: 1 + # set the delay before flushing packet in the queue inside kernel + qtimeout: 100 + # netlink max buffer size + max-size: 20000 + +# af-packet support +# Set threads to > 1 to use PACKET_FANOUT support +af-packet: + - interface: eth0 + # Number of receive threads (>1 will enable experimental flow pinned + # runmode) + threads: 1 + # Default clusterid. AF_PACKET will load balance packets based on flow. + # All threads/processes that will participate need to have the same + # clusterid. + cluster-id: 99 + # Default AF_PACKET cluster type. AF_PACKET can load balance per flow or per hash. + # This is only supported for Linux kernel > 3.1 + # possible value are: + # * cluster_round_robin: round robin load balancing + # * cluster_flow: all packets of a given flow are send to the same socket + # * cluster_cpu: all packets treated in kernel by a CPU are send to the same socket + cluster-type: cluster_flow + # In some fragmentation case, the hash can not be computed. If "defrag" is set + # to yes, the kernel will do the needed defragmentation before sending the packets. + defrag: yes + # To use the ring feature of AF_PACKET, set 'use-mmap' to yes + use-mmap: yes + # Ring size will be computed with respect to max_pending_packets and number + # of threads. You can set manually the ring size in number of packets by setting + # the following value. If you are using flow cluster-type and have really network + # intensive single-flow you could want to set the ring-size independantly of the number + # of threads: + #ring-size: 2048 + # On busy system, this could help to set it to yes to recover from a packet drop + # phase. This will result in some packets (at max a ring flush) being non treated. + #use-emergency-flush: yes + # recv buffer size, increase value could improve performance + # buffer-size: 32768 + # Set to yes to disable promiscuous mode + # disable-promisc: no + # Choose checksum verification mode for the interface. At the moment + # of the capture, some packets may be with an invalid checksum due to + # offloading to the network card of the checksum computation. + # Possible values are: + # - kernel: use indication sent by kernel for each packet (default) + # - yes: checksum validation is forced + # - no: checksum validation is disabled + # - auto: suricata uses a statistical approach to detect when + # checksum off-loading is used. + # Warning: 'checksum-validation' must be set to yes to have any validation + #checksum-checks: kernel + # BPF filter to apply to this interface. The pcap filter syntax apply here. + #bpf-filter: port 80 or udp + # You can use the following variables to activate AF_PACKET tap od IPS mode. + # If copy-mode is set to ips or tap, the traffic coming to the current + # interface will be copied to the copy-iface interface. If 'tap' is set, the + # copy is complete. If 'ips' is set, the packet matching a 'drop' action + # will not be copied. + #copy-mode: ips + #copy-iface: eth1 + - interface: eth1 + threads: 1 + cluster-id: 98 + cluster-type: cluster_flow + defrag: yes + # buffer-size: 32768 + # disable-promisc: no + # Put default values here + - interface: default + #threads: 2 + #use-mmap: yes + +legacy: + uricontent: enabled + +# You can specify a threshold config file by setting "threshold-file" +# to the path of the threshold config file: +# threshold-file: /etc/suricata/threshold.config + +# The detection engine builds internal groups of signatures. The engine +# allow us to specify the profile to use for them, to manage memory on an +# efficient way keeping a good performance. For the profile keyword you +# can use the words "low", "medium", "high" or "custom". If you use custom +# make sure to define the values at "- custom-values" as your convenience. +# Usually you would prefer medium/high/low. +# +# "sgh mpm-context", indicates how the staging should allot mpm contexts for +# the signature groups. "single" indicates the use of a single context for +# all the signature group heads. "full" indicates a mpm-context for each +# group head. "auto" lets the engine decide the distribution of contexts +# based on the information the engine gathers on the patterns from each +# group head. +# +# The option inspection-recursion-limit is used to limit the recursive calls +# in the content inspection code. For certain payload-sig combinations, we +# might end up taking too much time in the content inspection code. +# If the argument specified is 0, the engine uses an internally defined +# default limit. On not specifying a value, we use no limits on the recursion. +detect-engine: + - profile: medium + - custom-values: + toclient-src-groups: 2 + toclient-dst-groups: 2 + toclient-sp-groups: 2 + toclient-dp-groups: 3 + toserver-src-groups: 2 + toserver-dst-groups: 4 + toserver-sp-groups: 2 + toserver-dp-groups: 25 + - sgh-mpm-context: auto + - inspection-recursion-limit: 3000 + # When rule-reload is enabled, sending a USR2 signal to the Suricata process + # will trigger a live rule reload. Experimental feature, use with care. + #- rule-reload: true + # If set to yes, the loading of signatures will be made after the capture + # is started. This will limit the downtime in IPS mode. + #- delayed-detect: yes + +# Suricata is multi-threaded. Here the threading can be influenced. +threading: + # On some cpu's/architectures it is beneficial to tie individual threads + # to specific CPU's/CPU cores. In this case all threads are tied to CPU0, + # and each extra CPU/core has one "detect" thread. + # + # On Intel Core2 and Nehalem CPU's enabling this will degrade performance. + # + set-cpu-affinity: no + # Tune cpu affinity of suricata threads. Each family of threads can be bound + # on specific CPUs. + cpu-affinity: + - management-cpu-set: + cpu: [ 0 ] # include only these cpus in affinity settings + - receive-cpu-set: + cpu: [ 0 ] # include only these cpus in affinity settings + - decode-cpu-set: + cpu: [ 0, 1 ] + mode: "balanced" + - stream-cpu-set: + cpu: [ "0-1" ] + - detect-cpu-set: + cpu: [ "all" ] + mode: "exclusive" # run detect threads in these cpus + # Use explicitely 3 threads and don't compute number by using + # detect-thread-ratio variable: + # threads: 3 + prio: + low: [ 0 ] + medium: [ "1-2" ] + high: [ 3 ] + default: "medium" + - verdict-cpu-set: + cpu: [ 0 ] + prio: + default: "high" + - reject-cpu-set: + cpu: [ 0 ] + prio: + default: "low" + - output-cpu-set: + cpu: [ "all" ] + prio: + default: "medium" + # + # By default Suricata creates one "detect" thread per available CPU/CPU core. + # This setting allows controlling this behaviour. A ratio setting of 2 will + # create 2 detect threads for each CPU/CPU core. So for a dual core CPU this + # will result in 4 detect threads. If values below 1 are used, less threads + # are created. So on a dual core CPU a setting of 0.5 results in 1 detect + # thread being created. Regardless of the setting at a minimum 1 detect + # thread will always be created. + # + detect-thread-ratio: 1.5 + +# Cuda configuration. +cuda: + # The "mpm" profile. On not specifying any of these parameters, the engine's + # internal default values are used, which are same as the ones specified in + # in the default conf file. + mpm: + # The minimum length required to buffer data to the gpu. + # Anything below this is MPM'ed on the CPU. + # Can be specified in kb, mb, gb. Just a number indicates it's in bytes. + # A value of 0 indicates there's no limit. + data-buffer-size-min-limit: 0 + # The maximum length for data that we would buffer to the gpu. + # Anything over this is MPM'ed on the CPU. + # Can be specified in kb, mb, gb. Just a number indicates it's in bytes. + data-buffer-size-max-limit: 1500 + # The ring buffer size used by the CudaBuffer API to buffer data. + cudabuffer-buffer-size: 500mb + # The max chunk size that can be sent to the gpu in a single go. + gpu-transfer-size: 50mb + # The timeout limit for batching of packets in microseconds. + batching-timeout: 2000 + # The device to use for the mpm. Currently we don't support load balancing + # on multiple gpus. In case you have multiple devices on your system, you + # can specify the device to use, using this conf. By default we hold 0, to + # specify the first device cuda sees. To find out device-id associated with + # the card(s) on the system run "suricata --list-cuda-cards". + device-id: 0 + # No of Cuda streams used for asynchronous processing. All values > 0 are valid. + # For this option you need a device with Compute Capability > 1.0. + cuda-streams: 2 + +# Select the multi pattern algorithm you want to run for scan/search the +# in the engine. The supported algorithms are b2g, b2gc, b2gm, b3g, wumanber, +# ac and ac-gfbs. +# +# The mpm you choose also decides the distribution of mpm contexts for +# signature groups, specified by the conf - "detect-engine.sgh-mpm-context". +# Selecting "ac" as the mpm would require "detect-engine.sgh-mpm-context" +# to be set to "single", because of ac's memory requirements, unless the +# ruleset is small enough to fit in one's memory, in which case one can +# use "full" with "ac". Rest of the mpms can be run in "full" mode. +# +# There is also a CUDA pattern matcher (only available if Suricata was +# compiled with --enable-cuda: b2g_cuda. Make sure to update your +# max-pending-packets setting above as well if you use b2g_cuda. + +mpm-algo: ac + +# The memory settings for hash size of these algorithms can vary from lowest +# (2048) - low (4096) - medium (8192) - high (16384) - higher (32768) - max +# (65536). The bloomfilter sizes of these algorithms can vary from low (512) - +# medium (1024) - high (2048). +# +# For B2g/B3g algorithms, there is a support for two different scan/search +# algorithms. For B2g the scan algorithms are B2gScan & B2gScanBNDMq, and +# search algorithms are B2gSearch & B2gSearchBNDMq. For B3g scan algorithms +# are B3gScan & B3gScanBNDMq, and search algorithms are B3gSearch & +# B3gSearchBNDMq. +# +# For B2g the different scan/search algorithms and, hash and bloom +# filter size settings. For B3g the different scan/search algorithms and, hash +# and bloom filter size settings. For wumanber the hash and bloom filter size +# settings. + +pattern-matcher: + - b2gc: + search-algo: B2gSearchBNDMq + hash-size: low + bf-size: medium + - b2gm: + search-algo: B2gSearchBNDMq + hash-size: low + bf-size: medium + - b2g: + search-algo: B2gSearchBNDMq + hash-size: low + bf-size: medium + - b3g: + search-algo: B3gSearchBNDMq + hash-size: low + bf-size: medium + - wumanber: + hash-size: low + bf-size: medium + +# Defrag settings: + +defrag: + memcap: 32mb + hash-size: 65536 + trackers: 65535 # number of defragmented flows to follow + max-frags: 65535 # number of fragments to keep (higher than trackers) + prealloc: yes + timeout: 60 + +# Enable defrag per host settings +# host-config: +# +# - dmz: +# timeout: 30 +# address: [192.168.1.0/24, 127.0.0.0/8, 1.1.1.0/24, 2.2.2.0/24, "1.1.1.1", "2.2.2.2", "::1"] +# +# - lan: +# timeout: 45 +# address: +# - 192.168.0.0/24 +# - 192.168.10.0/24 +# - 172.16.14.0/24 + +# Flow settings: +# By default, the reserved memory (memcap) for flows is 32MB. This is the limit +# for flow allocation inside the engine. You can change this value to allow +# more memory usage for flows. +# The hash-size determine the size of the hash used to identify flows inside +# the engine, and by default the value is 65536. +# At the startup, the engine can preallocate a number of flows, to get a better +# performance. The number of flows preallocated is 10000 by default. +# emergency-recovery is the percentage of flows that the engine need to +# prune before unsetting the emergency state. The emergency state is activated +# when the memcap limit is reached, allowing to create new flows, but +# prunning them with the emergency timeouts (they are defined below). +# If the memcap is reached, the engine will try to prune flows +# with the default timeouts. If it doens't find a flow to prune, it will set +# the emergency bit and it will try again with more agressive timeouts. +# If that doesn't work, then it will try to kill the last time seen flows +# not in use. +# The memcap can be specified in kb, mb, gb. Just a number indicates it's +# in bytes. + +flow: + memcap: 64mb + hash-size: 65536 + prealloc: 10000 + emergency-recovery: 30 + +# This option controls the use of vlan ids in the flow (and defrag) +# hashing. Normally this should be enabled, but in some (broken) +# setups where both sides of a flow are not tagged with the same vlan +# tag, we can ignore the vlan id's in the flow hashing. +vlan: + use-for-tracking: true + +# Specific timeouts for flows. Here you can specify the timeouts that the +# active flows will wait to transit from the current state to another, on each +# protocol. The value of "new" determine the seconds to wait after a hanshake or +# stream startup before the engine free the data of that flow it doesn't +# change the state to established (usually if we don't receive more packets +# of that flow). The value of "established" is the amount of +# seconds that the engine will wait to free the flow if it spend that amount +# without receiving new packets or closing the connection. "closed" is the +# amount of time to wait after a flow is closed (usually zero). +# +# There's an emergency mode that will become active under attack circumstances, +# making the engine to check flow status faster. This configuration variables +# use the prefix "emergency-" and work similar as the normal ones. +# Some timeouts doesn't apply to all the protocols, like "closed", for udp and +# icmp. + +flow-timeouts: + + default: + new: 30 + established: 300 + closed: 0 + emergency-new: 10 + emergency-established: 100 + emergency-closed: 0 + tcp: + new: 60 + established: 3600 + closed: 120 + emergency-new: 10 + emergency-established: 300 + emergency-closed: 20 + udp: + new: 30 + established: 300 + emergency-new: 10 + emergency-established: 100 + icmp: + new: 30 + established: 300 + emergency-new: 10 + emergency-established: 100 + +# Stream engine settings. Here the TCP stream tracking and reassembly +# engine is configured. +# +# stream: +# memcap: 32mb # Can be specified in kb, mb, gb. Just a +# # number indicates it's in bytes. +# checksum-validation: yes # To validate the checksum of received +# # packet. If csum validation is specified as +# # "yes", then packet with invalid csum will not +# # be processed by the engine stream/app layer. +# # Warning: locally generated trafic can be +# # generated without checksum due to hardware offload +# # of checksum. You can control the handling of checksum +# # on a per-interface basis via the 'checksum-checks' +# # option +# prealloc-sessions: 2k # 2k sessions prealloc'd per stream thread +# midstream: false # don't allow midstream session pickups +# async-oneside: false # don't enable async stream handling +# inline: no # stream inline mode +# max-synack-queued: 5 # Max different SYN/ACKs to queue +# +# reassembly: +# memcap: 64mb # Can be specified in kb, mb, gb. Just a number +# # indicates it's in bytes. +# depth: 1mb # Can be specified in kb, mb, gb. Just a number +# # indicates it's in bytes. +# toserver-chunk-size: 2560 # inspect raw stream in chunks of at least +# # this size. Can be specified in kb, mb, +# # gb. Just a number indicates it's in bytes. +# # The max acceptable size is 4024 bytes. +# toclient-chunk-size: 2560 # inspect raw stream in chunks of at least +# # this size. Can be specified in kb, mb, +# # gb. Just a number indicates it's in bytes. +# # The max acceptable size is 4024 bytes. +# randomize-chunk-size: yes # Take a random value for chunk size around the specified value. +# # This lower the risk of some evasion technics but could lead +# # detection change between runs. It is set to 'yes' by default. +# randomize-chunk-range: 10 # If randomize-chunk-size is active, the value of chunk-size is +# # a random value between (1 - randomize-chunk-range/100)*randomize-chunk-size +# # and (1 + randomize-chunk-range/100)*randomize-chunk-size. Default value +# # of randomize-chunk-range is 10. +# +# raw: yes # 'Raw' reassembly enabled or disabled. +# # raw is for content inspection by detection +# # engine. +# +# chunk-prealloc: 250 # Number of preallocated stream chunks. These +# # are used during stream inspection (raw). +# segments: # Settings for reassembly segment pool. +# - size: 4 # Size of the (data)segment for a pool +# prealloc: 256 # Number of segments to prealloc and keep +# # in the pool. +# +stream: + memcap: 32mb + checksum-validation: yes # reject wrong csums + inline: auto # auto will use inline mode in IPS mode, yes or no set it statically + reassembly: + memcap: 128mb + depth: 1mb # reassemble 1mb into a stream + toserver-chunk-size: 2560 + toclient-chunk-size: 2560 + randomize-chunk-size: yes + #randomize-chunk-range: 10 + #raw: yes + #chunk-prealloc: 250 + #segments: + # - size: 4 + # prealloc: 256 + # - size: 16 + # prealloc: 512 + # - size: 112 + # prealloc: 512 + # - size: 248 + # prealloc: 512 + # - size: 512 + # prealloc: 512 + # - size: 768 + # prealloc: 1024 + # - size: 1448 + # prealloc: 1024 + # - size: 65535 + # prealloc: 128 + +# Host table: +# +# Host table is used by tagging and per host thresholding subsystems. +# +host: + hash-size: 4096 + prealloc: 1000 + memcap: 16777216 + +# Logging configuration. This is not about logging IDS alerts, but +# IDS output about what its doing, errors, etc. +logging: + + # The default log level, can be overridden in an output section. + # Note that debug level logging will only be emitted if Suricata was + # compiled with the --enable-debug configure option. + # + # This value is overriden by the SC_LOG_LEVEL env var. + default-log-level: notice + + # The default output format. Optional parameter, should default to + # something reasonable if not provided. Can be overriden in an + # output section. You can leave this out to get the default. + # + # This value is overriden by the SC_LOG_FORMAT env var. + #default-log-format: "[%i] %t - (%f:%l) <%d> (%n) -- " + + # A regex to filter output. Can be overridden in an output section. + # Defaults to empty (no filter). + # + # This value is overriden by the SC_LOG_OP_FILTER env var. + default-output-filter: + + # Define your logging outputs. If none are defined, or they are all + # disabled you will get the default - console output. + outputs: + - console: + enabled: yes + - file: + enabled: no + filename: /var/log/suricata.log + - syslog: + enabled: no + facility: local5 + format: "[%i] <%d> -- " + +# Tilera mpipe configuration. for use on Tilera TILE-Gx. +mpipe: + + # Load balancing modes: "static", "dynamic", "sticky", or "round-robin". + load-balance: dynamic + + # Number of Packets in each ingress packet queue. Must be 128, 512, 2028 or 65536 + iqueue-packets: 2048 + + # List of interfaces we will listen on. + inputs: + - interface: xgbe2 + - interface: xgbe3 + - interface: xgbe4 + + + # Relative weight of memory for packets of each mPipe buffer size. + stack: + size128: 0 + size256: 9 + size512: 0 + size1024: 0 + size1664: 7 + size4096: 0 + size10386: 0 + size16384: 0 + +# PF_RING configuration. for use with native PF_RING support +# for more info see http://www.ntop.org/PF_RING.html +pfring: + - interface: eth0 + # Number of receive threads (>1 will enable experimental flow pinned + # runmode) + threads: 1 + + # Default clusterid. PF_RING will load balance packets based on flow. + # All threads/processes that will participate need to have the same + # clusterid. + cluster-id: 99 + + # Default PF_RING cluster type. PF_RING can load balance per flow or per hash. + # This is only supported in versions of PF_RING > 4.1.1. + cluster-type: cluster_flow + # bpf filter for this interface + #bpf-filter: tcp + # Choose checksum verification mode for the interface. At the moment + # of the capture, some packets may be with an invalid checksum due to + # offloading to the network card of the checksum computation. + # Possible values are: + # - rxonly: only compute checksum for packets received by network card. + # - yes: checksum validation is forced + # - no: checksum validation is disabled + # - auto: suricata uses a statistical approach to detect when + # checksum off-loading is used. (default) + # Warning: 'checksum-validation' must be set to yes to have any validation + #checksum-checks: auto + # Second interface + #- interface: eth1 + # threads: 3 + # cluster-id: 93 + # cluster-type: cluster_flow + # Put default values here + - interface: default + #threads: 2 + +pcap: + - interface: eth0 + # On Linux, pcap will try to use mmaped capture and will use buffer-size + # as total of memory used by the ring. So set this to something bigger + # than 1% of your bandwidth. + #buffer-size: 16777216 + #bpf-filter: "tcp and port 25" + # Choose checksum verification mode for the interface. At the moment + # of the capture, some packets may be with an invalid checksum due to + # offloading to the network card of the checksum computation. + # Possible values are: + # - yes: checksum validation is forced + # - no: checksum validation is disabled + # - auto: suricata uses a statistical approach to detect when + # checksum off-loading is used. (default) + # Warning: 'checksum-validation' must be set to yes to have any validation + #checksum-checks: auto + # With some accelerator cards using a modified libpcap (like myricom), you + # may want to have the same number of capture threads as the number of capture + # rings. In this case, set up the threads variable to N to start N threads + # listening on the same interface. + #threads: 16 + # set to no to disable promiscuous mode: + #promisc: no + # set snaplen, if not set it defaults to MTU if MTU can be known + # via ioctl call and to full capture if not. + #snaplen: 1518 + # Put default values here + - interface: default + #checksum-checks: auto + +pcap-file: + # Possible values are: + # - yes: checksum validation is forced + # - no: checksum validation is disabled + # - auto: suricata uses a statistical approach to detect when + # checksum off-loading is used. (default) + # Warning: 'checksum-validation' must be set to yes to have checksum tested + checksum-checks: auto + +# For FreeBSD ipfw(8) divert(4) support. +# Please make sure you have ipfw_load="YES" and ipdivert_load="YES" +# in /etc/loader.conf or kldload'ing the appropriate kernel modules. +# Additionally, you need to have an ipfw rule for the engine to see +# the packets from ipfw. For Example: +# +# ipfw add 100 divert 8000 ip from any to any +# +# The 8000 above should be the same number you passed on the command +# line, i.e. -d 8000 +# +ipfw: + + # Reinject packets at the specified ipfw rule number. This config + # option is the ipfw rule number AT WHICH rule processing continues + # in the ipfw processing system after the engine has finished + # inspecting the packet for acceptance. If no rule number is specified, + # accepted packets are reinjected at the divert rule which they entered + # and IPFW rule processing continues. No check is done to verify + # this will rule makes sense so care must be taken to avoid loops in ipfw. + # + ## The following example tells the engine to reinject packets + # back into the ipfw firewall AT rule number 5500: + # + # ipfw-reinjection-rule-number: 5500 + +# Set the default rule path here to search for the files. +# if not set, it will look at the current working dir +default-rule-path: /etc/suricata/rules +rule-files: + - botcc.rules + - ciarmy.rules + - compromised.rules + - drop.rules + - dshield.rules + - emerging-activex.rules + - emerging-attack_response.rules + - emerging-chat.rules + - emerging-current_events.rules + - emerging-dns.rules + - emerging-dos.rules + - emerging-exploit.rules + - emerging-ftp.rules + - emerging-games.rules + - emerging-icmp_info.rules +# - emerging-icmp.rules + - emerging-imap.rules + - emerging-inappropriate.rules + - emerging-malware.rules + - emerging-misc.rules + - emerging-mobile_malware.rules + - emerging-netbios.rules + - emerging-p2p.rules + - emerging-policy.rules + - emerging-pop3.rules + - emerging-rpc.rules + - emerging-scada.rules + - emerging-scan.rules + - emerging-shellcode.rules + - emerging-smtp.rules + - emerging-snmp.rules + - emerging-sql.rules + - emerging-telnet.rules + - emerging-tftp.rules + - emerging-trojan.rules + - emerging-user_agents.rules + - emerging-voip.rules + - emerging-web_client.rules + - emerging-web_server.rules + - emerging-web_specific_apps.rules + - emerging-worm.rules + - tor.rules + - decoder-events.rules # available in suricata sources under rules dir + - stream-events.rules # available in suricata sources under rules dir + - http-events.rules # available in suricata sources under rules dir + - smtp-events.rules # available in suricata sources under rules dir + - dns-events.rules # available in suricata sources under rules dir + - tls-events.rules # available in suricata sources under rules dir + +classification-file: /etc/suricata/classification.config +reference-config-file: /etc/suricata/reference.config + +# Holds variables that would be used by the engine. +vars: + + # Holds the address group vars that would be passed in a Signature. + # These would be retrieved during the Signature address parsing stage. + address-groups: + + HOME_NET: "[192.168.0.0/16,10.0.0.0/8,172.16.0.0/12]" + + EXTERNAL_NET: "!$HOME_NET" + + HTTP_SERVERS: "$HOME_NET" + + SMTP_SERVERS: "$HOME_NET" + + SQL_SERVERS: "$HOME_NET" + + DNS_SERVERS: "$HOME_NET" + + TELNET_SERVERS: "$HOME_NET" + + AIM_SERVERS: "$EXTERNAL_NET" + + DNP3_SERVER: "$HOME_NET" + + DNP3_CLIENT: "$HOME_NET" + + MODBUS_CLIENT: "$HOME_NET" + + MODBUS_SERVER: "$HOME_NET" + + ENIP_CLIENT: "$HOME_NET" + + ENIP_SERVER: "$HOME_NET" + + # Holds the port group vars that would be passed in a Signature. + # These would be retrieved during the Signature port parsing stage. + port-groups: + + HTTP_PORTS: "80" + + SHELLCODE_PORTS: "!80" + + ORACLE_PORTS: 1521 + + SSH_PORTS: 22 + + DNP3_PORTS: 20000 + +# Set the order of alerts bassed on actions +# The default order is pass, drop, reject, alert +action-order: + - pass + - drop + - reject + - alert + +# IP Reputation +#reputation-categories-file: /etc/suricata/iprep/categories.txt +#default-reputation-path: /etc/suricata/iprep +#reputation-files: +# - reputation.list + +# Host specific policies for defragmentation and TCP stream +# reassembly. The host OS lookup is done using a radix tree, just +# like a routing table so the most specific entry matches. +host-os-policy: + # Make the default policy windows. + windows: [0.0.0.0/0] + bsd: [] + bsd-right: [] + old-linux: [] + linux: [10.0.0.0/8, 192.168.1.100, "8762:2352:6241:7245:E000:0000:0000:0000"] + old-solaris: [] + solaris: ["::1"] + hpux10: [] + hpux11: [] + irix: [] + macos: [] + vista: [] + windows2k3: [] + + +# Limit for the maximum number of asn1 frames to decode (default 256) +asn1-max-frames: 256 + +# When run with the option --engine-analysis, the engine will read each of +# the parameters below, and print reports for each of the enabled sections +# and exit. The reports are printed to a file in the default log dir +# given by the parameter "default-log-dir", with engine reporting +# subsection below printing reports in its own report file. +engine-analysis: + # enables printing reports for fast-pattern for every rule. + rules-fast-pattern: yes + # enables printing reports for each rule + rules: yes + +#recursion and match limits for PCRE where supported +pcre: + match-limit: 3500 + match-limit-recursion: 1500 + +# Holds details on the app-layer. The protocols section details each protocol. +# Under each protocol, the default value for detection-enabled and " +# parsed-enabled is yes, unless specified otherwise. +# Each protocol covers enabling/disabling parsers for all ipprotos +# the app-layer protocol runs on. For example "dcerpc" refers to the tcp +# version of the protocol as well as the udp version of the protocol. +# The option "enabled" takes 3 values - "yes", "no", "detection-only". +# "yes" enables both detection and the parser, "no" disables both, and +# "detection-only" enables detection only(parser disabled). +app-layer: + protocols: + tls: + enabled: yes + detection-ports: + dp: 443 + + #no-reassemble: yes + dcerpc: + enabled: yes + ftp: + enabled: yes + ssh: + enabled: yes + smtp: + enabled: yes + imap: + enabled: detection-only + msn: + enabled: detection-only + smb: + enabled: yes + detection-ports: + dp: 139 + # smb2 detection is disabled internally inside the engine. + #smb2: + # enabled: yes + dns: + # memcaps. Globally and per flow/state. + #global-memcap: 16mb + #state-memcap: 512kb + + # How many unreplied DNS requests are considered a flood. + # If the limit is reached, app-layer-event:dns.flooded; will match. + #request-flood: 500 + + tcp: + enabled: yes + detection-ports: + dp: 53 + udp: + enabled: yes + detection-ports: + dp: 53 + http: + enabled: yes + # memcap: 64mb + + ########################################################################### + # Configure libhtp. + # + # + # default-config: Used when no server-config matches + # personality: List of personalities used by default + # request-body-limit: Limit reassembly of request body for inspection + # by http_client_body & pcre /P option. + # response-body-limit: Limit reassembly of response body for inspection + # by file_data, http_server_body & pcre /Q option. + # double-decode-path: Double decode path section of the URI + # double-decode-query: Double decode query section of the URI + # + # server-config: List of server configurations to use if address matches + # address: List of ip addresses or networks for this block + # personalitiy: List of personalities used by this block + # request-body-limit: Limit reassembly of request body for inspection + # by http_client_body & pcre /P option. + # response-body-limit: Limit reassembly of response body for inspection + # by file_data, http_server_body & pcre /Q option. + # double-decode-path: Double decode path section of the URI + # double-decode-query: Double decode query section of the URI + # + # uri-include-all: Include all parts of the URI. By default the + # 'scheme', username/password, hostname and port + # are excluded. Setting this option to true adds + # all of them to the normalized uri as inspected + # by http_uri, urilen, pcre with /U and the other + # keywords that inspect the normalized uri. + # Note that this does not affect http_raw_uri. + # Also, note that including all was the default in + # 1.4 and 2.0beta1. + # + # meta-field-limit: Hard size limit for request and response size + # limits. Applies to request line and headers, + # response line and headers. Does not apply to + # request or response bodies. Default is 18k. + # If this limit is reached an event is raised. + # + # Currently Available Personalities: + # Minimal + # Generic + # IDS (default) + # IIS_4_0 + # IIS_5_0 + # IIS_5_1 + # IIS_6_0 + # IIS_7_0 + # IIS_7_5 + # Apache_2 + ########################################################################### + libhtp: + + default-config: + personality: IDS + + # Can be specified in kb, mb, gb. Just a number indicates + # it's in bytes. + request-body-limit: 3072 + response-body-limit: 3072 + + # inspection limits + request-body-minimal-inspect-size: 32kb + request-body-inspect-window: 4kb + response-body-minimal-inspect-size: 32kb + response-body-inspect-window: 4kb + # Take a random value for inspection sizes around the specified value. + # This lower the risk of some evasion technics but could lead + # detection change between runs. It is set to 'yes' by default. + #randomize-inspection-sizes: yes + # If randomize-inspection-sizes is active, the value of various + # inspection size will be choosen in the [1 - range%, 1 + range%] + # range + # Default value of randomize-inspection-range is 10. + #randomize-inspection-range: 10 + + # decoding + double-decode-path: no + double-decode-query: no + + server-config: + + #- apache: + # address: [192.168.1.0/24, 127.0.0.0/8, "::1"] + # personality: Apache_2 + # # Can be specified in kb, mb, gb. Just a number indicates + # # it's in bytes. + # request-body-limit: 4096 + # response-body-limit: 4096 + # double-decode-path: no + # double-decode-query: no + + #- iis7: + # address: + # - 192.168.0.0/24 + # - 192.168.10.0/24 + # personality: IIS_7_0 + # # Can be specified in kb, mb, gb. Just a number indicates + # # it's in bytes. + # request-body-limit: 4096 + # response-body-limit: 4096 + # double-decode-path: no + # double-decode-query: no + +# Profiling settings. Only effective if Suricata has been built with the +# the --enable-profiling configure flag. +# +profiling: + # Run profiling for every xth packet. The default is 1, which means we + # profile every packet. If set to 1000, one packet is profiled for every + # 1000 received. + #sample-rate: 1000 + + # rule profiling + rules: + + # Profiling can be disabled here, but it will still have a + # performance impact if compiled in. + enabled: yes + filename: rule_perf.log + append: yes + + # Sort options: ticks, avgticks, checks, matches, maxticks + sort: avgticks + + # Limit the number of items printed at exit. + limit: 100 + + # per keyword profiling + keywords: + enabled: yes + filename: keyword_perf.log + append: yes + + # packet profiling + packets: + + # Profiling can be disabled here, but it will still have a + # performance impact if compiled in. + enabled: yes + filename: packet_stats.log + append: yes + + # per packet csv output + csv: + + # Output can be disabled here, but it will still have a + # performance impact if compiled in. + enabled: no + filename: packet_stats.csv + + # profiling of locking. Only available when Suricata was built with + # --enable-profiling-locks. + locks: + enabled: no + filename: lock_stats.log + append: yes + +# Suricata core dump configuration. Limits the size of the core dump file to +# approximately max-dump. The actual core dump size will be a multiple of the +# page size. Core dumps that would be larger than max-dump are truncated. On +# Linux, the actual core dump size may be a few pages larger than max-dump. +# Setting max-dump to 0 disables core dumping. +# Setting max-dump to 'unlimited' will give the full core dump file. +# On 32-bit Linux, a max-dump value >= ULONG_MAX may cause the core dump size +# to be 'unlimited'. + +coredump: + max-dump: unlimited + +napatech: + # The Host Buffer Allowance for all streams + # (-1 = OFF, 1 - 100 = percentage of the host buffer that can be held back) + hba: -1 + + # use_all_streams set to "yes" will query the Napatech service for all configured + # streams and listen on all of them. When set to "no" the streams config array + # will be used. + use-all-streams: yes + + # The streams to listen on + streams: [1, 2, 3] + +# Includes. Files included here will be handled as if they were +# inlined in this configuration file. +#include: include1.yaml +#include: include2.yaml diff --git a/meta-security/recipes-security/suricata/files/volatiles.03_suricata b/meta-security/recipes-security/suricata/files/volatiles.03_suricata new file mode 100644 index 000000000..4627bd3b0 --- /dev/null +++ b/meta-security/recipes-security/suricata/files/volatiles.03_suricata @@ -0,0 +1,2 @@ +# <type> <owner> <group> <mode> <path> <linksource> +d root root 0755 /var/log/suricata none diff --git a/meta-security/recipes-security/suricata/libhtp_0.5.25.bb b/meta-security/recipes-security/suricata/libhtp_0.5.25.bb new file mode 100644 index 000000000..8305f7010 --- /dev/null +++ b/meta-security/recipes-security/suricata/libhtp_0.5.25.bb @@ -0,0 +1,15 @@ +SUMMARY = "LibHTP is a security-aware parser for the HTTP protocol and the related bits and pieces." + +require suricata.inc + +LIC_FILES_CHKSUM = "file://../LICENSE;beginline=1;endline=2;md5=c70d8d3310941dcdfcd1e02800a1f548" + +DEPENDS = "zlib" + +inherit autotools pkgconfig + +CFLAGS += "-D_DEFAULT_SOURCE" + +S = "${WORKDIR}/suricata-${VER}/${BPN}" + +RDEPENDS_${PN} += "zlib" diff --git a/meta-security/recipes-security/suricata/suricata.inc b/meta-security/recipes-security/suricata/suricata.inc new file mode 100644 index 000000000..a2d36eb61 --- /dev/null +++ b/meta-security/recipes-security/suricata/suricata.inc @@ -0,0 +1,9 @@ +HOMEPAGE = "http://suricata-ids.org/" +SECTION = "security Monitor/Admin" +LICENSE = "GPLv2" + +VER = "4.0.0" +SRC_URI = "http://www.openinfosecfoundation.org/download/suricata-${VER}.tar.gz" + +SRC_URI[md5sum] = "41fb91b4cbc6705b353e4bdd02c3df4b" +SRC_URI[sha256sum] = "6b8b183a8409829ca92c71854cc1abed45f04ccfb7f14c08211f4edf571fa577" diff --git a/meta-security/recipes-security/suricata/suricata_4.0.0.bb b/meta-security/recipes-security/suricata/suricata_4.0.0.bb new file mode 100644 index 000000000..e16348670 --- /dev/null +++ b/meta-security/recipes-security/suricata/suricata_4.0.0.bb @@ -0,0 +1,60 @@ +SUMMARY = "The Suricata Engine is an Open Source Next Generation Intrusion Detection and Prevention Engine" + +require suricata.inc + +LIC_FILES_CHKSUM = "file://LICENSE;beginline=1;endline=2;md5=c70d8d3310941dcdfcd1e02800a1f548" + +SRC_URI += " \ + file://volatiles.03_suricata \ + file://suricata.yaml \ + " + +inherit autotools-brokensep pkgconfig python-dir + +CFLAGS += "-D_DEFAULT_SOURCE" + +CACHED_CONFIGUREVARS = "ac_cv_header_htp_htp_h=yes ac_cv_lib_htp_htp_conn_create=yes " + +EXTRA_OECONF += " --disable-debug \ + --enable-non-bundled-htp \ + --disable-gccmarch-native \ + " + +PACKAGECONFIG ??= "htp jansson file pcre yaml pcap cap-ng net nfnetlink nss nspr" +PACKAGECONFIG[htp] = "--with-libhtp-includes=${STAGING_INCDIR} --with-libhtp-libraries=${STAGING_LIBDIR}, ,libhtp," +PACKAGECONFIG[pcre] = "--with-libpcre-includes=${STAGING_INCDIR} --with-libpcre-libraries=${STAGING_LIBDIR}, ,libpcre ," +PACKAGECONFIG[yaml] = "--with-libyaml-includes=${STAGING_INCDIR} --with-libyaml-libraries=${STAGING_LIBDIR}, ,libyaml ," +PACKAGECONFIG[pcap] = "--with-libpcap-includes=${STAGING_INCDIR} --with-libpcap-libraries=${STAGING_LIBDIR}, ,libpcap ," +PACKAGECONFIG[cap-ng] = "--with-libcap_ng-includes=${STAGING_INCDIR} --with-libcap_ng-libraries=${STAGING_LIBDIR}, ,libcap-ng , " +PACKAGECONFIG[net] = "--with-libnet-includes=${STAGING_INCDIR} --with-libnet-libraries=${STAGING_LIBDIR}, , libnet," +PACKAGECONFIG[nfnetlink] = "--with-libnfnetlink-includes=${STAGING_INCDIR} --with-libnfnetlink-libraries=${STAGING_LIBDIR}, ,libnfnetlink ," + +PACKAGECONFIG[jansson] = "--with-libjansson-includes=${STAGING_INCDIR} --with-libjansson-libraries=${STAGING_LIBDIR},,jansson, jansson" +PACKAGECONFIG[file] = ",,file, file" +PACKAGECONFIG[nss] = "--with-libnss-includes=${STAGING_INCDIR} --with-libnss-libraries=${STAGING_LIBDIR}, nss, nss," +PACKAGECONFIG[nspr] = "--with-libnspr-includes=${STAGING_INCDIR} --with-libnspr-libraries=${STAGING_LIBDIR}, nspr, nspr," +PACKAGECONFIG[python] = "--enable-python, --disable-python, python, python" + +export logdir = "${localstatedir}/log" + +do_install_append () { + install -d ${D}${sysconfdir}/suricata + install -d ${D}${sysconfdir}/suricata ${D}${sysconfdir}/default/volatiles + install -m 644 classification.config ${D}${sysconfdir}/suricata + install -m 644 reference.config ${D}${sysconfdir}/suricata + install -m 644 ${WORKDIR}/suricata.yaml ${D}${sysconfdir}/suricata + install -m 0644 ${WORKDIR}/volatiles.03_suricata ${D}${sysconfdir}/default/volatiles/volatiles.03_suricata +} + +pkg_postinst_ontarget_${PN} () { +if [ -e /etc/init.d/populate-volatile.sh ] ; then + ${sysconfdir}/init.d/populate-volatile.sh update +fi + ${bindir}/suricata -c ${sysconfdir}/suricata.yaml -i eth0 +} + +PACKAGES += "${PN}-python" +FILES_${PN} = "${bindir}/suricata ${sysconfdir}/default ${sysconfdir}/suricata ${logdir}/suricata" +FILES_${PN}-python = "${bindir}/suricatasc ${PYTHON_SITEPACKAGES_DIR}" + +RDEPENDS_${PN}-python = "python" diff --git a/meta-security/recipes-security/tripwire/files/add_armeb_arch.patch b/meta-security/recipes-security/tripwire/files/add_armeb_arch.patch new file mode 100644 index 000000000..2379d6654 --- /dev/null +++ b/meta-security/recipes-security/tripwire/files/add_armeb_arch.patch @@ -0,0 +1,18 @@ +tripwire: Add armeb support + +Upstream-Status: Submitted to tripwire-dev + +Signed-off-by: Armin Kuster <akuster@mvista.com> + +diff -Naurp tripwire-2.4.2.2-src_org/config.sub tripwire-2.4.2.2-src/config.sub +--- tripwire-2.4.2.2-src_org/config.sub 2015-07-20 15:03:04.161452573 +0530 ++++ tripwire-2.4.2.2-src/config.sub 2015-07-20 15:06:07.077673139 +0530 +@@ -268,7 +268,7 @@ case $basic_machine in + # FIXME: clean up the formatting here. + vax-* | tahoe-* | i*86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \ + | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | c[123]* | aarch64-* | aarch64be-* \ +- | arm-* | armbe-* | armle-* | armv*-* | strongarm-* | xscale-* \ ++ | arm-* | armeb-* | armbe-* | armle-* | armv*-* | strongarm-* | xscale-* \ + | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ + | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \ + | xmp-* | ymp-* \ diff --git a/meta-security/recipes-security/tripwire/files/tripwire.cron b/meta-security/recipes-security/tripwire/files/tripwire.cron new file mode 100644 index 000000000..2035508d7 --- /dev/null +++ b/meta-security/recipes-security/tripwire/files/tripwire.cron @@ -0,0 +1,8 @@ +#!/bin/sh +HOST_NAME=`uname -n` +if [ ! -e /var/lib/tripwire/${HOST_NAME}.twd ] ; then + echo "**** Error: Tripwire database for ${HOST_NAME} not found. ****" + echo "**** Run "/etc/tripwire/twinstall.sh" and/or "tripwire --init". ****" +else + test -f /etc/tripwire/tw.cfg && /usr/sbin/tripwire --check +fi diff --git a/meta-security/recipes-security/tripwire/files/tripwire.sh b/meta-security/recipes-security/tripwire/files/tripwire.sh new file mode 100644 index 000000000..4276d10eb --- /dev/null +++ b/meta-security/recipes-security/tripwire/files/tripwire.sh @@ -0,0 +1,9 @@ +#!/bin/sh +HOST_NAME=`uname -n` +if [ ! -e /var/lib/tripwire/${HOST_NAME}.twd ] ; then + echo "**** WARNING: Tripwire database for ${HOST_NAME} not found. ****" + echo "**** Run "/etc/tripwire/twinstall.sh" and/or "tripwire --init". ****" + # Note: /etc/tripwire/twinstall.sh creates and initializes tripwire + # database (i.e tripwire --init). + # Example: . /etc/tripwire/twinstall.sh 2> /dev/null +fi diff --git a/meta-security/recipes-security/tripwire/files/tripwire.txt b/meta-security/recipes-security/tripwire/files/tripwire.txt new file mode 100644 index 000000000..332d00420 --- /dev/null +++ b/meta-security/recipes-security/tripwire/files/tripwire.txt @@ -0,0 +1,69 @@ +Post-Installation Instructions +1. Run the configuration script: /etc/tripwire/twinstall.sh to sign these files. This script walks you through the processes of setting passphrases and signing the Tripwire policy and configuration files. +Note: Once encoded and signed, the configuration file should not be renamed or moved. +2. Initialize the Tripwire database file. (/usr/sbin/tripwire--init) +3. Run the first integrity check. (/usr/sbin/tripwire--check) +4. Edit the configuration file (twcfg.txt) with a text editor, if desired. +5. Edit the policy file (twpol.txt) with a text editor, if desired. + +Note: If you plan to modify the policy file, we recommend you do so before running the configuration script. If you modify the policy file after running the configuration script, you must re-run the configuration file before initializing the database file. + +Modifying the Policy File +You can specify how Tripwire software checks your system in the Tripwire policy file (twpol.txt). A default policy file is included in the Tripwire software installation. We recommend you tailor this policy file to fit your particular system. Tailoring the policy file greatly increases Tripwire software's ability to ensure the integrity of your system. + +Locate the default policy file at /etc/tripwire/twpol.txt. An example policy file (located at /usr/doc/tripwire-VER#-REL#/policyguide.txt) is included to help you learn the policy language. Read the sample policy file and the comments in the sample policy file to learn the policy language. + +After you modify the policy file, follow the Post-Installation Instructions (run the configuration script). This script signs the modified policy file and renames it to tw.pol. This is the active policy file that runs as part of the Tripwire software. + +Selecting Passphrases +Tripwire files are signed or encrypted using site or local keys. These keys are protected by passphrases. When selecting passphrases, the following recommendations apply: +Use at least eight alphanumeric and symbolic characters for each passphrase. The maximum length of a passphrase is 1023 characters. Quotes should not be used as passphrase characters. + +Assign a unique passphrase for the site key. The site key passphrase protects the site key, which is used to sign Tripwire software configuration and policy files. Assign a unique passphrase for the local key. The local key signs Tripwire database files. The local key may sign the Tripwire report files also. + +Store the passphrases in a secure location. There is no way to remove encryption from a signed file if you forget your passphrase. If you forget the passphrases, the files are unusable. In that case you must reinitialize the baseline database. + +Initializing the Database +In Database Initialization mode, Tripwire software builds a database of filesystem objects based on the rules in the policy file. This database serves as the baseline for integrity checks. The syntax for Database Initialization mode is: +tripwire --init + +Running an Integrity Check +The Integrity Check mode compares the current file system objects with their properties recorded in the Tripwire database. Violations are printed to stdout. The report file is saved and can later be accessed by twprint. An email option enables you to send email. The syntax for Integrity Check mode is: +tripwire --check + +Printing Reports - twprint Print Report Mode +The twprint --print-report mode prints the contents of a Tripwire report. If you do not specify a report with the --twrfile or -r command-line argument, the default report file specified by the configuration file REPORTFILE variable is used. +Example: On a machine named LIGHTHOUSE, the command would be: +./twprint -m r --twrfile LIGHTHOUSE-19990622-021212.twr + +Updating the Database after an Integrity Check +Database Update mode enables you to update the Tripwire database after an integrity check if you determine that the violations discovered are valid. This update process saves time by enabling you to update the database without having to re-initialize it. It also enables selective updating, which cannot be done through re-initialization. The syntax for Database Update mode is: +tripwire --update + +Updating the Policy File +Change the way that Tripwire software scans the system by changing the rules in the policy file. You can then update the database without a complete re-initialization. This saves a significant amount of time and preserves security by keeping the policy file synchronized with the database it uses. The syntax for Policy Update mode is: +tripwire --update-policy + +Testing email functions +Test mode tests the software's email notification system, using the settings currently specified in the configuration file. The syntax for Email Test Reporting mode is: +tripwire --test + +Tripwire Components +The policy file begins as a text file containing comments, rules, directives, and variables. These dictate the way Tripwire software checks your system. Each rule in the policy file specifies a system object to be monitored. Rules also describe which changes to the object to report, and which to ignore. + +System objects are the files and directories you wish to monitor. Each object is identified by an object name. A property refers to a single characteristic of an object that Tripwire software can monitor. Directives control conditional processing of sets of rules in a policy file. During installation, the text policy file is encrypted and renamed, and becomes the active policy file. + +The database file is an important component of Tripwire software. When first installed, Tripwire software uses the policy file rules to create the database file. The database file is a baseline "snapshot" of the system in a known secure state. Tripwire software compares this baseline against the current system to determine what changes have occurred. This is an integrity check. + +When you perform an integrity check, Tripwire software produces report files. Report files summarize any changes that violated the policy file rules during the integrity check. You can view the report file in a variety of formats, at varying levels of detail. + +The Tripwire configuration file stores system-specific information, such as the location of Tripwire data files. Tripwire software generates some of the configuration file information during installation. The system administrator can change parameters in the configuration file at any time. The configuration file variables POLFILE, DBFILE, REPORTFILE, SITEKEYFILE, and LOCALKEYFILE specify where the policy file, database file, report files, and site and local key files reside. These variables must be defined or the configuration file is invalid. If any of these variables are undefined, an error occurs on execution of Tripwire software and the program exits. + +Tripwire Help +All Tripwire commands support the help arguments. Example: To get help with Create Configuration File mode, type: ./twadmin --help --create-cfgfile + +-? Display usage and version information +--help Display all command modes +--help all Display help for all command modes +--help [mode] Display help for current command mode +--version Display version information diff --git a/meta-security/recipes-security/tripwire/files/twcfg.txt b/meta-security/recipes-security/tripwire/files/twcfg.txt new file mode 100644 index 000000000..224e9201e --- /dev/null +++ b/meta-security/recipes-security/tripwire/files/twcfg.txt @@ -0,0 +1,15 @@ +ROOT =/usr/sbin +POLFILE =/etc/tripwire/tw.pol +DBFILE =/var/lib/tripwire/$(HOSTNAME).twd +REPORTFILE =/var/lib/tripwire/report/$(HOSTNAME)-$(DATE).twr +SITEKEYFILE =/etc/tripwire/site.key +LOCALKEYFILE =/etc/tripwire/$(HOSTNAME)-local.key +EDITOR =/usr/bin/nano +LATEPROMPTING =false +LOOSEDIRECTORYCHECKING =false +MAILNOVIOLATIONS =true +EMAILREPORTLEVEL =3 +REPORTLEVEL =3 +MAILMETHOD =SENDMAIL +SYSLOGREPORTING =false +MAILPROGRAM =/usr/lib/sendmail -t diff --git a/meta-security/recipes-security/tripwire/files/twinstall.sh b/meta-security/recipes-security/tripwire/files/twinstall.sh new file mode 100644 index 000000000..7d1b63fe5 --- /dev/null +++ b/meta-security/recipes-security/tripwire/files/twinstall.sh @@ -0,0 +1,320 @@ +#!/bin/sh + +######################################################################## +######################################################################## +## +## Tripwire(R) 2.3 for LINUX(R) Post-RPM installation script +## +## Copyleft information contained in footer +## +######################################################################## +######################################################################## + +##======================================================= +## Setup +##======================================================= + +# We can assume all the correct tools are in place because the +# RPM installed, didn't it? + +##------------------------------------------------------- +## Set HOST_NAME variable +##------------------------------------------------------- +HOST_NAME='localhost' +if uname -n > /dev/null 2> /dev/null ; then + HOST_NAME=`uname -n` +fi + +##------------------------------------------------------- +## Program variables - edited by RPM during initial install +##------------------------------------------------------- + +# Site Passphrase variable +TW_SITE_PASS="tripwire" + +# Complete path to site key +SITE_KEY="/etc/tripwire/site.key" + +# Local Passphrase variable +TW_LOCAL_PASS="tripwire" + +# Complete path to local key +LOCAL_KEY="/etc/tripwire/${HOST_NAME}-local.key" + +# If clobber==true, overwrite files; if false, do not overwrite files. +CLOBBER="false" + +# If prompt==true, ask for confirmation before continuing with install. +PROMPT="true" + +# Name of twadmin executeable +TWADMIN="twadmin" + +# Path to twadmin executeable +TWADMPATH=/usr/sbin + +# Path to configuration directory +CONF_PATH="/etc/tripwire" + +# Name of clear text policy file +TXT_POL=$CONF_PATH/twpol.txt + +# Name of clear text configuration file +TXT_CFG=$CONF_PATH/twcfg.txt + +# Name of encrypted configuration file +CONFIG_FILE=$CONF_PATH/tw.cfg + +# Path of the final Tripwire policy file (signed) +SIGNED_POL=`grep POLFILE $TXT_CFG | sed -e 's/^.*=\(.*\)/\1/'` + + +##======================================================= +## Create Key Files +##======================================================= + +##------------------------------------------------------- +## If user has to enter a passphrase, give some +## advice about what is appropriate. +##------------------------------------------------------- + +if [ -z "$TW_SITE_PASS" ] || [ -z "$TW_LOCAL_PASS" ]; then +cat << END_OF_TEXT + +---------------------------------------------- +The Tripwire site and local passphrases are used to +sign a variety of files, such as the configuration, +policy, and database files. + +Passphrases should be at least 8 characters in length +and contain both letters and numbers. + +See the Tripwire manual for more information. +END_OF_TEXT +fi + +##======================================================= +## Generate keys. +##======================================================= + +echo +echo "----------------------------------------------" +echo "Creating key files..." + +##------------------------------------------------------- +## Site key file. +##------------------------------------------------------- + +# If clobber is true, and prompting is off (unattended operation) +# and the key file already exists, remove it. Otherwise twadmin +# will prompt with an "are you sure?" message. + +if [ "$CLOBBER" = "true" ] && [ "$PROMPT" = "false" ] && [ -f "$SITE_KEY" ] ; then + rm -f "$SITE_KEY" +fi + +if [ -f "$SITE_KEY" ] && [ "$CLOBBER" = "false" ] ; then + echo "The site key file \"$SITE_KEY\"" + echo 'exists and will not be overwritten.' +else + cmdargs="--generate-keys --site-keyfile \"$SITE_KEY\"" + if [ -n "$TW_SITE_PASS" ] ; then + cmdargs="$cmdargs --site-passphrase \"$TW_SITE_PASS\"" + fi + eval "\"$TWADMPATH/$TWADMIN\" $cmdargs" + if [ $? -ne 0 ] ; then + echo "Error: site key generation failed" + exit 1 + else chmod 640 "$SITE_KEY" + fi +fi + +##------------------------------------------------------- +## Local key file. +##------------------------------------------------------- + +# If clobber is true, and prompting is off (unattended operation) +# and the key file already exists, remove it. Otherwise twadmin +# will prompt with an "are you sure?" message. + +if [ "$CLOBBER" = "true" ] && [ "$PROMPT" = "false" ] && [ -f "$LOCAL_KEY" ] ; then + rm -f "$LOCAL_KEY" +fi + +if [ -f "$LOCAL_KEY" ] && [ "$CLOBBER" = "false" ] ; then + echo "The site key file \"$LOCAL_KEY\"" + echo 'exists and will not be overwritten.' +else + cmdargs="--generate-keys --local-keyfile \"$LOCAL_KEY\"" + if [ -n "$TW_LOCAL_PASS" ] ; then + cmdargs="$cmdargs --local-passphrase \"$TW_LOCAL_PASS\"" + fi + eval "\"$TWADMPATH/$TWADMIN\" $cmdargs" + if [ $? -ne 0 ] ; then + echo "Error: local key generation failed" + exit 1 + else chmod 640 "$LOCAL_KEY" + fi +fi + +##======================================================= +## Sign the Configuration File +##======================================================= + +echo +echo "----------------------------------------------" +echo "Signing configuration file..." + +##------------------------------------------------------- +## If noclobber, then backup any existing config file. +##------------------------------------------------------- + +if [ "$CLOBBER" = "false" ] && [ -s "$CONFIG_FILE" ] ; then + backup="${CONFIG_FILE}.$$.bak" + echo "Backing up $CONFIG_FILE" + echo " to $backup" + `mv "$CONFIG_FILE" "$backup"` + if [ $? -ne 0 ] ; then + echo "Error: backup of configuration file failed." + exit 1 + fi +fi + +##------------------------------------------------------- +## Build command line. +##------------------------------------------------------- + +cmdargs="--create-cfgfile" +cmdargs="$cmdargs --cfgfile \"$CONFIG_FILE\"" +cmdargs="$cmdargs --site-keyfile \"$SITE_KEY\"" +if [ -n "$TW_SITE_PASS" ] ; then + cmdargs="$cmdargs --site-passphrase \"$TW_SITE_PASS\"" +fi + +##------------------------------------------------------- +## Sign the file. +##------------------------------------------------------- + +eval "\"$TWADMPATH/$TWADMIN\" $cmdargs \"$TXT_CFG\"" +if [ $? -ne 0 ] ; then + echo "Error: signing of configuration file failed." + exit 1 +fi + +# Set the rights properly +chmod 640 "$CONFIG_FILE" + +##------------------------------------------------------- +## We keep the cleartext version around. +##------------------------------------------------------- + +cat << END_OF_TEXT + +A clear-text version of the Tripwire configuration file +$TXT_CFG +has been preserved for your inspection. It is recommended +that you delete this file manually after you have examined it. + +END_OF_TEXT + +##======================================================= +## Sign tripwire policy file. +##======================================================= + +echo +echo "----------------------------------------------" +echo "Signing policy file..." + +##------------------------------------------------------- +## If noclobber, then backup any existing policy file. +##------------------------------------------------------- + +if [ "$CLOBBER" = "false" ] && [ -s "$POLICY_FILE" ] ; then + backup="${POLICY_FILE}.$$.bak" + echo "Backing up $POLICY_FILE" + echo " to $backup" + mv "$POLICY_FILE" "$backup" + if [ $? -ne 0 ] ; then + echo "Error: backup of policy file failed." + exit 1 + fi +fi + +##------------------------------------------------------- +## Build command line. +##------------------------------------------------------- + +cmdargs="--create-polfile" +cmdargs="$cmdargs --cfgfile \"$CONFIG_FILE\"" +cmdargs="$cmdargs --site-keyfile \"$SITE_KEY\"" +if [ -n "$TW_SITE_PASS" ] ; then + cmdargs="$cmdargs --site-passphrase \"$TW_SITE_PASS\"" +fi + +##------------------------------------------------------- +## Sign the file. +##------------------------------------------------------- + +eval "\"$TWADMPATH/$TWADMIN\" $cmdargs \"$TXT_POL\"" +if [ $? -ne 0 ] ; then + echo "Error: signing of policy file failed." + exit 1 +fi + +# Set the proper rights on the newly signed policy file. +chmod 0640 "$SIGNED_POL" + +##------------------------------------------------------- +## We keep the cleartext version around. +##------------------------------------------------------- + +cat << END_OF_TEXT + +A clear-text version of the Tripwire policy file +$TXT_POL +has been preserved for your inspection. This implements +a minimal policy, intended only to test essential +Tripwire functionality. You should edit the policy file +to describe your system, and then use twadmin to generate +a new signed copy of the Tripwire policy. + +END_OF_TEXT + +# Initialize tripwire database +/usr/sbin/tripwire --init --cfgfile $CONFIG_FILE --site-keyfile $SITE_KEY \ +--local-passphrase $TW_LOCAL_PASS 2> /dev/null + +######################################################################## +######################################################################## +# +# TRIPWIRE GPL NOTICES +# +# The developer of the original code and/or files is Tripwire, Inc. +# Portions created by Tripwire, Inc. are copyright 2000 Tripwire, Inc. +# Tripwire is a registered trademark of Tripwire, Inc. All rights reserved. +# +# This program is free software. The contents of this file are subject to +# the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. You may redistribute it and/or modify it only in +# compliance with the GNU General Public License. +# +# This program is distributed in the hope that it will be useful. However, +# this program is distributed "AS-IS" WITHOUT ANY WARRANTY; INCLUDING THE +# IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. +# Please see the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# Nothing in the GNU General Public License or any other license to use the +# code or files shall permit you to use Tripwire's trademarks, +# service marks, or other intellectual property without Tripwire's +# prior written consent. +# +# If you have any questions, please contact Tripwire, Inc. at either +# info@tripwire.org or www.tripwire.org. +# +######################################################################## +######################################################################## diff --git a/meta-security/recipes-security/tripwire/files/twpol-yocto.txt b/meta-security/recipes-security/tripwire/files/twpol-yocto.txt new file mode 100644 index 000000000..65f5f7500 --- /dev/null +++ b/meta-security/recipes-security/tripwire/files/twpol-yocto.txt @@ -0,0 +1,1107 @@ + ############################################################################## + # ## +############################################################################## # +# # # +# Generic Policy file # # +# V1.2.0rh # # +# August 9, 2001 # # +# ## +############################################################################## + + + ############################################################################## + # ## +############################################################################## # +# # # +# This is the example Tripwire Policy file. It is intended as a place to # # +# start creating your own custom Tripwire Policy file. Referring to it as # # +# well as the Tripwire Policy Guide should give you enough information to # # +# make a good custom Tripwire Policy file that better covers your # # +# configuration and security needs. A text version of this policy file is # # +# called twpol.txt. # # +# # # +# Note that this file is tuned to an 'everything' install of Red Hat Linux. # # +# If run unmodified, this file should create no errors on database # # +# creation, or violations on a subsiquent integrity check. However, it is # # +# impossible for there to be one policy file for all machines, so this # # +# existing one errs on the side of security. Your Linux configuration will # # +# most likey differ from the one our policy file was tuned to, and will # # +# therefore require some editing of the default Tripwire Policy file. # # +# # # +# The example policy file is best run with 'Loose Directory Checking' # # +# enabled. Set LOOSEDIRECTORYCHECKING=TRUE in the Tripwire Configuration # # +# file. # # +# # # +# Email support is not included and must be added to this file. # # +# Add the 'emailto=' to the rule directive section of each rule (add a comma # # +# after the 'severity=' line and add an 'emailto=' and include the email # # +# addresses you want the violation reports to go to). Addresses are # # +# semi-colon delimited. # # +# ## +############################################################################## + + + + ############################################################################## + # ## +############################################################################## # +# # # +# Global Variable Definitions # # +# # # +# These are defined at install time by the installation script. You may # # +# Manually edit these if you are using this file directly and not from the # # +# installation script itself. # # +# ## +############################################################################## + +@@section GLOBAL +TWROOT=/usr/sbin; +TWBIN=/usr/sbin; +TWPOL="/etc/tripwire"; +TWDB="/var/lib/tripwire"; +TWSKEY="/etc/tripwire"; +TWLKEY="/etc/tripwire"; +TWREPORT="/var/lib/tripwire/report"; +HOSTNAME=localhost; + +@@section FS +SEC_CRIT = $(IgnoreNone)-SHa ; # Critical files that cannot change +SEC_SUID = $(IgnoreNone)-SHa ; # Binaries with the SUID or SGID flags set +SEC_BIN = $(ReadOnly) ; # Binaries that should not change +SEC_CONFIG = $(Dynamic) ; # Config files that are changed infrequently but accessed often +SEC_LOG = $(Growing) ; # Files that grow, but that should never change ownership +SEC_INVARIANT = +tpug ; # Directories that should never change permission or ownership +SIG_LOW = 33 ; # Non-critical files that are of minimal security impact +SIG_MED = 66 ; # Non-critical files that are of significant security impact +SIG_HI = 100 ; # Critical files that are significant points of vulnerability + + +# Tripwire Binaries +( + rulename = "Tripwire Binaries", + severity = $(SIG_HI) +) +{ + $(TWBIN)/siggen -> $(SEC_BIN) ; + $(TWBIN)/tripwire -> $(SEC_BIN) ; + $(TWBIN)/twadmin -> $(SEC_BIN) ; + $(TWBIN)/twprint -> $(SEC_BIN) ; +} + +# Tripwire Data Files - Configuration Files, Policy Files, Keys, Reports, Databases +( + rulename = "Tripwire Data Files", + severity = $(SIG_HI) +) +{ + # NOTE: We remove the inode attribute because when Tripwire creates a backup, + # it does so by renaming the old file and creating a new one (which will + # have a new inode number). Inode is left turned on for keys, which shouldn't + # ever change. + + # NOTE: The first integrity check triggers this rule and each integrity check + # afterward triggers this rule until a database update is run, since the + # database file does not exist before that point. + + $(TWDB) -> $(SEC_CONFIG) -i ; + $(TWPOL)/tw.pol -> $(SEC_BIN) -i ; + $(TWPOL)/tw.cfg -> $(SEC_BIN) -i ; + $(TWLKEY)/$(HOSTNAME)-local.key -> $(SEC_BIN) ; + $(TWSKEY)/site.key -> $(SEC_BIN) ; + + #don't scan the individual reports + $(TWREPORT) -> $(SEC_CONFIG) (recurse=0) ; +} + + +# Tripwire HQ Connector Binaries +#( +# rulename = "Tripwire HQ Connector Binaries", +# severity = $(SIG_HI) +#) +#{ +# $(TWBIN)/hqagent -> $(SEC_BIN) ; +#} +# +# Tripwire HQ Connector - Configuration Files, Keys, and Logs + + ############################################################################## + # ## +############################################################################## # +# # # +# Note: File locations here are different than in a stock HQ Connector # # +# installation. This is because Tripwire 2.3 uses a different path # # +# structure than Tripwire 2.2.1. # # +# # # +# You may need to update your HQ Agent configuation file (or this policy # # +# file) to correct the paths. We have attempted to support the FHS standard # # +# here by placing the HQ Agent files similarly to the way Tripwire 2.3 # # +# places them. # # +# ## +############################################################################## + +#( +# rulename = "Tripwire HQ Connector Data Files", +# severity = $(SIG_HI) +#) +#{ +# ############################################################################# +# ############################################################################## +# # NOTE: Removing the inode attribute because when Tripwire creates a backup ## +# # it does so by renaming the old file and creating a new one (which will ## +# # have a new inode number). Leaving inode turned on for keys, which ## +# # shouldn't ever change. ## +# ############################################################################# +# +# $(TWBIN)/agent.cfg -> $(SEC_BIN) -i ; +# $(TWLKEY)/authentication.key -> $(SEC_BIN) ; +# $(TWDB)/tasks.dat -> $(SEC_CONFIG) ; +# $(TWDB)/schedule.dat -> $(SEC_CONFIG) ; +# +# # Uncomment if you have agent logging enabled. +# #/var/log/tripwire/agent.log -> $(SEC_LOG) ; +#} + + + +# Commonly accessed directories that should remain static with regards to owner and group +( + rulename = "Invariant Directories", + severity = $(SIG_MED) +) +{ + / -> $(SEC_INVARIANT) (recurse = 0) ; + /home -> $(SEC_INVARIANT) (recurse = 0) ; + /etc -> $(SEC_INVARIANT) (recurse = 0) ; +} + ################################################ + # ## +################################################ # +# # # +# File System and Disk Administration Programs # # +# ## +################################################ + +( + rulename = "File System and Disk Administraton Programs", + severity = $(SIG_HI) +) +{ + /sbin/accton -> $(SEC_CRIT) ; + /sbin/badblocks -> $(SEC_CRIT) ; + /sbin/busybox -> $(SEC_CRIT) ; + /sbin/busybox.anaconda -> $(SEC_CRIT) ; + /sbin/convertquota -> $(SEC_CRIT) ; + /sbin/dosfsck -> $(SEC_CRIT) ; + /sbin/debugfs -> $(SEC_CRIT) ; + /sbin/debugreiserfs -> $(SEC_CRIT) ; + /sbin/dumpe2fs -> $(SEC_CRIT) ; + /sbin/dump -> $(SEC_CRIT) ; + /sbin/dump.static -> $(SEC_CRIT) ; + # /sbin/e2fsadm -> $(SEC_CRIT) ; tune2fs? + /sbin/e2fsck -> $(SEC_CRIT) ; + /sbin/e2label -> $(SEC_CRIT) ; + /sbin/fdisk -> $(SEC_CRIT) ; + /sbin/fsck -> $(SEC_CRIT) ; + /sbin/fsck.ext2 -> $(SEC_CRIT) ; + /sbin/fsck.ext3 -> $(SEC_CRIT) ; + /sbin/fsck.minix -> $(SEC_CRIT) ; + /sbin/fsck.msdos -> $(SEC_CRIT) ; + /sbin/fsck.vfat -> $(SEC_CRIT) ; + /sbin/ftl_check -> $(SEC_CRIT) ; + /sbin/ftl_format -> $(SEC_CRIT) ; + /sbin/hdparm -> $(SEC_CRIT) ; + #/sbin/lvchange -> $(SEC_CRIT) ; + #/sbin/lvcreate -> $(SEC_CRIT) ; + #/sbin/lvdisplay -> $(SEC_CRIT) ; + #/sbin/lvextend -> $(SEC_CRIT) ; + #/sbin/lvmchange -> $(SEC_CRIT) ; + #/sbin/lvmcreate_initrd -> $(SEC_CRIT) ; + #/sbin/lvmdiskscan -> $(SEC_CRIT) ; + #/sbin/lvmsadc -> $(SEC_CRIT) ; + #/sbin/lvmsar -> $(SEC_CRIT) ; + #/sbin/lvreduce -> $(SEC_CRIT) ; + #/sbin/lvremove -> $(SEC_CRIT) ; + #/sbin/lvrename -> $(SEC_CRIT) ; + #/sbin/lvscan -> $(SEC_CRIT) ; + /sbin/mkbootdisk -> $(SEC_CRIT) ; + /sbin/mkdosfs -> $(SEC_CRIT) ; + /sbin/mke2fs -> $(SEC_CRIT) ; + /sbin/mkfs -> $(SEC_CRIT) ; + /sbin/mkfs.bfs -> $(SEC_CRIT) ; + /sbin/mkfs.ext2 -> $(SEC_CRIT) ; + /sbin/mkfs.minix -> $(SEC_CRIT) ; + /sbin/mkfs.msdos -> $(SEC_CRIT) ; + /sbin/mkfs.vfat -> $(SEC_CRIT) ; + /sbin/mkinitrd -> $(SEC_CRIT) ; + #/sbin/mkpv -> $(SEC_CRIT) ; + /sbin/mkraid -> $(SEC_CRIT) ; + /sbin/mkreiserfs -> $(SEC_CRIT) ; + /sbin/mkswap -> $(SEC_CRIT) ; + #/sbin/mtx -> $(SEC_CRIT) ; + /sbin/pam_console_apply -> $(SEC_CRIT) ; + /sbin/parted -> $(SEC_CRIT) ; + /sbin/pcinitrd -> $(SEC_CRIT) ; + #/sbin/pvchange -> $(SEC_CRIT) ; + #/sbin/pvcreate -> $(SEC_CRIT) ; + #/sbin/pvdata -> $(SEC_CRIT) ; + #/sbin/pvdisplay -> $(SEC_CRIT) ; + #/sbin/pvmove -> $(SEC_CRIT) ; + #/sbin/pvscan -> $(SEC_CRIT) ; + /sbin/quotacheck -> $(SEC_CRIT) ; + /sbin/quotaon -> $(SEC_CRIT) ; + /sbin/raidstart -> $(SEC_CRIT) ; + /sbin/reiserfsck -> $(SEC_CRIT) ; + /sbin/resize2fs -> $(SEC_CRIT) ; + /sbin/resize_reiserfs -> $(SEC_CRIT) ; + /sbin/restore -> $(SEC_CRIT) ; + /sbin/restore.static -> $(SEC_CRIT) ; + /sbin/scsi_info -> $(SEC_CRIT) ; + /sbin/sfdisk -> $(SEC_CRIT) ; + /sbin/stinit -> $(SEC_CRIT) ; + #/sbin/tapeinfo -> $(SEC_CRIT) ; + /sbin/tune2fs -> $(SEC_CRIT) ; + /sbin/unpack -> $(SEC_CRIT) ; + /sbin/update -> $(SEC_CRIT) ; + #/sbin/vgcfgbackup -> $(SEC_CRIT) ; + #/sbin/vgcfgrestore -> $(SEC_CRIT) ; + #/sbin/vgchange -> $(SEC_CRIT) ; + #/sbin/vgck -> $(SEC_CRIT) ; + #/sbin/vgcreate -> $(SEC_CRIT) ; + #/sbin/vgdisplay -> $(SEC_CRIT) ; + #/sbin/vgexport -> $(SEC_CRIT) ; + #/sbin/vgextend -> $(SEC_CRIT) ; + #/sbin/vgimport -> $(SEC_CRIT) ; + #/sbin/vgmerge -> $(SEC_CRIT) ; + #/sbin/vgmknodes -> $(SEC_CRIT) ; + #/sbin/vgreduce -> $(SEC_CRIT) ; + #/sbin/vgremove -> $(SEC_CRIT) ; + #/sbin/vgrename -> $(SEC_CRIT) ; + #/sbin/vgscan -> $(SEC_CRIT) ; + #/sbin/vgsplit -> $(SEC_CRIT) ; + /bin/chgrp -> $(SEC_CRIT) ; + /bin/chmod -> $(SEC_CRIT) ; + /bin/chown -> $(SEC_CRIT) ; + /bin/cp -> $(SEC_CRIT) ; + /bin/cpio -> $(SEC_CRIT) ; + /bin/mount -> $(SEC_CRIT) ; + /bin/umount -> $(SEC_CRIT) ; + /bin/mkdir -> $(SEC_CRIT) ; + /bin/mknod -> $(SEC_CRIT) ; + /bin/mktemp -> $(SEC_CRIT) ; + /bin/rm -> $(SEC_CRIT) ; + /bin/rmdir -> $(SEC_CRIT) ; + /bin/touch -> $(SEC_CRIT) ; +} + + ################################## + # ## +################################## # +# # # +# Kernel Administration Programs # # +# ## +################################## + +( + rulename = "Kernel Administration Programs", + severity = $(SIG_HI) +) +{ + /sbin/adjtimex -> $(SEC_CRIT) ; + /sbin/ctrlaltdel -> $(SEC_CRIT) ; + /sbin/depmod -> $(SEC_CRIT) ; + /sbin/insmod -> $(SEC_CRIT) ; + /sbin/insmod.static -> $(SEC_CRIT) ; + /sbin/insmod_ksymoops_clean -> $(SEC_CRIT) ; + /sbin/klogd -> $(SEC_CRIT) ; + /sbin/ldconfig -> $(SEC_CRIT) ; + /sbin/minilogd -> $(SEC_CRIT) ; + /sbin/modinfo -> $(SEC_CRIT) ; + #/sbin/nuactlun -> $(SEC_CRIT) ; + #/sbin/nuscsitcpd -> $(SEC_CRIT) ; + /sbin/pivot_root -> $(SEC_CRIT) ; + /sbin/sndconfig -> $(SEC_CRIT) ; + /sbin/sysctl -> $(SEC_CRIT) ; +} + + ####################### + # ## +####################### # +# # # +# Networking Programs # # +# ## +####################### + +( + rulename = "Networking Programs", + severity = $(SIG_HI) +) +{ + /etc/sysconfig/network-scripts/ifdown -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifdown-cipcb -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifdown-ippp -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifdown-ipv6 -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifdown-isdn -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifdown-post -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifdown-ppp -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifdown-sit -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifdown-sl -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-aliases -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-cipcb -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-ippp -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-ipv6 -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-isdn -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-plip -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-plusb -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-post -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-ppp -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-routes -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-sit -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-sl -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-wireless -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/network-functions -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/network-functions-ipv6 -> $(SEC_CRIT) ; + /bin/ping -> $(SEC_CRIT) ; + /sbin/agetty -> $(SEC_CRIT) ; + /sbin/arp -> $(SEC_CRIT) ; + /sbin/arping -> $(SEC_CRIT) ; + /sbin/dhcpcd -> $(SEC_CRIT) ; + /sbin/ether-wake -> $(SEC_CRIT) ; + #/sbin/getty -> $(SEC_CRIT) ; + /sbin/ifcfg -> $(SEC_CRIT) ; + /sbin/ifconfig -> $(SEC_CRIT) ; + /sbin/ifdown -> $(SEC_CRIT) ; + /sbin/ifenslave -> $(SEC_CRIT) ; + /sbin/ifport -> $(SEC_CRIT) ; + /sbin/ifup -> $(SEC_CRIT) ; + /sbin/ifuser -> $(SEC_CRIT) ; + /sbin/ip -> $(SEC_CRIT) ; + /sbin/ip6tables -> $(SEC_CRIT) ; + /sbin/ipchains -> $(SEC_CRIT) ; + /sbin/ipchains-restore -> $(SEC_CRIT) ; + /sbin/ipchains-save -> $(SEC_CRIT) ; + /sbin/ipfwadm -> $(SEC_CRIT) ; + /sbin/ipmaddr -> $(SEC_CRIT) ; + /sbin/iptables -> $(SEC_CRIT) ; + /sbin/iptables-restore -> $(SEC_CRIT) ; + /sbin/iptables-save -> $(SEC_CRIT) ; + /sbin/iptunnel -> $(SEC_CRIT) ; + #/sbin/ipvsadm -> $(SEC_CRIT) ; + #/sbin/ipvsadm-restore -> $(SEC_CRIT) ; + #/sbin/ipvsadm-save -> $(SEC_CRIT) ; + /sbin/ipx_configure -> $(SEC_CRIT) ; + /sbin/ipx_interface -> $(SEC_CRIT) ; + /sbin/ipx_internal_net -> $(SEC_CRIT) ; + /sbin/iwconfig -> $(SEC_CRIT) ; + /sbin/iwgetid -> $(SEC_CRIT) ; + /sbin/iwlist -> $(SEC_CRIT) ; + /sbin/iwpriv -> $(SEC_CRIT) ; + /sbin/iwspy -> $(SEC_CRIT) ; + /sbin/mgetty -> $(SEC_CRIT) ; + /sbin/mingetty -> $(SEC_CRIT) ; + /sbin/nameif -> $(SEC_CRIT) ; + /sbin/netreport -> $(SEC_CRIT) ; + /sbin/plipconfig -> $(SEC_CRIT) ; + /sbin/portmap -> $(SEC_CRIT) ; + /sbin/ppp-watch -> $(SEC_CRIT) ; + #/sbin/rarp -> $(SEC_CRIT) ; + /sbin/route -> $(SEC_CRIT) ; + /sbin/slattach -> $(SEC_CRIT) ; + /sbin/tc -> $(SEC_CRIT) ; + #/sbin/uugetty -> $(SEC_CRIT) ; + /sbin/vgetty -> $(SEC_CRIT) ; + /sbin/ypbind -> $(SEC_CRIT) ; +} + + ################################## + # ## +################################## # +# # # +# System Administration Programs # # +# ## +################################## + +( + rulename = "System Administration Programs", + severity = $(SIG_HI) +) +{ + /sbin/chkconfig -> $(SEC_CRIT) ; + /sbin/fuser -> $(SEC_CRIT) ; + /sbin/halt -> $(SEC_CRIT) ; + /sbin/init -> $(SEC_CRIT) ; + /sbin/initlog -> $(SEC_CRIT) ; + /sbin/install-info -> $(SEC_CRIT) ; + /sbin/killall5 -> $(SEC_CRIT) ; + #/sbin/linuxconf -> $(SEC_CRIT) ; + #/sbin/linuxconf-auth -> $(SEC_CRIT) ; + /sbin/pam_tally -> $(SEC_CRIT) ; + /sbin/pwdb_chkpwd -> $(SEC_CRIT) ; + #/sbin/remadmin -> $(SEC_CRIT) ; + /sbin/rescuept -> $(SEC_CRIT) ; + /sbin/rmt -> $(SEC_CRIT) ; + /sbin/rpc.lockd -> $(SEC_CRIT) ; + /sbin/rpc.statd -> $(SEC_CRIT) ; + /sbin/rpcdebug -> $(SEC_CRIT) ; + /sbin/service -> $(SEC_CRIT) ; + /sbin/setsysfont -> $(SEC_CRIT) ; + /sbin/shutdown -> $(SEC_CRIT) ; + /sbin/sulogin -> $(SEC_CRIT) ; + /sbin/swapon -> $(SEC_CRIT) ; + /sbin/syslogd -> $(SEC_CRIT) ; + /sbin/unix_chkpwd -> $(SEC_CRIT) ; + /bin/pwd -> $(SEC_CRIT) ; + /bin/uname -> $(SEC_CRIT) ; +} + + ######################################## + # ## +######################################## # +# # # +# Hardware and Device Control Programs # # +# ## +######################################## +( + rulename = "Hardware and Device Control Programs", + severity = $(SIG_HI) +) +{ + /bin/setserial -> $(SEC_CRIT) ; + /bin/sfxload -> $(SEC_CRIT) ; + /sbin/blockdev -> $(SEC_CRIT) ; + /sbin/cardctl -> $(SEC_CRIT) ; + /sbin/cardmgr -> $(SEC_CRIT) ; + /sbin/cbq -> $(SEC_CRIT) ; + /sbin/dump_cis -> $(SEC_CRIT) ; + /sbin/elvtune -> $(SEC_CRIT) ; + /sbin/hotplug -> $(SEC_CRIT) ; + /sbin/hwclock -> $(SEC_CRIT) ; + /sbin/ide_info -> $(SEC_CRIT) ; + #/sbin/isapnp -> $(SEC_CRIT) ; + /sbin/kbdrate -> $(SEC_CRIT) ; + /sbin/losetup -> $(SEC_CRIT) ; + /sbin/lspci -> $(SEC_CRIT) ; + /sbin/lspnp -> $(SEC_CRIT) ; + /sbin/mii-tool -> $(SEC_CRIT) ; + /sbin/pack_cis -> $(SEC_CRIT) ; + #/sbin/pnpdump -> $(SEC_CRIT) ; + /sbin/probe -> $(SEC_CRIT) ; + /sbin/pump -> $(SEC_CRIT) ; + /sbin/setpci -> $(SEC_CRIT) ; + /sbin/shapecfg -> $(SEC_CRIT) ; +} + + ############################### + # ## +############################### # +# # # +# System Information Programs # # +# ## +############################### +( + rulename = "System Information Programs", + severity = $(SIG_HI) +) +{ + /sbin/consoletype -> $(SEC_CRIT) ; + /sbin/kernelversion -> $(SEC_CRIT) ; + /sbin/runlevel -> $(SEC_CRIT) ; +} + + #################################### + # ## +#################################### # +# # # +# Application Information Programs # # +# ## +#################################### + +( + rulename = "Application Information Programs", + severity = $(SIG_HI) +) +{ + /sbin/genksyms -> $(SEC_CRIT) ; + #/sbin/genksyms.old -> $(SEC_CRIT) ; + /sbin/rtmon -> $(SEC_CRIT) ; +} + + ########################## + # ## +########################## # +# # # +# Shell Related Programs # # +# ## +########################## +( + rulename = "Shell Related Programs", + severity = $(SIG_HI) +) +{ + /sbin/getkey -> $(SEC_CRIT) ; + /sbin/nash -> $(SEC_CRIT) ; + /sbin/sash -> $(SEC_CRIT) ; +} + + + ################ + # ## +################ # +# # # +# OS Utilities # # +# ## +################ +( + rulename = "Operating System Utilities", + severity = $(SIG_HI) +) +{ + /bin/arch -> $(SEC_CRIT) ; + /bin/ash -> $(SEC_CRIT) ; + /bin/ash.static -> $(SEC_CRIT) ; + /bin/aumix-minimal -> $(SEC_CRIT) ; + /bin/basename -> $(SEC_CRIT) ; + /bin/cat -> $(SEC_CRIT) ; + /bin/consolechars -> $(SEC_CRIT) ; + /bin/cut -> $(SEC_CRIT) ; + /bin/date -> $(SEC_CRIT) ; + /bin/dd -> $(SEC_CRIT) ; + /bin/df -> $(SEC_CRIT) ; + /bin/dmesg -> $(SEC_CRIT) ; + /bin/doexec -> $(SEC_CRIT) ; + /bin/echo -> $(SEC_CRIT) ; + /bin/ed -> $(SEC_CRIT) ; + /bin/egrep -> $(SEC_CRIT) ; + /bin/false -> $(SEC_CRIT) ; + /bin/fgrep -> $(SEC_CRIT) ; + /bin/gawk -> $(SEC_CRIT) ; + /bin/gawk-3.1.0 -> $(SEC_CRIT) ; + /bin/gettext -> $(SEC_CRIT) ; + /bin/grep -> $(SEC_CRIT) ; + /bin/gunzip -> $(SEC_CRIT) ; + /bin/gzip -> $(SEC_CRIT) ; + /bin/hostname -> $(SEC_CRIT) ; + /bin/igawk -> $(SEC_CRIT) ; + /bin/ipcalc -> $(SEC_CRIT) ; + /bin/kill -> $(SEC_CRIT) ; + /bin/ln -> $(SEC_CRIT) ; + /bin/loadkeys -> $(SEC_CRIT) ; + /bin/login -> $(SEC_CRIT) ; + /bin/ls -> $(SEC_CRIT) ; + /bin/mail -> $(SEC_CRIT) ; + /bin/more -> $(SEC_CRIT) ; + /bin/mt -> $(SEC_CRIT) ; + /bin/mv -> $(SEC_CRIT) ; + /bin/netstat -> $(SEC_CRIT) ; + /bin/nice -> $(SEC_CRIT) ; + /bin/pgawk -> $(SEC_CRIT) ; + /bin/ps -> $(SEC_CRIT) ; + /bin/rpm -> $(SEC_CRIT) ; + /bin/sed -> $(SEC_CRIT) ; + /bin/sleep -> $(SEC_CRIT) ; + /bin/sort -> $(SEC_CRIT) ; + /bin/stty -> $(SEC_CRIT) ; + /bin/su -> $(SEC_CRIT) ; + /bin/sync -> $(SEC_CRIT) ; + /bin/tar -> $(SEC_CRIT) ; + /bin/true -> $(SEC_CRIT) ; + /bin/usleep -> $(SEC_CRIT) ; + /bin/vi -> $(SEC_CRIT) ; + /bin/zcat -> $(SEC_CRIT) ; + /bin/zsh -> $(SEC_CRIT) ; + #/bin/zsh-4.0.2 -> $(SEC_CRIT) ; + /sbin/sln -> $(SEC_CRIT) ; + /usr/bin/vimtutor -> $(SEC_CRIT) ; +} + + ############################## + # ## +############################## # +# # # +# Critical Utility Sym-Links # # +# ## +############################## +( + rulename = "Critical Utility Sym-Links", + severity = $(SIG_HI) +) +{ + #/sbin/askrunlevel -> $(SEC_CRIT) ; + /sbin/clock -> $(SEC_CRIT) ; + #/sbin/fixperm -> $(SEC_CRIT) ; + /sbin/fsck.reiserfs -> $(SEC_CRIT) ; + #/sbin/fsconf -> $(SEC_CRIT) ; + /sbin/ipfwadm-wrapper -> $(SEC_CRIT) ; + /sbin/kallsyms -> $(SEC_CRIT) ; + /sbin/ksyms -> $(SEC_CRIT) ; + /sbin/lsmod -> $(SEC_CRIT) ; + #/sbin/mailconf -> $(SEC_CRIT) ; + /sbin/mkfs.reiserfs -> $(SEC_CRIT) ; + #/sbin/modemconf -> $(SEC_CRIT) ; + /sbin/modprobe -> $(SEC_CRIT) ; + /sbin/mount.ncp -> $(SEC_CRIT) ; + /sbin/mount.ncpfs -> $(SEC_CRIT) ; + /sbin/mount.smb -> $(SEC_CRIT) ; + /sbin/mount.smbfs -> $(SEC_CRIT) ; + #/sbin/netconf -> $(SEC_CRIT) ; + /sbin/pidof -> $(SEC_CRIT) ; + /sbin/poweroff -> $(SEC_CRIT) ; + /sbin/quotaoff -> $(SEC_CRIT) ; + /sbin/raid0run -> $(SEC_CRIT) ; + /sbin/raidhotadd -> $(SEC_CRIT) ; + /sbin/raidhotgenerateerror -> $(SEC_CRIT) ; + /sbin/raidhotremove -> $(SEC_CRIT) ; + /sbin/raidstop -> $(SEC_CRIT) ; + /sbin/rdump -> $(SEC_CRIT) ; + /sbin/rdump.static -> $(SEC_CRIT) ; + /sbin/reboot -> $(SEC_CRIT) ; + /sbin/rmmod -> $(SEC_CRIT) ; + /sbin/rrestore -> $(SEC_CRIT) ; + /sbin/rrestore.static -> $(SEC_CRIT) ; + /sbin/swapoff -> $(SEC_CRIT) ; + /sbin/telinit -> $(SEC_CRIT) ; + #/sbin/userconf -> $(SEC_CRIT) ; + #/sbin/uucpconf -> $(SEC_CRIT) ; + #/sbin/vregistry -> $(SEC_CRIT) ; + /bin/awk -> $(SEC_CRIT) ; + /bin/bash2 -> $(SEC_CRIT) ; + /bin/bsh -> $(SEC_CRIT) ; + /bin/csh -> $(SEC_CRIT) ; + /bin/dnsdomainname -> $(SEC_CRIT) ; + /bin/domainname -> $(SEC_CRIT) ; + /bin/ex -> $(SEC_CRIT) ; + /bin/gtar -> $(SEC_CRIT) ; + /bin/nisdomainname -> $(SEC_CRIT) ; + /bin/red -> $(SEC_CRIT) ; + /bin/rvi -> $(SEC_CRIT) ; + /bin/rview -> $(SEC_CRIT) ; + /bin/view -> $(SEC_CRIT) ; + /bin/ypdomainname -> $(SEC_CRIT) ; +} + + + ######################### + # ## +######################### # +# # # +# Temporary directories # # +# ## +######################### +( + rulename = "Temporary directories", + recurse = false, + severity = $(SIG_LOW) +) +{ + /usr/tmp -> $(SEC_INVARIANT) ; + /var/tmp -> $(SEC_INVARIANT) ; + /tmp -> $(SEC_INVARIANT) ; +} + + ############### + # ## +############### # +# # # +# Local files # # +# ## +############### +( + rulename = "User binaries", + severity = $(SIG_MED) +) +{ + /sbin -> $(SEC_BIN) (recurse = 1) ; + /usr/bin -> $(SEC_BIN) (recurse = 1) ; + /usr/sbin -> $(SEC_BIN) (recurse = 1) ; + /usr/local/bin -> $(SEC_BIN) (recurse = 1) ; +} + +( + rulename = "Shell Binaries", + severity = $(SIG_HI) +) +{ + /bin/bash -> $(SEC_BIN) ; + /bin/ksh -> $(SEC_BIN) ; + # /bin/psh -> $(SEC_BIN) ; # No longer used? + # /bin/Rsh -> $(SEC_BIN) ; # No longer used? + /bin/sh -> $(SEC_BIN) ; + # /bin/shell -> $(SEC_SUID) ; # No longer used? + # /bin/tsh -> $(SEC_BIN) ; # No longer used? + /bin/tcsh -> $(SEC_BIN) ; + /sbin/nologin -> $(SEC_BIN) ; +} + +( + rulename = "Security Control", + severity = $(SIG_HI) +) +{ + /etc/group -> $(SEC_CRIT) ; + /etc/security -> $(SEC_CRIT) ; + #/var/spool/cron/crontabs -> $(SEC_CRIT) ; # Uncomment when this file exists +} + +#( +# rulename = "Boot Scripts", +# severity = $(SIG_HI) +#) +#{ +# /etc/rc -> $(SEC_CONFIG) ; +# /etc/rc.bsdnet -> $(SEC_CONFIG) ; +# /etc/rc.dt -> $(SEC_CONFIG) ; +# /etc/rc.net -> $(SEC_CONFIG) ; +# /etc/rc.net.serial -> $(SEC_CONFIG) ; +# /etc/rc.nfs -> $(SEC_CONFIG) ; +# /etc/rc.powerfail -> $(SEC_CONFIG) ; +# /etc/rc.tcpip -> $(SEC_CONFIG) ; +# /etc/trcfmt.Z -> $(SEC_CONFIG) ; +#} + +( + rulename = "Login Scripts", + severity = $(SIG_HI) +) +{ + /etc/bashrc -> $(SEC_CONFIG) ; + /etc/csh.cshrc -> $(SEC_CONFIG) ; + /etc/csh.login -> $(SEC_CONFIG) ; + /etc/inputrc -> $(SEC_CONFIG) ; + # /etc/tsh_profile -> $(SEC_CONFIG) ; #Uncomment when this file exists + /etc/profile -> $(SEC_CONFIG) ; +} + +# Libraries +( + rulename = "Libraries", + severity = $(SIG_MED) +) +{ + /usr/lib -> $(SEC_BIN) ; + /usr/local/lib -> $(SEC_BIN) ; +} + + + ###################################################### + # ## +###################################################### # +# # # +# Critical System Boot Files # # +# These files are critical to a correct system boot. # # +# ## +###################################################### + +( + rulename = "Critical system boot files", + severity = $(SIG_HI) +) +{ + /boot -> $(SEC_CRIT) ; + #/sbin/devfsd -> $(SEC_CRIT) ; + /sbin/grub -> $(SEC_CRIT) ; + /sbin/grub-install -> $(SEC_CRIT) ; + /sbin/grub-md5-crypt -> $(SEC_CRIT) ; + /sbin/installkernel -> $(SEC_CRIT) ; + /sbin/lilo -> $(SEC_CRIT) ; + /sbin/mkkerneldoth -> $(SEC_CRIT) ; + !/boot/System.map ; + !/boot/module-info ; + /usr/share/grub/i386-redhat/e2fs_stage1_5 -> $(SEC_CRIT) ; + /usr/share/grub/i386-redhat/fat_stage1_5 -> $(SEC_CRIT) ; + /usr/share/grub/i386-redhat/ffs_stage1_5 -> $(SEC_CRIT) ; + /usr/share/grub/i386-redhat/minix_stage1_5 -> $(SEC_CRIT) ; + /usr/share/grub/i386-redhat/reiserfs_stage1_5 -> $(SEC_CRIT) ; + /usr/share/grub/i386-redhat/stage1 -> $(SEC_CRIT) ; + /usr/share/grub/i386-redhat/stage2 -> $(SEC_CRIT) ; + /usr/share/grub/i386-redhat/vstafs_stage1_5 -> $(SEC_CRIT) ; + # other boot files may exist. Look for: + #/ufsboot -> $(SEC_CRIT) ; +} + ################################################## + ################################################### + # These files change every time the system boots ## + ################################################## +( + rulename = "System boot changes", + severity = $(SIG_HI) +) +{ + !/var/run/ftp.pids-all ; # Comes and goes on reboot. + !/root/.enlightenment ; + /dev/log -> $(SEC_CONFIG) ; + /dev/cua0 -> $(SEC_CONFIG) ; + # /dev/printer -> $(SEC_CONFIG) ; # Uncomment if you have a printer device + /dev/console -> $(SEC_CONFIG) -u ; # User ID may change on console login/logout. + /dev/tty1 -> $(SEC_CONFIG) ; # tty devices + /dev/tty2 -> $(SEC_CONFIG) ; # tty devices + /dev/tty3 -> $(SEC_CONFIG) ; # are extremely + /dev/tty4 -> $(SEC_CONFIG) ; # variable + /dev/tty5 -> $(SEC_CONFIG) ; + /dev/tty6 -> $(SEC_CONFIG) ; + /dev/urandom -> $(SEC_CONFIG) ; + /dev/initctl -> $(SEC_CONFIG) ; + /var/lock/subsys -> $(SEC_CONFIG) ; + #/var/lock/subsys/amd -> $(SEC_CONFIG) ; + /var/lock/subsys/anacron -> $(SEC_CONFIG) ; + /var/lock/subsys/apmd -> $(SEC_CONFIG) ; + #/var/lock/subsys/arpwatch -> $(SEC_CONFIG) ; + /var/lock/subsys/atd -> $(SEC_CONFIG) ; + /var/lock/subsys/autofs -> $(SEC_CONFIG) ; + #/var/lock/subsys/bcm5820 -> $(SEC_CONFIG) ; + #/var/lock/subsys/bgpd -> $(SEC_CONFIG) ; + #/var/lock/subsys/bootparamd -> $(SEC_CONFIG) ; + #/var/lock/subsys/canna -> $(SEC_CONFIG) ; + /var/lock/subsys/crond -> $(SEC_CONFIG) ; + #/var/lock/subsys/cWnn -> $(SEC_CONFIG) ; + #/var/lock/subsys/dhcpd -> $(SEC_CONFIG) ; + #/var/lock/subsys/firewall -> $(SEC_CONFIG) ; + #/var/lock/subsys/freeWnn -> $(SEC_CONFIG) ; + #/var/lock/subsys/gated -> $(SEC_CONFIG) ; + /var/lock/subsys/gpm -> $(SEC_CONFIG) ; + #/var/lock/subsys/httpd -> $(SEC_CONFIG) ; + #/var/lock/subsys/identd -> $(SEC_CONFIG) ; + #/var/lock/subsys/innd -> $(SEC_CONFIG) ; + /var/lock/subsys/ipchains -> $(SEC_CONFIG) ; + #/var/lock/subsys/iptables -> $(SEC_CONFIG) ; + #/var/lock/subsys/ipvsadm -> $(SEC_CONFIG) ; + #/var/lock/subsys/irda -> $(SEC_CONFIG) ; + #/var/lock/subsys/iscsi -> $(SEC_CONFIG) ; + #/var/lock/subsys/isdn -> $(SEC_CONFIG) ; + #/var/lock/subsys/junkbuster -> $(SEC_CONFIG) ; + #/var/lock/subsys/kadmin -> $(SEC_CONFIG) ; + /var/lock/subsys/keytable -> $(SEC_CONFIG) ; + #/var/lock/subsys/kprop -> $(SEC_CONFIG) ; + #/var/lock/subsys/krb524 -> $(SEC_CONFIG) ; + #/var/lock/subsys/krb5kdc -> $(SEC_CONFIG) ; + /var/lock/subsys/kudzu -> $(SEC_CONFIG) ; + #/var/lock/subsys/kWnn -> $(SEC_CONFIG) ; + #/var/lock/subsys/ldap -> $(SEC_CONFIG) ; + #/var/lock/subsys/linuxconf -> $(SEC_CONFIG) ; + #/var/lock/subsys/lpd -> $(SEC_CONFIG) ; + #/var/lock/subsys/mars_nwe -> $(SEC_CONFIG) ; + #/var/lock/subsys/mcserv -> $(SEC_CONFIG) ; + #/var/lock/subsys/mysqld -> $(SEC_CONFIG) ; + #/var/lock/subsys/named -> $(SEC_CONFIG) ; + /var/lock/subsys/netfs -> $(SEC_CONFIG) ; + /var/lock/subsys/network -> $(SEC_CONFIG) ; + #/var/lock/subsys/nfs -> $(SEC_CONFIG) ; + /var/lock/subsys/nfslock -> $(SEC_CONFIG) ; + #/var/lock/subsys/nscd -> $(SEC_CONFIG) ; + #/var/lock/subsys/ntpd -> $(SEC_CONFIG) ; + #/var/lock/subsys/ospf6d -> $(SEC_CONFIG) ; + #/var/lock/subsys/ospfd -> $(SEC_CONFIG) ; + /var/lock/subsys/pcmcia -> $(SEC_CONFIG) ; + /var/lock/subsys/portmap -> $(SEC_CONFIG) ; + #/var/lock/subsys/postgresql -> $(SEC_CONFIG) ; + #/var/lock/subsys/pxe -> $(SEC_CONFIG) ; + #/var/lock/subsys/radvd -> $(SEC_CONFIG) ; + /var/lock/subsys/random -> $(SEC_CONFIG) ; + #/var/lock/subsys/rarpd -> $(SEC_CONFIG) ; + /var/lock/subsys/reconfig -> $(SEC_CONFIG) ; + /var/lock/subsys/rhnsd -> $(SEC_CONFIG) ; + #/var/lock/subsys/ripd -> $(SEC_CONFIG) ; + #/var/lock/subsys/ripngd -> $(SEC_CONFIG) ; + #/var/lock/subsys/routed -> $(SEC_CONFIG) ; + #/var/lock/subsys/rstatd -> $(SEC_CONFIG) ; + #/var/lock/subsys/rusersd -> $(SEC_CONFIG) ; + #/var/lock/subsys/rwalld -> $(SEC_CONFIG) ; + #/var/lock/subsys/rwhod -> $(SEC_CONFIG) ; + /var/lock/subsys/sendmail -> $(SEC_CONFIG) ; + #/var/lock/subsys/smb -> $(SEC_CONFIG) ; + #/var/lock/subsys/snmpd -> $(SEC_CONFIG) ; + #/var/lock/subsys/squid -> $(SEC_CONFIG) ; + /var/lock/subsys/sshd -> $(SEC_CONFIG) ; + /var/lock/subsys/syslog -> $(SEC_CONFIG) ; + #/var/lock/subsys/tux -> $(SEC_CONFIG) ; + #/var/lock/subsys/tWnn -> $(SEC_CONFIG) ; + #/var/lock/subsys/ups -> $(SEC_CONFIG) ; + #/var/lock/subsys/vncserver -> $(SEC_CONFIG) ; + #/var/lock/subsys/wine -> $(SEC_CONFIG) ; + /var/lock/subsys/xfs -> $(SEC_CONFIG) ; + /var/lock/subsys/xinetd -> $(SEC_CONFIG) ; + /var/lock/subsys/ypbind -> $(SEC_CONFIG) ; + #/var/lock/subsys/yppasswdd -> $(SEC_CONFIG) ; + #/var/lock/subsys/ypserv -> $(SEC_CONFIG) ; + #/var/lock/subsys/ypxfrd -> $(SEC_CONFIG) ; + #/var/lock/subsys/zebra -> $(SEC_CONFIG) ; + /var/run -> $(SEC_CONFIG) ; + /var/log -> $(SEC_CONFIG) ; + /etc/ioctl.save -> $(SEC_CONFIG) ; + /etc/issue.net -> $(SEC_CONFIG) -i ; # Inode number changes + /etc/issue -> $(SEC_CONFIG) ; + /etc/mtab -> $(SEC_CONFIG) -i ; # Inode number changes on any mount/unmount + /lib/modules -> $(SEC_CONFIG) ; + /etc/.pwd.lock -> $(SEC_CONFIG) ; + # /lib/modules/preferred -> $(SEC_CONFIG) ; #Uncomment when this file exists +} + +# These files change the behavior of the root account +( + rulename = "Root config files", + severity = 100 +) +{ + /root -> $(SEC_CRIT) ; # Catch all additions to /root + #/root/.Xresources -> $(SEC_CONFIG) ; + /root/.bashrc -> $(SEC_CONFIG) ; + /root/.bash_profile -> $(SEC_CONFIG) ; + /root/.bash_logout -> $(SEC_CONFIG) ; + /root/.cshrc -> $(SEC_CONFIG) ; + /root/.tcshrc -> $(SEC_CONFIG) ; + /root/Mail -> $(SEC_CONFIG) ; + #/root/mail -> $(SEC_CONFIG) ; + #/root/.amandahosts -> $(SEC_CONFIG) ; + #/root/.addressbook.lu -> $(SEC_CONFIG) ; + #/root/.addressbook -> $(SEC_CONFIG) ; + /root/.bash_history -> $(SEC_CONFIG) ; + /root/.elm -> $(SEC_CONFIG) ; + #/root/.esd_auth -> $(SEC_CONFIG) ; + /root/.gnome_private -> $(SEC_CONFIG) ; + /root/.gnome-desktop -> $(SEC_CONFIG) ; + /root/.gnome -> $(SEC_CONFIG) ; + /root/.ICEauthority -> $(SEC_CONFIG) ; + #/root/.mc -> $(SEC_CONFIG) ; + #/root/.pinerc -> $(SEC_CONFIG) ; + /root/.sawfish -> $(SEC_CONFIG) ; + /root/.Xauthority -> $(SEC_CONFIG) -i ; # Changes Inode number on login + #/root/.xauth -> $(SEC_CONFIG) ; + /root/.xsession-errors -> $(SEC_CONFIG) ; +} + + ################################ + # ## +################################ # +# # # +# Critical configuration files # # +# ## +################################ +( + rulename = "Critical configuration files", + severity = $(SIG_HI) +) +{ + #/etc/conf.linuxconf -> $(SEC_BIN) ; + /etc/crontab -> $(SEC_BIN) ; + /etc/cron.hourly -> $(SEC_BIN) ; + /etc/cron.daily -> $(SEC_BIN) ; + /etc/cron.weekly -> $(SEC_BIN) ; + /etc/cron.monthly -> $(SEC_BIN) ; + /etc/default -> $(SEC_BIN) ; + /etc/fstab -> $(SEC_BIN) ; + /etc/exports -> $(SEC_BIN) ; + /etc/group- -> $(SEC_BIN) ; # changes should be infrequent + /etc/host.conf -> $(SEC_BIN) ; + /etc/hosts.allow -> $(SEC_BIN) ; + /etc/hosts.deny -> $(SEC_BIN) ; + /etc/httpd/conf -> $(SEC_BIN) ; # changes should be infrequent + /etc/protocols -> $(SEC_BIN) ; + /etc/services -> $(SEC_BIN) ; + /etc/rc.d/init.d -> $(SEC_BIN) ; + /etc/rc.d -> $(SEC_BIN) ; + /etc/mail.rc -> $(SEC_BIN) ; + /etc/modules.conf -> $(SEC_BIN) ; + /etc/motd -> $(SEC_BIN) ; + /etc/named.conf -> $(SEC_BIN) ; + /etc/passwd -> $(SEC_CONFIG) ; + /etc/passwd- -> $(SEC_CONFIG) ; + /etc/profile.d -> $(SEC_BIN) ; + /var/lib/nfs/rmtab -> $(SEC_BIN) ; + /usr/sbin/fixrmtab -> $(SEC_BIN) ; + /etc/rpc -> $(SEC_BIN) ; + /etc/sysconfig -> $(SEC_BIN) ; + /etc/samba/smb.conf -> $(SEC_CONFIG) ; + #/etc/gettydefs -> $(SEC_BIN) ; + /etc/nsswitch.conf -> $(SEC_BIN) ; + /etc/yp.conf -> $(SEC_BIN) ; + /etc/hosts -> $(SEC_CONFIG) ; + /etc/xinetd.conf -> $(SEC_CONFIG) ; + /etc/inittab -> $(SEC_CONFIG) ; + /etc/resolv.conf -> $(SEC_CONFIG) ; + /etc/syslog.conf -> $(SEC_CONFIG) ; +} + + #################### + # ## +#################### # +# # # +# Critical devices # # +# ## +#################### +( + rulename = "Critical devices", + severity = $(SIG_HI), + recurse = false +) +{ + /dev/kmem -> $(Device) ; + /dev/mem -> $(Device) ; + /dev/null -> $(Device) ; + /dev/zero -> $(Device) ; + /proc/devices -> $(Device) ; + /proc/net -> $(Device) ; + /proc/sys -> $(Device) ; + /proc/cpuinfo -> $(Device) ; + /proc/modules -> $(Device) ; + /proc/mounts -> $(Device) ; + /proc/dma -> $(Device) ; + /proc/filesystems -> $(Device) ; + /proc/pci -> $(Device) ; + /proc/interrupts -> $(Device) ; + /proc/driver/rtc -> $(Device) ; + /proc/ioports -> $(Device) ; + #/proc/scsi -> $(Device) ; + /proc/kcore -> $(Device) ; + /proc/self -> $(Device) ; + /proc/kmsg -> $(Device) ; + /proc/stat -> $(Device) ; + /proc/ksyms -> $(Device) ; + /proc/loadavg -> $(Device) ; + /proc/uptime -> $(Device) ; + /proc/locks -> $(Device) ; + /proc/version -> $(Device) ; + /proc/mdstat -> $(Device) ; + /proc/meminfo -> $(Device) ; + /proc/cmdline -> $(Device) ; + /proc/misc -> $(Device) ; +} + +# Rest of critical system binaries +( + rulename = "OS executables and libraries", + severity = $(SIG_HI) +) +{ + /bin -> $(SEC_BIN) ; + /lib -> $(SEC_BIN) ; +} + +#============================================================================= +# +# Copyright 2000 Tripwire, Inc. Tripwire is a registered trademark of Tripwire, +# Inc. in the United States and other countries. All rights reserved. +# +# Linux is a registered trademark of Linus Torvalds. +# +# UNIX is a registered trademark of The Open Group. +# +#============================================================================= +# +# Permission is granted to make and distribute verbatim copies of this document +# provided the copyright notice and this permission notice are preserved on all +# copies. +# +# Permission is granted to copy and distribute modified versions of this +# document under the conditions for verbatim copying, provided that the entire +# resulting derived work is distributed under the terms of a permission notice +# identical to this one. +# +# Permission is granted to copy and distribute translations of this document +# into another language, under the above conditions for modified versions, +# except that this permission notice may be stated in a translation approved by +# Tripwire, Inc. +# +# DCM +# +# $Id: twpol-GENERIC.txt,v 1.1 2003/06/08 02:00:06 pherman Exp $ +# diff --git a/meta-security/recipes-security/tripwire/tripwire_2.4.3.6.bb b/meta-security/recipes-security/tripwire/tripwire_2.4.3.6.bb new file mode 100644 index 000000000..465960f23 --- /dev/null +++ b/meta-security/recipes-security/tripwire/tripwire_2.4.3.6.bb @@ -0,0 +1,66 @@ +SUMMARY = "Tripwire: A system integrity assessment tool (IDS)" +DESCRIPTION = "Open Source Tripwire® software is a security and data \ +integrity tool useful for monitoring and alerting on specific file change(s) on a range of systems" +HOMEPAGE="http://sourceforge.net/projects/tripwire" +SECTION = "security Monitor/Admin" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://COPYING;md5=1c069be8dbbe48e89b580ab4ed86c127" + +SRCREV = "80db91b4c1ca4be9efafd2286e3b2ad32ba4c34c" + +SRC_URI = "\ + git://github.com/Tripwire/tripwire-open-source.git \ + file://tripwire.cron \ + file://tripwire.sh \ + file://tripwire.txt \ + file://twcfg.txt \ + file://twinstall.sh \ + file://twpol-yocto.txt \ + " + +S = "${WORKDIR}/git" + +inherit autotools-brokensep update-rc.d + +INITSCRIPT_NAME = "tripwire" +INITSCRIPT_PARAMS = "start 40 S ." +TRIPWIRE_HOST = "${HOST_SYS}" +TRIPWIRE_TARGET = "${TARGET_SYS}" + +CXXFLAGS += "-fno-strict-aliasing" +EXTRA_OECONF = "--disable-openssl --enable-static --sysconfdir=/etc/tripwire" + +do_install () { + install -d ${D}${libdir} ${D}${datadir} ${D}${base_libdir} + install -d ${D}${sysconfdir} ${D}${mandir} ${D}${sbindir} + install -d ${D}${sysconfdir}/${PN} + install -d ${D}${localstatedir}/lib/${PN} ${D}${localstatedir}/lib/${BPN}/report + install -d ${D}${mandir}/man4 ${D}${mandir}/man5 ${D}${mandir}/man8 + install -d ${D}${docdir}/${BPN} ${D}${docdir}/${BPN}/templates + install -d ${D}${sysconfdir}/init.d + + install -m 0755 ${S}/bin/* ${D}${sbindir} + install -m 0644 ${S}/lib/* ${D}${base_libdir} + install -m 0644 ${S}/lib/* ${D}${localstatedir}/lib/${PN} + install -m 0755 ${WORKDIR}/tripwire.cron ${D}${sysconfdir} + install -m 0755 ${WORKDIR}/tripwire.sh ${D}${sysconfdir}/init.d/tripwire + install -m 0755 ${WORKDIR}/twinstall.sh ${D}${sysconfdir}/${PN} + install -m 0644 ${WORKDIR}/twpol-yocto.txt ${D}${sysconfdir}/${PN}/twpol.txt + install -m 0644 ${WORKDIR}/twcfg.txt ${D}${sysconfdir}/${PN} + + install -m 0644 ${S}/man/man4/* ${D}${mandir}/man4 + install -m 0644 ${S}/man/man5/* ${D}${mandir}/man5 + install -m 0644 ${S}/man/man8/* ${D}${mandir}/man8 + install -m 0644 ${S}/policy/templates/* ${D}${docdir}/${BPN}/templates + install -m 0644 ${S}/policy/*txt ${D}${docdir}/${BPN} + install -m 0644 ${S}/COPYING ${D}${docdir}/${BPN} + install -m 0644 ${S}/TRADEMARK ${D}${docdir}/${BPN} + install -m 0644 ${WORKDIR}/tripwire.txt ${D}${docdir}/${BPN} +} + + +FILES_${PN} += "${libdir} ${docdir}/${PN}/*" +FILES_${PN}-dbg += "${sysconfdir}/${PN}/.debug" +FILES_${PN}-staticdev += "${localstatedir}/lib/${PN}/lib*.a" + +RDEPENDS_${PN} += " perl nano msmtp cronie" diff --git a/meta-security/recipes-security/xmlsec1/xmlsec1/change-finding-path-of-nss.patch b/meta-security/recipes-security/xmlsec1/xmlsec1/change-finding-path-of-nss.patch new file mode 100644 index 000000000..fcc63b34c --- /dev/null +++ b/meta-security/recipes-security/xmlsec1/xmlsec1/change-finding-path-of-nss.patch @@ -0,0 +1,72 @@ +From 47379747e34f952d31af028c672940ca7859ae3c Mon Sep 17 00:00:00 2001 +From: Yulong Pei <Yulong.pei@windriver.com> +Date: Wed, 21 Jul 2010 22:33:43 +0800 +Subject: [PATCH] change finding path of nss and nspr + +Upstream-Status: Pending + +Signed-off-by: Yulong Pei <Yulong.pei@windriver.com> +Signed-off-by: Mingli Yu <Mingli.Yu@windriver.com> + +--- + configure.ac | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 3278200..6edec7d 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -644,7 +644,7 @@ if test "z$NSS_FOUND" = "zno" ; then + + if test "z$with_nspr" != "z" ; then + NSPR_PREFIX="$with_nspr" +- NSPR_CFLAGS="-I$with_nspr/include -I$with_nspr/include/nspr" ++ NSPR_CFLAGS="-I$with_nspr/usr/include -I$with_nspr/usr/include/nspr4" + if test "z$with_gnu_ld" = "zyes" ; then + NSPR_LIBS="-Wl,-rpath-link -Wl,$with_nspr/lib -L$with_nspr/lib $NSPR_LIBS_LIST" + else +@@ -652,7 +652,7 @@ if test "z$NSS_FOUND" = "zno" ; then + fi + NSPR_INCLUDES_FOUND="yes" + NSPR_LIBS_FOUND="yes" +- NSPR_PRINIT_H="$with_nspr/include/prinit.h" ++ NSPR_PRINIT_H="$with_nspr/usr/include/nspr4/prinit.h" + else + for dir in $ac_nss_inc_dir ; do + if test -f $dir/nspr/prinit.h ; then +@@ -690,7 +690,7 @@ if test "z$NSS_FOUND" = "zno" ; then + OLD_CPPFLAGS=$CPPFLAGS + CPPFLAGS="$NSPR_CFLAGS" + AC_EGREP_CPP(yes,[ +- #include <prinit.h> ++ #include <nspr4/prinit.h> + #if PR_VMAJOR >= 4 + yes + #endif +@@ -715,7 +715,7 @@ if test "z$NSS_FOUND" = "zno" ; then + NSS_NSS_H="" + + if test "z$with_nss" != "z" ; then +- NSS_CFLAGS="$NSS_CFLAGS -I$with_nss/include -I$with_nss/include/nss" ++ NSS_CFLAGS="$NSS_CFLAGS -I$with_nss/usr/include -I$with_nss/usr/include/nss3 -I$with_nspr/usr/include/nspr4" + if test "z$with_gnu_ld" = "zyes" ; then + NSS_LIBS="$NSS_LIBS -Wl,-rpath-link -Wl,$with_nss/lib -L$with_nss/lib $NSS_LIBS_LIST" + else +@@ -723,7 +723,7 @@ if test "z$NSS_FOUND" = "zno" ; then + fi + NSS_INCLUDES_FOUND="yes" + NSS_LIBS_FOUND="yes" +- NSS_NSS_H="$with_nss/include/nss.h" ++ NSS_NSS_H="$with_nss/usr/include/nss3/nss.h" + else + for dir in $ac_nss_inc_dir ; do + if test -f $dir/nss/nss.h ; then +@@ -761,7 +761,7 @@ if test "z$NSS_FOUND" = "zno" ; then + OLD_CPPFLAGS=$CPPFLAGS + CPPFLAGS="$NSPR_CFLAGS $NSS_CFLAGS" + AC_EGREP_CPP(yes,[ +- #include <nss.h> ++ #include <nss3/nss.h> + #if NSS_VMAJOR >= 3 && NSS_VMINOR >= 2 + yes + #endif diff --git a/meta-security/recipes-security/xmlsec1/xmlsec1/fix-ltmain.sh.patch b/meta-security/recipes-security/xmlsec1/xmlsec1/fix-ltmain.sh.patch new file mode 100644 index 000000000..af598fe74 --- /dev/null +++ b/meta-security/recipes-security/xmlsec1/xmlsec1/fix-ltmain.sh.patch @@ -0,0 +1,26 @@ +From 847dc52f5a50e34ee4d6e3dc2c708711747a58ca Mon Sep 17 00:00:00 2001 +From: Yulong Pei <Yulong.pei@windriver.com> +Date: Thu, 21 Jan 2010 14:11:20 +0800 +Subject: [PATCH] force to use our own libtool + +Upstream-Status: Inappropriate [ OE specific ] + +Signed-off-by: Yulong Pei <Yulong.pei@windriver.com> + +--- + ltmain.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ltmain.sh b/ltmain.sh +index 147d758..a61f16b 100644 +--- a/ltmain.sh ++++ b/ltmain.sh +@@ -6969,7 +6969,7 @@ func_mode_link () + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in +- [\\/]* | [A-Za-z]:[\\/]*) ;; ++ =* | [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ diff --git a/meta-security/recipes-security/xmlsec1/xmlsec1/makefile-ptest.patch b/meta-security/recipes-security/xmlsec1/xmlsec1/makefile-ptest.patch new file mode 100644 index 000000000..d45356924 --- /dev/null +++ b/meta-security/recipes-security/xmlsec1/xmlsec1/makefile-ptest.patch @@ -0,0 +1,40 @@ +From 83a1381e1d6bd1b5ec3df6f7c4bc1f4fe4f860b6 Mon Sep 17 00:00:00 2001 +From: Jackie Huang <jackie.huang@windriver.com> +Date: Thu, 15 Jun 2017 14:44:01 +0800 +Subject: [PATCH] xmlsec1: add new recipe + +This enables the building of the examples directory +and it's installed as ptest. + +Upstream-Status: Inappropriate [ OE ptest specific ] + +Signed-off-by: Jackie Huang <jackie.huang@windriver.com> + +--- + examples/Makefile | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/examples/Makefile b/examples/Makefile +index 89b1d61..c1cbcca 100644 +--- a/examples/Makefile ++++ b/examples/Makefile +@@ -8,9 +8,17 @@ PROGRAMS = \ + decrypt1 decrypt2 decrypt3 \ + xmldsigverify + ++ifndef CC + CC = gcc +-CFLAGS += -g $(shell xmlsec1-config --cflags) -DUNIX_SOCKETS +-LDLIBS += -g $(shell xmlsec1-config --libs) ++endif ++ ++CFLAGS += -I../include -g $(shell PKG_CONFIG_PATH=.. pkg-config --cflags xmlsec1 ) -DUNIX_SOCKETS ++LDLIBS += -L../src/.libs -g $(shell PKG_CONFIG_PATH=.. pkg-config --libs xmlsec1 ) ++ ++DESTDIR = /usr/share/xmlsec1 ++install-ptest: ++ if [ ! -d $(DESTDIR) ]; then mkdir -p $(DESTDIR); fi ++ cp * $(DESTDIR) + + all: $(PROGRAMS) + diff --git a/meta-security/recipes-security/xmlsec1/xmlsec1/run-ptest b/meta-security/recipes-security/xmlsec1/xmlsec1/run-ptest new file mode 100755 index 000000000..a203c38f2 --- /dev/null +++ b/meta-security/recipes-security/xmlsec1/xmlsec1/run-ptest @@ -0,0 +1,85 @@ +#!/bin/sh + +check_return() { + if [ $? == 0 ]; then + echo -e "PASS: $1\n" + else + echo -e "FAIL: $1\n" + fi +} + +echo "---------------------------------------------------" +echo "Signing a template file..." +./sign1 sign1-tmpl.xml rsakey.pem > sign1-res.xml +./verify1 sign1-res.xml rsapub.pem +check_return sign-tmpl + +echo "---------------------------------------------------" +echo "Signing a dynamicaly created template..." +./sign2 sign2-doc.xml rsakey.pem > sign2-res.xml +./verify1 sign2-res.xml rsapub.pem +check_return sign-dynamic-templ + +echo "---------------------------------------------------" +echo "Signing with X509 certificate..." +./sign3 sign3-doc.xml rsakey.pem rsacert.pem > sign3-res.xml +./verify3 sign3-res.xml ca2cert.pem cacert.pem +check_return sign-x509 + +echo "---------------------------------------------------" +echo "Verifying a signature with a single key..." +./verify1 sign1-res.xml rsapub.pem +./verify1 sign2-res.xml rsapub.pem +check_return verify-single-key + +echo "---------------------------------------------------" +echo "Verifying a signature with keys manager..." +./verify2 sign1-res.xml rsapub.pem +./verify2 sign2-res.xml rsapub.pem +check_return verify-keys-manager + +echo "---------------------------------------------------" +echo "Verifying a signature with X509 certificates..." +./verify3 sign3-res.xml ca2cert.pem cacert.pem +check_return verify-x509 + +echo "---------------------------------------------------" +echo "Verifying a signature with additional restrictions..." +./verify4 verify4-res.xml ca2cert.pem cacert.pem +check_return verify-res + +echo "---------------------------------------------------" +echo "Encrypting data with a template file..." +./encrypt1 encrypt1-tmpl.xml deskey.bin > encrypt1-res.xml +./decrypt1 encrypt1-res.xml deskey.bin +check_return encrypt-tmpl + +echo "---------------------------------------------------" +echo "Encrypting data with a dynamicaly created template..." +./encrypt2 encrypt2-doc.xml deskey.bin > encrypt2-res.xml +./decrypt1 encrypt2-res.xml deskey.bin +check_return encrypt-dynamic-tmpl + +echo "---------------------------------------------------" +echo "Encrypting data with a session key..." +./encrypt3 encrypt3-doc.xml rsakey.pem > encrypt3-res.xml +./decrypt3 encrypt3-res.xml +check_return encrypt-session-key + +echo "---------------------------------------------------" +echo "Decrypting data with a single key..." +./decrypt1 encrypt1-res.xml deskey.bin +./decrypt1 encrypt2-res.xml deskey.bin +check_return encrypt-single-key + +echo "---------------------------------------------------" +echo "Decrypting data with keys manager..." +./decrypt2 encrypt1-res.xml deskey.bin +./decrypt2 encrypt2-res.xml deskey.bin +check_return encrypt-keys-manager + +echo "---------------------------------------------------" +echo "Writing a custom keys manager..." +./decrypt3 encrypt1-res.xml +./decrypt3 encrypt2-res.xml +check_return write-keys-manager diff --git a/meta-security/recipes-security/xmlsec1/xmlsec1/xmlsec1-examples-allow-build-in-separate-dir.patch b/meta-security/recipes-security/xmlsec1/xmlsec1/xmlsec1-examples-allow-build-in-separate-dir.patch new file mode 100644 index 000000000..8b2533ed9 --- /dev/null +++ b/meta-security/recipes-security/xmlsec1/xmlsec1/xmlsec1-examples-allow-build-in-separate-dir.patch @@ -0,0 +1,30 @@ +From 0c38c6864e7ba8f53a657d87894f24374a6a4932 Mon Sep 17 00:00:00 2001 +From: Jackie Huang <jackie.huang@windriver.com> +Date: Tue, 30 Dec 2014 11:18:17 +0800 +Subject: [PATCH] examples: allow build in separate dir + +Upstream-Status: Inappropriate [ OE specific ] + +Signed-off-by: Jackie Huang <jackie.huang@windriver.com> + +--- + examples/Makefile | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/examples/Makefile b/examples/Makefile +index c1cbcca..3f1bd14 100644 +--- a/examples/Makefile ++++ b/examples/Makefile +@@ -12,8 +12,10 @@ ifndef CC + CC = gcc + endif + +-CFLAGS += -I../include -g $(shell PKG_CONFIG_PATH=.. pkg-config --cflags xmlsec1 ) -DUNIX_SOCKETS +-LDLIBS += -L../src/.libs -g $(shell PKG_CONFIG_PATH=.. pkg-config --libs xmlsec1 ) ++top_srcdir = .. ++top_builddir = .. ++CFLAGS += -I$(top_srcdir)/include -g $(shell PKG_CONFIG_PATH=$(top_srcdir) pkg-config --cflags xmlsec1 ) -DUNIX_SOCKETS ++LDLIBS += -L$(top_builddir)/src/.libs -g $(shell PKG_CONFIG_PATH=$(top_srcdir) pkg-config --libs xmlsec1 ) + + DESTDIR = /usr/share/xmlsec1 + install-ptest: diff --git a/meta-security/recipes-security/xmlsec1/xmlsec1/xmlsec1-fix-a-typo-in-examples-verify3.c.patch b/meta-security/recipes-security/xmlsec1/xmlsec1/xmlsec1-fix-a-typo-in-examples-verify3.c.patch new file mode 100644 index 000000000..5f967bbaa --- /dev/null +++ b/meta-security/recipes-security/xmlsec1/xmlsec1/xmlsec1-fix-a-typo-in-examples-verify3.c.patch @@ -0,0 +1,23 @@ +From 1d8ae4b32bd76c19ec238f30eb9b1ee582cbe990 Mon Sep 17 00:00:00 2001 +From: Jackie Huang <jackie.huang@windriver.com> +Date: Fri, 2 Mar 2018 01:10:58 -0800 +Subject: [PATCH] xmlsec1: fix a typo in examples/verify3.c + +Upstream-Status: Submitted [https://github.com/lsh123/xmlsec/pull/153] + +Signed-off-by: Jackie Huang <jackie.huang@windriver.com> + +--- + examples/verify3.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/examples/verify3.c b/examples/verify3.c +index 2d26ae7..68f52ab 100644 +--- a/examples/verify3.c ++++ b/examples/verify3.c +@@ -1,4 +1,4 @@ +-4/** ++/** + * XML Security Library example: Verifying a file signed with X509 certificate + * + * Verifies a file signed with X509 certificate. diff --git a/meta-security/recipes-security/xmlsec1/xmlsec1_1.2.25.bb b/meta-security/recipes-security/xmlsec1/xmlsec1_1.2.25.bb new file mode 100644 index 000000000..341ca08fd --- /dev/null +++ b/meta-security/recipes-security/xmlsec1/xmlsec1_1.2.25.bb @@ -0,0 +1,57 @@ +SUMMARY = "XML Security Library is a C library based on LibXML2" +DESCRIPTION = "\ + XML Security Library is a C library based on \ + LibXML2 and OpenSSL. The library was created with a goal to support major \ + XML security standards "XML Digital Signature" and "XML Encryption". \ + " +HOMEPAGE = "http://www.aleksey.com/xmlsec/" +DEPENDS = "libtool libxml2 libxslt openssl zlib libgcrypt gnutls nss nspr libgpg-error" + +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://COPYING;md5=352791d62092ea8104f085042de7f4d0" + +SECTION = "libs" + +SRC_URI = "http://www.aleksey.com/xmlsec/download/${BP}.tar.gz \ + file://fix-ltmain.sh.patch \ + file://change-finding-path-of-nss.patch \ + file://makefile-ptest.patch \ + file://xmlsec1-examples-allow-build-in-separate-dir.patch \ + file://xmlsec1-fix-a-typo-in-examples-verify3.c.patch \ + file://run-ptest \ + " + +SRC_URI[md5sum] = "dbbef1efc69e61bc4629650205a05b41" +SRC_URI[sha256sum] = "967ca83edf25ccb5b48a3c4a09ad3405a63365576503bf34290a42de1b92fcd2" + +inherit autotools-brokensep ptest pkgconfig + +CFLAGS += "-I${STAGING_INCDIR}/nspr4 -I${STAGING_INCDIR}/nss3" +CPPFLAGS += "-I${STAGING_INCDIR}/nspr4 -I${STAGING_INCDIR}/nss3" + +EXTRA_OECONF = "\ + --with-nss=${STAGING_LIBDIR}/../.. --with-nspr=${STAGING_LIBDIR}/../.. \ + " + +FILES_${PN}-dev += "${libdir}/xmlsec1Conf.sh" +FILES_${PN}-dbg += "${PTEST_PATH}/.debug/*" + +RDEPENDS_${PN}-ptest += "${PN}-dev" +INSANE_SKIP_${PN}-ptest += "dev-deps" + +PTEST_EXTRA_ARGS = "top_srcdir=${S} top_builddir=${B}" + +do_compile_ptest () { + oe_runmake -C ${S}/examples ${PTEST_EXTRA_ARGS} all +} + +do_install_append() { + for i in ${bindir}/xmlsec1-config ${libdir}/xmlsec1Conf.sh \ + ${libdir}/pkgconfig/xmlsec1-openssl.pc; do + sed -i -e "s@${RECIPE_SYSROOT}@@g" ${D}$i + done +} + +do_install_ptest () { + oe_runmake -C ${S}/examples DESTDIR=${D}${PTEST_PATH} ${PTEST_EXTRA_ARGS} install-ptest +} |