diff options
-rw-r--r-- | Makefile | 50 | ||||
-rw-r--r-- | conf/perm.0 | 36 | ||||
-rw-r--r-- | conf/perm.1 | 32 | ||||
-rw-r--r-- | conf/perm.2 | 32 | ||||
-rw-r--r-- | conf/perm.3 | 34 | ||||
-rw-r--r-- | conf/perm.4 | 36 | ||||
-rw-r--r-- | conf/perm.5 | 46 | ||||
-rw-r--r-- | conf/perm.snf | 38 | ||||
-rwxr-xr-x | cron-sh/diff_check.sh | 56 | ||||
-rwxr-xr-x | cron-sh/security.sh | 36 | ||||
-rwxr-xr-x | cron-sh/security_check.sh | 24 | ||||
-rwxr-xr-x | init-sh/cleanold.sh | 133 | ||||
-rwxr-xr-x | msec.sh | 2 | ||||
-rw-r--r-- | msec.spec | 105 | ||||
-rw-r--r-- | share/.cvsignore | 2 | ||||
-rw-r--r-- | share/CHANGES | 40 | ||||
-rw-r--r-- | share/Config.py | 46 | ||||
-rw-r--r-- | share/ConfigFile.py | 376 | ||||
-rw-r--r-- | share/Log.py | 53 | ||||
-rwxr-xr-x | share/Perms.py | 173 | ||||
-rw-r--r-- | share/README | 66 | ||||
-rwxr-xr-x | share/compile.py | 17 | ||||
-rw-r--r-- | share/libmsec.py | 488 | ||||
-rwxr-xr-x | share/msec | 48 | ||||
-rwxr-xr-x | share/msec.py | 195 |
25 files changed, 1955 insertions, 209 deletions
@@ -3,11 +3,10 @@ VERSION := $(shell grep 'Version:' $(PACKAGE).spec| cut -f 2) RELEASE := $(shell grep 'Release:' $(PACKAGE).spec| cut -f 2) TAG := $(shell echo "V$(VERSION)_$(RELEASE)" | tr -- '-.' '__') -all: promisc_check msec_find +all: promisc_check msec_find python clean: - -find . -name '*.o' -exec rm -f {} \; - -find . -name '*~' -exec rm -f {} \; + -find . -name '*.o' -o -name '*.pyc' -o -name '*~' -exec rm -f {} \; rm -f src/promisc_check/promisc_check rm -f src/msec_find/msec_find @@ -17,29 +16,30 @@ promisc_check: msec_find: (cd src/msec_find && make) +python: + -cd share; ./msec.py -h + install: - (mkdir -p $(RPM_BUILD_ROOT)/etc/security/msec) - (mkdir -p $(RPM_BUILD_ROOT)/usr/share/msec) - (mkdir -p $(RPM_BUILD_ROOT)/usr/sbin) - (cp init-sh/*.sh $(RPM_BUILD_ROOT)/usr/share/msec) - (cp cron-sh/*.sh $(RPM_BUILD_ROOT)/usr/share/msec) - (cp init-sh/msec $(RPM_BUILD_ROOT)/usr/sbin) - (cp conf/perm.* conf/server.* $(RPM_BUILD_ROOT)/etc/security/msec) - - (mkdir -p $(RPM_BUILD_ROOT)/var/log) - (mkdir -p $(RPM_BUILD_ROOT)/var/log/security) - (touch $(RPM_BUILD_ROOT)/etc/security/msec/security.conf) - (touch $(RPM_BUILD_ROOT)/var/log/security.log) - (cd src/promisc_check && make install) - (cd src/msec_find && make install) - (mkdir -p $(RPM_BUILD_ROOT)/usr/man/man8/) - install -d $(RPM_BUILD_ROOT)/usr/man/man8/ - install -m644 man/C/*8 $(RPM_BUILD_ROOT)/usr/man/man8/ - bzip2 -9f $(RPM_BUILD_ROOT)/usr/man/man8/*8 + mkdir -p $RPM_BUILD_ROOT/etc/security/msec + mkdir -p $RPM_BUILD_ROOT/usr/share/msec + mkdir -p $RPM_BUILD_ROOT/usr/sbin + cp init-sh/*.sh $RPM_BUILD_ROOT/usr/share/msec + cp cron-sh/*.sh $RPM_BUILD_ROOT/usr/share/msec + cp init-sh/msec $RPM_BUILD_ROOT/usr/sbin + cp conf/perm.* conf/server.* $RPM_BUILD_ROOT/etc/security/msec + + mkdir -p $RPM_BUILD_ROOT/var/log + mkdir -p $RPM_BUILD_ROOT/var/log/security + touch $RPM_BUILD_ROOT/etc/security/msec/security.conf + touch $RPM_BUILD_ROOT/var/log/security.log + cd src/promisc_check && make install + cd src/msec_find && make install + mkdir -p $RPM_BUILD_ROOT/usr/share/man/man8/ + install -d $(RPM_BUILD_ROOT)/usr/share/man/man8/ + install -m644 man/C/*8 $(RPM_BUILD_ROOT)/usr/share/man/man8/ for i in man/??* ; do \ - install -d $(RPM_BUILD_ROOT)/usr/man/`basename $$i`/man8 ; \ - install -m 644 $$i/*.8 $(RPM_BUILD_ROOT)/usr/man/`basename $$i`/man8 ; \ - bzip2 -9f $(RPM_BUILD_ROOT)/usr/man/`basename $$i`/man8/*8 ; \ + install -d $(RPM_BUILD_ROOT)/usr/share/man/`basename $$i`/man8 ; \ + install -m 644 $$i/*.8 $(RPM_BUILD_ROOT)/usr/share/man/`basename $$i`/man8 ; \ done version: @@ -47,7 +47,7 @@ version: # rules to build a test rpm -localrpm: localdist buildrpm +localrpm: clean localdist buildrpm localdist: cleandist dir localcopy tar diff --git a/conf/perm.0 b/conf/perm.0 index 1cc7203..92adab5 100644 --- a/conf/perm.0 +++ b/conf/perm.0 @@ -1,10 +1,9 @@ -# Welcome in Level 1 +# Welcome in Level 0 ### +/ root.root 755 /bin/ root.root 755 /boot/ root.root 755 /dev/ root.root 755 -/dev/audio* root.audio 660 -/dev/dsp* root.audio 660 /etc/ root.root 755 /etc/conf.modules root.root 644 /etc/cron.daily/ root.root 755 @@ -14,7 +13,6 @@ /etc/crontab root.root 644 /etc/dhcpcd/ root.root 755 /etc/dhcpcd/* root.root 644 -/etc/esd.conf root.root 644 /etc/ftpaccess root.root 644 /etc/ftpconversions root.root 644 /etc/ftpgroups root.root 644 @@ -26,28 +24,31 @@ /etc/hosts.equiv root.root 644 /etc/inetd.conf root.root 644 /etc/init.d/ root.root 755 -/etc/rc.d/init.d/syslog root.root 744 /etc/inittab root.root 644 /etc/ld.so.conf root.root 644 /etc/lilo.conf root.root 644 +/etc/mandrake-release root.root 644 /etc/modules.conf root.root 644 /etc/motd root.root 644 /etc/printcap root.root 644 /etc/profile.d/* root.root 755 /etc/rc.d/ root.root 755 +/etc/rc.d/init.d/syslog root.root 744 /etc/securetty root.root 644 /etc/sendmail.cf root.root 644 /etc/shutdown.allow root.root 644 -/etc/ssh_config root.root 644 -/etc/ssh_host_key root.root 644 -/etc/ssh_host_key.pub root.root 644 -/etc/sshd_config root.root 644 +/etc/ssh/ssh_config root.root 644 +/etc/ssh/ssh_host_*key root.root 600 +/etc/ssh/ssh_host_*key.pub root.root 644 +/etc/ssh/sshd_config root.root 644 +/etc/sysconfig root.root 755 /etc/syslog.conf root.root 644 /etc/updatedb.conf root.root 644 /home/ root.root 755 /home/* current 755 /lib/ root.root 755 /mnt/ root.root 755 +/proc root.root 555 /root/ root.root 755 /sbin/ root.root 755 /tmp/ root.root 1777 @@ -55,18 +56,17 @@ /usr/* root.root 755 /usr/X11R6/ root.root 755 /usr/bin/ root.root 755 -/usr/sbin/ root.root 755 /usr/lib/rpm/rpm? rpm.rpm 755 +/usr/sbin/ root.root 755 /usr/share/doc root.root 755 +/usr/share/man root.root 755 +/usr/tmp root.root 1777 /var/ root.root 755 -/var/tmp root.root 1777 +/var/lock/subsys root.root 755 /var/log/ root.root 755 /var/log/* root.adm 644 -/var/log/squidGuard squid.squid 755 -/var/log/squid squid.squid 755 -/var/log/snort snort.snort 755 -/var/log/uucp uucp.uucp 755 -/var/log/news news.news 755 -/var/log/security/ root.root 700 -/var/log/security/* root.root 600 +/var/log/*/* current 644 +/var/log/*/*/* current 644 +/var/log/*/. current 755 /var/spool/mail/ root.mail 771 +/var/tmp root.root 1777 diff --git a/conf/perm.1 b/conf/perm.1 index a0ade08..52a9067 100644 --- a/conf/perm.1 +++ b/conf/perm.1 @@ -1,10 +1,9 @@ # Welcome in Level 1 ### +/ root.root 755 /bin/ root.root 755 /boot/ root.root 755 /dev/ root.root 755 -/dev/audio* root.audio 660 -/dev/dsp* root.audio 660 /etc/ root.root 755 /etc/conf.modules root.root 644 /etc/cron.daily/ root.root 755 @@ -14,7 +13,6 @@ /etc/crontab root.root 644 /etc/dhcpcd/ root.root 755 /etc/dhcpcd/* root.root 644 -/etc/esd.conf root.root 644 /etc/ftpaccess root.root 644 /etc/ftpconversions root.root 644 /etc/ftpgroups root.root 644 @@ -26,46 +24,48 @@ /etc/hosts.equiv root.root 644 /etc/inetd.conf root.root 644 /etc/init.d/ root.root 755 -/etc/rc.d/init.d/syslog root.root 744 /etc/inittab root.root 644 /etc/ld.so.conf root.root 644 /etc/lilo.conf root.root 644 +/etc/mandrake-release root.root 644 /etc/modules.conf root.root 644 /etc/motd root.root 644 /etc/printcap root.root 644 /etc/profile.d/* root.root 755 /etc/rc.d/ root.root 755 +/etc/rc.d/init.d/syslog root.root 744 /etc/securetty root.root 644 /etc/sendmail.cf root.root 644 /etc/shutdown.allow root.root 644 -/etc/ssh_config root.root 644 -/etc/ssh_host_key root.root 644 -/etc/ssh_host_key.pub root.root 644 -/etc/sshd_config root.root 644 +/etc/ssh/ssh_config root.root 644 +/etc/ssh/ssh_host_*key root.root 600 +/etc/ssh/ssh_host_*key.pub root.root 644 +/etc/ssh/sshd_config root.root 644 +/etc/sysconfig root.root 755 /etc/syslog.conf root.root 644 /etc/updatedb.conf root.root 644 /home/ root.root 755 /home/* current 755 /lib/ root.root 755 /mnt/ root.root 755 +/proc root.root 555 /root/ root.root 755 /sbin/ root.root 755 /tmp/ root.root 1777 /usr/ root.root 755 /usr/X11R6/ root.root 755 /usr/bin/ root.root 755 -/usr/sbin/ root.root 755 /usr/lib/rpm/rpm? rpm.rpm 755 +/usr/sbin/ root.root 755 /usr/share/doc root.root 755 +/usr/share/man root.root 755 +/usr/tmp root.root 2777 /var/ root.root 755 +/var/lock/subsys root.root 755 /var/log/ root.root 755 /var/log/* root.adm 644 -/var/log/squidGuard squid.squid 755 -/var/log/squid squid.squid 755 -/var/log/snort snort.snort 755 -/var/log/uucp uucp.uucp 755 -/var/log/news news.news 755 -/var/log/security/ root.root 700 -/var/log/security/* root.root 600 +/var/log/*/* current 644 +/var/log/*/*/* current 644 +/var/log/*/. current 755 /var/spool/mail/ root.mail 2775 /var/tmp root.root 2777 diff --git a/conf/perm.2 b/conf/perm.2 index 82052de..51e183f 100644 --- a/conf/perm.2 +++ b/conf/perm.2 @@ -1,10 +1,9 @@ # Welcome in Level 2 ### +/ root.root 755 /bin/ root.root 755 /boot/ root.root 755 /dev/ root.root 755 -/dev/audio* root.audio 660 -/dev/dsp* root.audio 660 /etc/ root.root 755 /etc/conf.modules root.root 644 /etc/cron.daily/ root.root 755 @@ -14,7 +13,6 @@ /etc/crontab root.root 644 /etc/dhcpcd/ root.root 755 /etc/dhcpcd/* root.root 644 -/etc/esd.conf root.root 644 /etc/ftpaccess root.root 644 /etc/ftpconversions root.root 644 /etc/ftpgroups root.root 644 @@ -26,28 +24,31 @@ /etc/hosts.equiv root.root 644 /etc/inetd.conf root.root 644 /etc/init.d/ root.root 755 -/etc/rc.d/init.d/syslog root.root 744 /etc/inittab root.root 644 /etc/ld.so.conf root.root 644 /etc/lilo.conf root.root 644 +/etc/mandrake-release root.root 644 /etc/modules.conf root.root 644 /etc/motd root.root 644 /etc/printcap root.root 644 /etc/profile.d/* root.root 755 /etc/rc.d/ root.root 755 +/etc/rc.d/init.d/* root.root 744 /etc/securetty root.root 644 /etc/sendmail.cf root.root 644 /etc/shutdown.allow root.root 644 -/etc/ssh_config root.root 644 -/etc/ssh_host_key root.root 644 -/etc/ssh_host_key.pub root.root 644 -/etc/sshd_config root.root 644 +/etc/ssh/ssh_config root.root 644 +/etc/ssh/ssh_host_*key root.root 600 +/etc/ssh/ssh_host_*key.pub root.root 644 +/etc/ssh/sshd_config root.root 644 +/etc/sysconfig root.root 755 /etc/syslog.conf root.root 644 /etc/updatedb.conf root.root 644 /home/ root.root 755 /home/* current 755 /lib/ root.root 755 /mnt/ root.root 755 +/proc root.root 555 /root/ root.root 700 /sbin/ root.root 755 /tmp/ root.root 1777 @@ -55,18 +56,17 @@ /usr/* root.root 755 /usr/X11R6/ root.root 755 /usr/bin/ root.root 755 -/usr/sbin/ root.root 755 /usr/lib/rpm/rpm? rpm.rpm 755 +/usr/sbin/ root.root 755 /usr/share/doc root.root 755 +/usr/share/man root.root 755 +/usr/tmp root.root 1777 /var/ root.root 755 +/var/lock/subsys root.root 755 /var/log/ root.root 755 /var/log/* root.adm 640 -/var/log/squidGuard squid.squid 755 -/var/log/squid squid.squid 755 -/var/log/snort snort.snort 755 -/var/log/uucp uucp.uucp 755 -/var/log/news news.news 755 -/var/log/security/ root.root 700 -/var/log/security/* root.root 600 +/var/log/*/* current 640 +/var/log/*/*/* current 640 +/var/log/*/. current 755 /var/spool/mail/ root.mail 2775 /var/tmp root.root 1777 diff --git a/conf/perm.3 b/conf/perm.3 index 1d78f10..798adb5 100644 --- a/conf/perm.3 +++ b/conf/perm.3 @@ -1,10 +1,9 @@ # Welcome in Level 3 ### +/ root.adm 755 /bin/ root.root 755 /boot/ root.root 755 /dev/ root.root 755 -/dev/audio* root.audio 660 -/dev/dsp* root.audio 660 /etc/ root.root 755 /etc/conf.modules root.root 644 /etc/cron.daily/ root.root 755 @@ -14,7 +13,6 @@ /etc/crontab root.root 644 /etc/dhcpcd/ root.root 755 /etc/dhcpcd/* root.root 644 -/etc/esd.conf root.root 644 /etc/ftpaccess root.root 644 /etc/ftpconversions root.root 644 /etc/ftpgroups root.root 644 @@ -26,28 +24,31 @@ /etc/hosts.equiv root.root 644 /etc/inetd.conf root.root 644 /etc/init.d/ root.root 755 -/etc/rc.d/init.d/syslog root.root 700 /etc/inittab root.root 644 /etc/ld.so.conf root.root 644 /etc/lilo.conf root.root 644 +/etc/mandrake-release root.root 644 /etc/modules.conf root.root 644 /etc/motd root.root 644 /etc/printcap root.root 644 /etc/profile.d/* root.root 755 /etc/rc.d/ root.root 755 +/etc/rc.d/init.d/* root.root 700 /etc/securetty root.root 644 /etc/sendmail.cf root.root 644 /etc/shutdown.allow root.root 644 -/etc/ssh_config root.root 644 -/etc/ssh_host_key root.root 644 -/etc/ssh_host_key.pub root.root 644 -/etc/sshd_config root.root 644 +/etc/ssh/ssh_config root.root 644 +/etc/ssh/ssh_host_*key root.root 600 +/etc/ssh/ssh_host_*key.pub root.root 644 +/etc/ssh/sshd_config root.root 644 +/etc/sysconfig root.root 755 /etc/syslog.conf root.adm 640 /etc/updatedb.conf root.root 644 /home/ root.root 755 /home/* current 700 /lib/ root.root 755 /mnt/ root.root 755 +/proc root.root 555 /root/ root.root 700 /sbin/ root.root 755 /tmp/ root.root 1777 @@ -55,18 +56,17 @@ /usr/* root.root 755 /usr/X11R6/ root.root 755 /usr/bin/ root.root 755 -/usr/sbin/ root.root 755 /usr/lib/rpm/rpm? rpm.rpm 755 +/usr/sbin/ root.root 755 /usr/share/doc root.root 755 +/usr/share/man root.root 755 +/usr/tmp root.root 1777 /var/ root.root 755 +/var/lock/subsys root.root 755 /var/log/ root.root 755 -/var/log/* root.root 600 -/var/log/squidGuard squid.squid 755 -/var/log/squid squid.squid 755 -/var/log/snort snort.snort 755 -/var/log/uucp uucp.uucp 755 -/var/log/news news.news 755 -/var/log/security/ root.root 700 -/var/log/security/* root.root 600 +/var/log/* root.root 640 +/var/log/*/* current 640 +/var/log/*/*/* current 640 +/var/log/*/. current 755 /var/spool/mail/ root.mail 2775 /var/tmp root.root 1777 diff --git a/conf/perm.4 b/conf/perm.4 index 45b3fdc..41a00b2 100644 --- a/conf/perm.4 +++ b/conf/perm.4 @@ -1,11 +1,10 @@ # Welcome in Level 4, aka secure & usable. ### +/ root.adm 751 /bin/ root.root 711 /bin/rpm rpm.rpm 750 /boot/ root.root 700 /dev/ root.root 711 -/dev/audio* root.audio 600 -/dev/dsp* root.audio 600 /etc/ root.adm 711 /etc/conf.modules root.adm 640 /etc/cron.daily/ root.adm 750 @@ -15,7 +14,6 @@ /etc/crontab root.adm 640 /etc/dhcpcd/ root.adm 750 /etc/dhcpcd/* root.adm 640 -/etc/esd.conf root.audio 640 /etc/ftpaccess root.adm 640 /etc/ftpconversions root.adm 640 /etc/ftpgroups root.adm 640 @@ -26,29 +24,32 @@ /etc/hosts.deny root.adm 640 /etc/hosts.equiv root.adm 640 /etc/inetd.conf root.adm 640 -/etc/rc.d/init.d/ root.adm 750 -/etc/rc.d/init.d/syslog root.adm 740 /etc/inittab root.adm 640 /etc/ld.so.conf root.adm 640 /etc/lilo.conf root.adm 600 +/etc/mandrake-release root.adm 640 /etc/modules.conf root.adm 640 /etc/motd root.adm 644 /etc/printcap root.lp 640 /etc/profile.d/* root.root 755 -/etc/rc.d/ root.adm 640 +/etc/rc.d/ root.adm 750 +/etc/rc.d/init.d/ root.adm 750 +/etc/rc.d/init.d/* root.adm 740 /etc/securetty root.root 640 /etc/sendmail.cf root.adm 640 /etc/shutdown.allow root.root 600 -/etc/ssh_config root.root 644 -/etc/ssh_host_key root.adm 640 -/etc/ssh_host_key.pub root.adm 644 -/etc/sshd_config root.adm 640 +/etc/ssh/ssh_config root.root 644 +/etc/ssh/ssh_host_*key root.adm 600 +/etc/ssh/ssh_host_*key.pub root.adm 644 +/etc/ssh/sshd_config root.adm 640 +/etc/sysconfig root.adm 751 /etc/syslog.conf root.adm 640 /etc/updatedb.conf root.adm 640 /home/ root.adm 751 /home/* current 700 /lib/ root.adm 751 /mnt/ root.adm 750 +/proc root.kmem 550 /root/ root.root 700 /sbin/ root.adm 751 /tmp/ root.root 1777 @@ -56,18 +57,17 @@ /usr/* root.adm 751 /usr/X11R6/ root.xgrp 751 /usr/bin/ root.adm 751 -/usr/sbin/ root.adm 751 /usr/lib/rpm/rpm? rpm.rpm 750 +/usr/sbin/ root.adm 751 /usr/share/doc rpm.rpm 750 +/usr/share/man rpm.rpm 750 +/usr/tmp root.root 1777 /var/ root.root 755 +/var/lock/subsys root.root 700 /var/log/ root.root 711 /var/log/* root.root 600 -/var/log/squidGuard squid.squid 751 -/var/log/squid squid.squid 751 -/var/log/snort snort.snort 750 -/var/log/uucp uucp.uucp 750 -/var/log/news news.news 750 -/var/log/security/ root.root 700 -/var/log/security/* root.root 600 +/var/log/*/* current 600 +/var/log/*/*/* current 600 +/var/log/*/. current 700 /var/spool/mail/ root.mail 771 /var/tmp root.root 1777 diff --git a/conf/perm.5 b/conf/perm.5 index 8ba96d7..84797ed 100644 --- a/conf/perm.5 +++ b/conf/perm.5 @@ -1,11 +1,10 @@ # Welcome in Level 5, aka paranoid. ### +/ root.root 711 /bin/ root.root 711 /bin/rpm rpm.rpm 750 /boot/ root.root 700 /dev/ root.root 711 -/dev/audio* root.audio 600 -/dev/dsp* root.audio 600 /etc/ root.root 711 /etc/conf.modules root.root 600 /etc/cron.daily/ root.root 700 @@ -15,7 +14,6 @@ /etc/crontab root.root 600 /etc/dhcpcd/ root.root 700 /etc/dhcpcd/* root.root 600 -/etc/esd.conf root.audio 640 /etc/ftpaccess root.root 600 /etc/ftpconversions root.root 600 /etc/ftpgroups root.root 600 @@ -26,29 +24,32 @@ /etc/hosts.deny root.root 600 /etc/hosts.equiv root.root 600 /etc/inetd.conf root.root 600 -/etc/rc.d/init.d/ root.root 700 -/etc/rc.d/init.d/syslog root.root 700 /etc/inittab root.root 600 /etc/ld.so.conf root.root 600 /etc/lilo.conf root.root 600 +/etc/mandrake-release root.root 600 /etc/modules.conf root.root 600 /etc/motd root.root 644 -/etc/printcap root.lp 640 +/etc/printcap root.lp 640 /etc/profile.d/* root.root 755 -/etc/rc.d/ root.root 600 +/etc/rc.d/ root.root 700 +/etc/rc.d/init.d/ root.root 700 +/etc/rc.d/init.d/* root.root 700 /etc/securetty root.root 600 /etc/sendmail.cf root.root 600 -/etc/shutdown.allow root.root 600 -/etc/ssh_config root.root 644 -/etc/ssh_host_key root.root 600 -/etc/ssh_host_key.pub root.root 644 -/etc/sshd_config root.root 600 +/etc/shutdown.allow root.root 600 +/etc/ssh/ssh_config root.root 644 +/etc/ssh/ssh_host_*key root.root 600 +/etc/ssh/ssh_host_*key.pub root.root 644 +/etc/ssh/sshd_config root.root 600 +/etc/sysconfig root.root 711 /etc/syslog.conf root.root 600 /etc/updatedb.conf root.root 600 /home/ root.root 711 /home/* current 700 /lib/ root.root 711 /mnt/ root.root 710 +/proc root.kmem 550 /root/ root.root 700 /sbin/ root.root 711 /tmp/ root.root 1777 @@ -58,27 +59,26 @@ /usr/bin/ root.root 711 /usr/bin/cc root.ctools 750 /usr/bin/finger root.ntools 750 -/usr/bin/gcc root.ctools 750 -/usr/bin/g++ root.ctools 750 +/usr/bin/g++* root.ctools 750 +/usr/bin/gcc* root.ctools 750 /usr/bin/ping root.ntools 750 +/usr/bin/ssh root.ntools 750 /usr/bin/telnet root.ntools 750 /usr/bin/w root.ntools 750 /usr/bin/who root.ntools 750 -/usr/bin/ssh root.ntools 750 +/usr/lib/rpm/rpm? rpm.rpm 750 /usr/sbin/ root.root 711 /usr/sbin/sendmail root.root 755 /usr/sbin/traceroute root.ntools 750 -/usr/lib/rpm/rpm? rpm.rpm 750 /usr/share/doc rpm.rpm 710 +/usr/share/man rpm.rpm 710 +/usr/tmp root.root 1777 /var/ root.root 755 +/var/lock/subsys root.root 700 /var/log/ root.root 711 /var/log/* root.root 600 -/var/log/squidGuard squid.squid 751 -/var/log/squid squid.squid 751 -/var/log/snort snort.snort 750 -/var/log/uucp uucp.uucp 750 -/var/log/news news.news 750 -/var/log/security/ root.root 700 -/var/log/security/* root.root 600 +/var/log/*/* current 600 +/var/log/*/*/* current 600 +/var/log/*/. current 700 /var/spool/mail/ root.mail 771 /var/tmp root.root 1777 diff --git a/conf/perm.snf b/conf/perm.snf index 33bc189..3b12650 100644 --- a/conf/perm.snf +++ b/conf/perm.snf @@ -1,11 +1,10 @@ # Welcome in Level 4, aka secure & usable. ### +/ root.adm 751 /bin/ root.root 711 /bin/rpm rpm.rpm 750 /boot/ root.root 700 /dev/ root.root 711 -/dev/audio* root.audio 600 -/dev/dsp* root.audio 600 /etc/ root.adm 711 /etc/conf.modules root.adm 640 /etc/cron.daily/ root.adm 750 @@ -15,7 +14,6 @@ /etc/crontab root.adm 640 /etc/dhcpcd/ root.adm 750 /etc/dhcpcd/* root.adm 640 -/etc/esd.conf root.audio 640 /etc/ftpaccess root.adm 640 /etc/ftpconversions root.adm 640 /etc/ftpgroups root.adm 640 @@ -26,29 +24,31 @@ /etc/hosts.deny root.adm 640 /etc/hosts.equiv root.adm 640 /etc/inetd.conf root.adm 640 -/etc/rc.d/init.d/ root.adm 750 -/etc/rc.d/init.d/syslog root.adm 740 /etc/inittab root.adm 640 /etc/ld.so.conf root.adm 640 /etc/lilo.conf root.adm 600 +/etc/mandrake-release root.adm 640 /etc/modules.conf root.adm 640 /etc/motd root.adm 644 /etc/printcap root.lp 640 /etc/profile.d/* root.root 755 /etc/rc.d/ root.adm 640 +/etc/rc.d/init.d/ root.adm 750 +/etc/rc.d/init.d/syslog root.adm 740 /etc/securetty root.root 640 /etc/sendmail.cf root.adm 640 /etc/shutdown.allow root.root 600 -/etc/ssh_config root.root 644 -/etc/ssh_host_key root.adm 640 -/etc/ssh_host_key.pub root.adm 644 -/etc/sshd_config root.adm 640 +/etc/ssh/ssh_config root.root 644 +/etc/ssh/ssh_host_*key root.adm 600 +/etc/ssh/ssh_host_*key.pub root.adm 644 +/etc/ssh/sshd_config root.adm 640 /etc/syslog.conf root.adm 640 /etc/updatedb.conf root.adm 640 /home/ root.adm 751 /home/* current 700 /lib/ root.adm 751 /mnt/ root.adm 750 +/proc root.kmem 550 /root/ root.root 700 /sbin/ root.adm 751 /tmp/ root.root 1777 @@ -56,22 +56,20 @@ /usr/* root.adm 751 /usr/X11R6/ root.xgrp 751 /usr/bin/ root.adm 751 -/usr/sbin/ root.adm 751 /usr/lib/rpm/rpm? rpm.rpm 750 +/usr/sbin/ root.adm 751 /usr/share/doc rpm.rpm 750 +/usr/share/man rpm.rpm 750 +/usr/tmp root.root 1777 /var/ root.root 755 +/var/lib/monitoring root.root 751 +/var/lib/naat root.admin 2770 +/var/lock/subsys root.root 700 /var/log/ root.root 711 /var/log/* root.root 600 -/var/log/squidGuard squid.squid 751 -/var/log/squid squid.squid 751 -/var/log/uucp uucp.uucp 750 -/var/log/news news.news 750 -/var/log/security/ root.root 700 -/var/log/security/* root.root 600 +/var/log/*/* current 600 +/var/log/*/*/* current 600 +/var/log/*/. current 700 /var/spool/mail/ root.mail 771 /var/tmp root.root 1777 -/var/lib/monitoring root.root 751 -/var/lib/naat root.admin 2770 -/var/log/httpd-naat httpd-naat.admin 750 /var/www-naat httpd-naat.admin 750 -/var/log/snort snort.snort 750 diff --git a/cron-sh/diff_check.sh b/cron-sh/diff_check.sh index 1b6f9e4..f93c754 100755 --- a/cron-sh/diff_check.sh +++ b/cron-sh/diff_check.sh @@ -55,7 +55,8 @@ fi if [[ ${CHECK_WRITEABLE} == yes ]]; then if [[ -f ${WRITEABLE_YESTERDAY} ]]; then - if ! diff -u ${WRITEABLE_YESTERDAY} ${WRITEABLE_TODAY} > ${WRITEABLE_DIFF}; then + diff -u ${WRITEABLE_YESTERDAY} ${WRITEABLE_TODAY} > ${WRITEABLE_DIFF} + if [ -s ${WRITEABLE_DIFF} ]; then printf "\nSecurity Warning: Change in World Writeable Files found :\n" >> ${TMP} grep '^+' ${WRITEABLE_DIFF} | grep -vw "^+++ " | sed 's|^.||' | while read file; do printf "\t\t- Added writables files : ${file}\n" @@ -72,7 +73,8 @@ fi if [[ ${CHECK_UNOWNED} == yes ]]; then if [[ -f ${UNOWNED_USER_YESTERDAY} ]]; then - if ! diff -u ${UNOWNED_USER_YESTERDAY} ${UNOWNED_USER_TODAY} > ${UNOWNED_USER_DIFF}; then + diff -u ${UNOWNED_USER_YESTERDAY} ${UNOWNED_USER_TODAY} > ${UNOWNED_USER_DIFF} + if [ -s ${UNOWNED_USER_DIFF} ]; then printf "\nSecurity Warning: the following files aren't owned by an user :\n" >> ${TMP} grep '^+' ${UNOWNED_USER_DIFF} | grep -vw "^+++ " | sed 's|^.||' | while read file; do printf "\t\t- Added un-owned files : ${file}\n" @@ -84,7 +86,8 @@ if [[ ${CHECK_UNOWNED} == yes ]]; then fi if [[ -f ${UNOWNED_GROUP_YESTERDAY} ]]; then - if ! diff -u ${UNOWNED_GROUP_YESTERDAY} ${UNOWNED_GROUP_TODAY} > ${UNOWNED_GROUP_DIFF}; then + diff -u ${UNOWNED_GROUP_YESTERDAY} ${UNOWNED_GROUP_TODAY} > ${UNOWNED_GROUP_DIFF} + if [ -s ${UNOWNED_GROUP_DIFF} ]; then printf "\nSecurity Warning: the following files aren't owned by a group :\n" >> ${TMP} grep '^+' ${UNOWNED_GROUP_DIFF} | grep -vw "^+++ " | sed 's|^.||' | while read file; do printf "\t\t- Added un-owned files : ${file}\n" @@ -102,7 +105,8 @@ if [[ ${CHECK_SUID_MD5} == yes ]]; then ctrl_md5=0; if [[ -f ${SUID_MD5_YESTERDAY} ]]; then - if ! diff -u ${SUID_MD5_YESTERDAY} ${SUID_MD5_TODAY} > ${SUID_MD5_DIFF}; then + diff -u ${SUID_MD5_YESTERDAY} ${SUID_MD5_TODAY} > ${SUID_MD5_DIFF} + if [ -s ${SUID_MD5_DIFF} ]; then grep '^+' ${SUID_MD5_DIFF} | grep -vw "^+++ " | sed 's|^.||' | awk '{print $2}' | while read file; do if cat ${SUID_MD5_YESTERDAY} | awk '{print $2}' | grep -qw ${file}; then if [[ ${ctrl_md5} == 0 ]]; then @@ -122,8 +126,9 @@ fi if [[ ${CHECK_OPEN_PORT} == yes ]]; then if [[ -f ${OPEN_PORT_YESTERDAY} ]]; then - if ! diff -u ${OPEN_PORT_YESTERDAY} ${OPEN_PORT_TODAY} 1> ${OPEN_PORT_DIFF}; then - printf "\nSecurity Warning: There is modifications for port listening on your machine :\n" >> ${TMP} + diff -u ${OPEN_PORT_YESTERDAY} ${OPEN_PORT_TODAY} 1> ${OPEN_PORT_DIFF} + if [ -s ${OPEN_PORT_DIFF} ]; then + printf "\nSecurity Warning: There are modifications for port listening on your machine :\n" >> ${TMP} grep '^+' ${OPEN_PORT_DIFF} | grep -vw "^+++ " | sed 's|^.||' | while read file; do printf "\t\t- Opened ports : ${file}\n" done >> ${TMP} @@ -135,26 +140,47 @@ if [[ ${CHECK_OPEN_PORT} == yes ]]; then fi +### rpm database +if [[ ${RPM_CHECK} == yes ]]; then + if [[ -f ${RPM_VA_YESTERDAY} ]]; then + diff -u ${RPM_VA_YESTERDAY} ${RPM_VA_TODAY} > ${RPM_VA_DIFF} + if [ -s ${RPM_VA_DIFF} ]; then + printf "\nSecurity Warning: These files have been modified on the system :\n" >> ${TMP} + grep '^+' ${RPM_VA_DIFF} | grep -vw "^+++ " | sed 's|^.||' | while read file; do + printf "\t\t- newly modified : ${file}\n" + done >> ${TMP} + grep '^-' ${RPM_VA_DIFF} | grep -vw "^--- " | sed 's|^.||' | while read file; do + printf "\t\t- no more modified : ${file}\n" + done >> ${TMP} + fi + fi + if [[ -f ${RPM_QA_YESTERDAY} ]]; then + diff -u ${RPM_QA_YESTERDAY} ${RPM_QA_TODAY} > ${RPM_QA_DIFF} + if [ -s ${RPM_QA_DIFF} ]; then + printf "\nSecurity Warning: These packages have changed on the system :\n" >> ${TMP} + grep '^+' ${RPM_QA_DIFF} | grep -vw "^+++ " | sed 's|^.||' | while read file; do + printf "\t\t- added package : ${file}\n" + done >> ${TMP} + grep '^-' ${RPM_QA_DIFF} | grep -vw "^--- " | sed 's|^.||' | while read file; do + printf "\t\t- removed package : ${file}\n" + done >> ${TMP} + fi + fi +fi + ######## Report ###### if [[ -s ${TMP} ]]; then Syslog ${TMP} Ttylog ${TMP} date=`date` + hostname=`hostname` echo -e "\n\n*** Diff Check, ${date} ***\n" >> ${SECURITY_LOG} cat ${TMP} >> ${SECURITY_LOG} - Maillog "*** Diff Check, ${date} ***" "${TMP}" + Maillog "*** Diff Check on ${hostname}, ${date} ***" "${TMP}" fi if [[ -f ${TMP} ]]; then rm -f ${TMP} fi - - - - - - - - diff --git a/cron-sh/security.sh b/cron-sh/security.sh index 01d3e4c..5b974a4 100755 --- a/cron-sh/security.sh +++ b/cron-sh/security.sh @@ -30,6 +30,12 @@ UNOWNED_USER_DIFF="/var/log/security/unowned_user.diff" export UNOWNED_GROUP_TODAY="/var/log/security/unowned_group.today" UNOWNED_GROUP_YESTERDAY="/var/log/security/unowned_group.yesterday" UNOWNED_GROUP_DIFF="/var/log/security/unowned_group.diff" +export RPM_VA_TODAY="/var/log/security/rpm-va.today" +RPM_VA_YESTERDAY="/var/log/security/rpm-va.yesterday" +RPM_VA_DIFF="/var/log/security/rpm-va.diff" +export RPM_QA_TODAY="/var/log/security/rpm-qa.today" +RPM_QA_YESTERDAY="/var/log/security/rpm-qa.yesterday" +RPM_QA_DIFF="/var/log/security/rpm-qa.diff" # Modified filters coming from debian security scripts. CS_NFSAFS='(nfs|afs|xfs|coda)' @@ -72,6 +78,13 @@ if [[ -f ${SUID_MD5_TODAY} ]]; then mv ${SUID_MD5_TODAY} ${SUID_MD5_YESTERDAY}; fi +if [[ -f ${RPM_VA_TODAY} ]]; then + mv -f ${RPM_VA_TODAY} ${RPM_VA_YESTERDAY} +fi + +if [[ -f ${RPM_QA_TODAY} ]]; then + mv -f ${RPM_QA_TODAY} ${RPM_QA_YESTERDAY} +fi netstat -pvlA inet 2> /dev/null > ${OPEN_PORT_TODAY}; @@ -109,6 +122,19 @@ if [[ -f ${SUID_ROOT_TODAY} ]]; then done < ${SUID_ROOT_TODAY} > ${SUID_MD5_TODAY} fi +### rpm database check + +if [[ ${RPM_CHECK} == yes ]]; then + if [ -f /var/lib/rpm/__db.001 -o -f /var/lib/rpm/__db.002 ]; then + rm -f /var/lib/rpm/__db.00* + rpm --rebuilddb + fi + + rpm -qa --qf "%{NAME}-%{VERSION}-%{RELEASE}\t%{INSTALLTIME}\n" | sort > ${RPM_QA_TODAY} + + nice --adjustment=+19 rpm -V `cut -f 1 < ${RPM_QA_TODAY} | grep -v '^dev-[0-9]'` | grep '^..5' | sed 's/...........//' | sort > ${RPM_VA_TODAY} +fi + ### Functions ### Syslog() { @@ -121,7 +147,7 @@ Syslog() { Ttylog() { if [[ ${TTY_WARN} == yes ]]; then - for i in `w | grep -v "load\|TTY" | awk '{print $2}'` ; do + for i in `w | grep -v "load\|TTY" | grep '^root' | awk '{print $2}'` ; do cat ${1} > /dev/$i done fi @@ -146,11 +172,3 @@ Maillog() { . /usr/share/msec/diff_check.sh . /usr/share/msec/security_check.sh - - - - - - - - diff --git a/cron-sh/security_check.sh b/cron-sh/security_check.sh index 5055b52..9ffc469 100755 --- a/cron-sh/security_check.sh +++ b/cron-sh/security_check.sh @@ -36,7 +36,7 @@ fi if [[ ${CHECK_UNOWNED} == yes ]]; then if [[ -s ${UNOWNED_USER_TODAY} ]]; then printf "\nSecurity Warning : User Unowned files found :\n" >> ${SECURITY} - printf "\t( theses files now have user \"nobody\" as their owner. )\n" >> ${SECURITY_LOG} + printf "\t( theses files now have user \"nobody\" as their owner. )\n" >> ${SECURITY} cat ${UNOWNED_USER_TODAY} | awk '{print "\t\t- " $0}' >> ${SECURITY} cat ${UNOWNED_USER_TODAY} | while read line; do chown nobody "${line}"; # Use quote if filename contain space. @@ -135,6 +135,8 @@ if [[ ${CHECK_PASSWD} == yes ]]; then printf("\t\t- /etc/passwd:%d: User \"%s\" has no password !\n", FNR, $1); else if ($2 !~ /^[x*!]+$/) printf("\t\t- /etc/passwd:%d: User \"%s\" has a real password (it is not shadowed).\n", FNR, $1); + else if ( $3 == 0 && $1 != "root" ) + printf("\t\t- /etc/passwd:%d: User \"%s\" has id 0 !\n", FNR, $1); }' < /etc/passwd > ${TMP} if [[ -s ${TMP} ]]; then @@ -245,17 +247,29 @@ if [[ ${CHECK_OPEN_PORT} == yes ]]; then fi +### rpm database checks +if [[ ${RPM_CHECK} == yes ]]; then + + if [[ -s ${RPM_VA_TODAY} ]]; then + printf "\nSecurity Warning: These files belonging to packages are modified on the system :\n" >> ${SECURITY} + cat ${RPM_VA_TODAY} | while read f; do + printf "\t\t- $f\n" + done >> ${SECURITY} + fi +fi + ### Report if [[ -s ${SECURITY} ]]; then Syslog ${SECURITY} Ttylog ${SECURITY} date=`date` - + hostname=`hostname` + echo -e "\n\n*** Security Check, ${date} ***\n" >> ${SECURITY_LOG} cat ${SECURITY} >> ${SECURITY_LOG} cat ${INFOS} >> ${SECURITY_LOG} - Maillog "*** Security Check, ${date} ***" "${SECURITY} ${INFOS}" + Maillog "*** Security Check on ${hostname}, ${date} ***" "${SECURITY} ${INFOS}" fi if [[ -f ${SECURITY} ]]; then @@ -269,7 +283,3 @@ fi if [[ -f ${INFOS} ]]; then rm -f ${INFOS}; fi - - - - diff --git a/init-sh/cleanold.sh b/init-sh/cleanold.sh new file mode 100755 index 0000000..90c2df8 --- /dev/null +++ b/init-sh/cleanold.sh @@ -0,0 +1,133 @@ +# +# Security level implementation... +# Writen by Vandoorselaere Yoann <yoann@mandrakesoft.com> +# + +# Need root access +if [[ ${UID} != 0 ]]; then + echo "You need to be root in order to change secure level." + exit 1 +fi + +export COMMENT="# Mandrake-Security : if you remove this comment, remove the next line too." + +AddRules() { + string=$1 + file=$2 + quiet=$3 + + if [[ -z ${string} ]]; then + return; + fi + + if [[ -z ${quiet} ]]; then + echo "Modifying config in ${file}..." + fi + + if ! grep -qEx "^${string}" ${file}; then + echo -e "${COMMENT}" >> ${file}; + echo -e "${string}" >> ${file}; + fi + + if [[ -z ${3} ]]; then + echo -e "done.\n" + fi +} + +CleanRules() { + echo -en "\t- Cleaning msec appended line in $1 : " + + perl -ni -e '$_ eq "$ENV{COMMENT}\n" ... // or print' $1 + + echo "done." +} + +CommentUserRules() { + file=$1 + + if [[ ! -f ${file} ]]; then + return; + fi + + echo -en "\t- Cleaning user appended line in ${file} : " + + tmpfile=`mktemp /tmp/secure.XXXXXX` + cp -f ${file} ${tmpfile} + + while read line; do + if ! echo "${line}" | grep -qE "^#"; then + echo "# ${line}" + else + echo "${line}" + fi + done < ${tmpfile} > ${file} + + rm -f ${tmpfile} + + echo "done." +} + +RestoreIssues () { + if [ ! -f /etc/issue.net -a -f /etc/issue.net.msec ]; then + mv -f /etc/issue.net.msec /etc/issue.net + fi + + if [ ! -f /etc/issue -a -f /etc/issue.msec ]; then + mv -f /etc/issue.msec /etc/issue + fi +} + +# If we are currently installing our +# system with DrakX, we don't ask anything to the user... +# Instead, DrakX do it and give us a file with some variable. +if [[ -f /etc/security/msec/security.conf ]]; then + . /etc/security/msec/security.conf +fi + +CleanRules /etc/syslog.conf +CleanRules /etc/hosts.deny +CleanRules /etc/hosts.allow +CleanRules /etc/securetty +CleanRules /etc/security/msec/security.conf +CleanRules /etc/ld.so.preload +CleanRules /etc/host.conf +CleanRules /etc/sysctl.conf + +CleanRules /etc/logrotate.conf +CleanRules /etc/rc.d/rc.local +CleanRules /etc/rc.d/rc.firewall +CleanRules /etc/crontab +CleanRules /etc/profile +CleanRules /etc/zprofile + +RestoreIssues + +if [[ -f /etc/X11/xinit.d/msec ]]; then + CleanRules /etc/X11/xinit.d/msec +else + touch /etc/X11/xinit.d/msec + chmod 755 /etc/X11/xinit.d/msec +fi + +if [[ -f /etc/sysconfig/msec ]]; then + CleanRules /etc/sysconfig/msec +fi + +if [[ -f /etc/profile.d/msec.sh && -f /etc/profile.d/msec.csh ]]; then + CleanRules /etc/profile.d/msec.sh + CleanRules /etc/profile.d/msec.csh +else + chmod 755 /etc/profile.d/msec.sh + chmod 755 /etc/profile.d/msec.csh +fi + +# default group which must exist on the system +# groupadd already check for their existance... +groupadd nogroup >& /dev/null +groupadd audio >& /dev/null +groupadd xgrp >& /dev/null +groupadd ntools >& /dev/null +groupadd ctools >& /dev/null + +usermod -G xgrp xfs + @@ -11,3 +11,5 @@ if ! echo ${PATH} |grep -q /usr/games ; then fi export SECURE_LEVEL=${SECURE_LEVEL} + +[ -n "$TMOUT" ] && typeset -r TMOUT @@ -1,9 +1,9 @@ Summary: Security Level & Program for the Mandrake Linux distribution Name: msec -Version: 0.16 -Release: 4mdk +Version: 0.17 +Release: 12mdk Url: http://www.linux-mandrake.com -Source0: %{name}-%{version}.tar.bz2 +Source0: %{name}-%{version}.tar.bz2 Source1: msec.logrotate Source2: msec.sh Source3: msec.csh @@ -11,7 +11,8 @@ Source3: msec.csh License: GPL Group: System/Base BuildRoot: %_tmppath/%name-%version-%release-root -Requires: /bin/bash /bin/touch setup chkconfig >= 0.9-6 +Requires: /bin/bash /bin/touch perl diffutils textutils /usr/bin/python /usr/bin/chage gawk +Requires: setup >= 2.2.0-19mdk Requires: chkconfig >= 1.2.24-3mdk %description @@ -29,6 +30,9 @@ in order to test the security of your system and alert you if needed. %build make CFLAGS="$RPM_OPT_FLAGS" +cd share; ./compile.py '/usr/share/msec/' *.py +rm -f msec.pyo + %install #make install RPM_BUILD_ROOT=$RPM_BUILD_ROOT @@ -39,8 +43,8 @@ install -d $RPM_BUILD_ROOT/usr/sbin $RPM_BUILD_ROOT/usr/bin install -d $RPM_BUILD_ROOT/var/log/security install -d $RPM_BUILD_ROOT%{_mandir}/man8 -install -m 755 init-sh/*.sh cron-sh/*.sh $RPM_BUILD_ROOT/usr/share/msec -install -m 755 init-sh/msec $RPM_BUILD_ROOT/usr/sbin +cp -p init-sh/cleanold.sh share/*.py share/*.pyo cron-sh/*.sh $RPM_BUILD_ROOT/usr/share/msec +install -m 755 share/msec $RPM_BUILD_ROOT/usr/sbin install -m 644 conf/perm.* conf/server.* $RPM_BUILD_ROOT/etc/security/msec install -m 755 src/promisc_check/promisc_check src/msec_find/msec_find $RPM_BUILD_ROOT/usr/bin @@ -62,26 +66,17 @@ install -m 755 %{SOURCE2} $RPM_BUILD_ROOT/etc/profile.d install -m 755 %{SOURCE3} $RPM_BUILD_ROOT/etc/profile.d touch $RPM_BUILD_ROOT/var/log/security.log -%post +%post -p /bin/sh touch /var/log/security.log -# create the /etc/security/msec/server -# the /usr/share/msec/current-level.sh and -# /etc/security/msec/current.perm files -if [[ ${SECURE_LEVEL} == 4 || ${SECURE_LEVEL} == 5 || ${SECURE_LEVEL} == snf ]]; then - ln -sf /etc/security/msec/server.${SECURE_LEVEL} /etc/security/msec/server - else - rm -rf /etc/security/msec/server - chkconfig --list |awk ' {print $1}' | grep -v ":" | sort -u > /etc/security/msec/server -fi - -ln -sf /usr/share/msec/level${SECURE_LEVEL}.sh /usr/share/msec/current-level.sh -echo -echo "You might need to logout of your terminal session in order to update your environment variables." -echo -if [[ -f /etc/security/msec/perm.${SECURE_LEVEL} ]]; then - ln -sf /etc/security/msec/perm.${SECURE_LEVEL} /etc/security/msec/current.perm - /usr/share/msec/file_perm.sh /etc/security/msec/current.perm +if [ $1 != 1 -a -f /etc/security/msec/security.conf ]; then + if grep -q "# Mandrake-Security : if you remove this comment" /etc/security/msec/security.conf; then + SL=`sed -n 's/SECURE_LEVEL=//p' < /etc/sysconfig/msec` || : + /usr/share/msec/cleanold.sh || : + msec $SL < /dev/null || : + else + msec < /dev/null || : + fi fi %clean @@ -89,7 +84,7 @@ rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) -%doc AUTHORS COPYING Makefile README +%doc AUTHORS COPYING Makefile share/README share/CHANGES %doc doc/*txt ChangeLog doc/*ps %_bindir/promisc_check %_bindir/msec_find @@ -108,6 +103,66 @@ rm -rf $RPM_BUILD_ROOT # MAKE THE CHANGES IN CVS: NO PATCH OR SOURCE ALLOWED %changelog +* Thu Jan 17 2002 Frederic Lepied <flepied@mandrakesoft.com> 0.17-12mdk +- report cron log to tty only on root ttys. +- better layout of rpm modified files report. + +* Wed Jan 9 2002 Frederic Lepied <flepied@mandrakesoft.com> 0.17-11mdk +- added hostname to the subject of the mail report for better information +when you receive multiple reports + +- really added rpm-va check to the mail report + +- fix handling of the owner/group of subdirectories of /var/log in a +generic manner. + +- oops put back periodic filesystems check + +* Mon Jan 7 2002 Frederic Lepied <flepied@mandrakesoft.com> 0.17-10mdk +- corrected first invocation. + +* Sun Jan 6 2002 Frederic Lepied <flepied@mandrakesoft.com> 0.17-9mdk +- oops: corrected broken security.sh script + +* Fri Jan 4 2002 Frederic Lepied <flepied@mandrakesoft.com> 0.17-8mdk +- TMOUT is now a read only variable +- allow/forbid reboot/shutdown by [kg]dm + +* Thu Jan 3 2002 Frederic Lepied <flepied@mandrakesoft.com> 0.17-7mdk +- rpm -qa check now logs install time too +- corrected the way we install the byte compiled python files to avoid +false rpm -V warnings. +- added a CHANGES file to document what has changed between 0.16 and 0.17 +- send complete rpm -va check to the main mail +- perm.*: added handling of /etc/rc.d/init.d/* +- changed the way /etc/security/msec/perm.local is used to avoid flip/flap changes +- reworked output in diff rpm check to be more coherent + +* Sat Dec 29 2001 Frederic Lepied <flepied@mandrakesoft.com> 0.17-6mdk +- added doc of the features of the msec utility +- corrected enable_at_crontab +- password_aging only takes care of /etc/shadow users and avoid the users +with a deactivated password. + +* Fri Dec 28 2001 Frederic Lepied <flepied@mandrakesoft.com> 0.17-5mdk +- added rpm database checks +- added check of accounts with the 0 id that aren't root. + +* Thu Dec 27 2001 Frederic Lepied <flepied@mandrakesoft.com> 0.17-4mdk +- disable root login in xdm,kdm,gdm the same way as in Bastille (via pam). +- manage password aging. +- manage crontab and at authorization. + +* Thu Dec 27 2001 Frederic Lepied <flepied@mandrakesoft.com> 0.17-3mdk +- avoid changing permissions twice in the same run (to avoid unneeded logging). +- when run in non-interactive mode, the output goes to the auth facility. + +* Fri Dec 14 2001 Frederic Lepied <flepied@mandrakesoft.com> 0.17-2mdk +- fixed sysctl.conf handling + +* Thu Dec 13 2001 Frederic Lepied <flepied@mandrakesoft.com> 0.17-1mdk +- rewritten file modifications part in python + * Wed Dec 05 2001 Florin <florin@mandrakesoft.com> 0.16-4mdk - oups, use %{_sysconfdir}/sysconfig/%{name} instead of %{_sysconfdir}/%{name} - fix the msec.csh file (thks again to Konrad Bernlohr) diff --git a/share/.cvsignore b/share/.cvsignore new file mode 100644 index 0000000..34fcef1 --- /dev/null +++ b/share/.cvsignore @@ -0,0 +1,2 @@ +*.pyo +*.pyc diff --git a/share/CHANGES b/share/CHANGES new file mode 100644 index 0000000..0e66020 --- /dev/null +++ b/share/CHANGES @@ -0,0 +1,40 @@ +changes between version 0.16 and 0.17 +===================================== + +msec utility changes: + + * handle shell timeout (level 4 and 5) + * limit shell history (level 4 and 5) + * su only for wheel group (level 5) + * sulogin for single user mode (level 4 and 5) + * various sysctl.conf settings for icmp and network parameters + * password aging (level 4 and 5) + * suppress /etc/issue.net (level 4 and 5) and /etc/issue (level 5) + * removed manipulation of the groups of users + * removed removal of services + * logging in syslog according to the guideline for explanations in tools + * rewritten in python + +msec can be used to change level and it's also run hourly by cron to +maintain the security level on the system. Only the minimum of changes +on the filesystem are applied and the minimum of programs started. + +Periodic security checks changes: + + * added an rpm database check (rpm -va and rpm -qa) + * report when a user other than root is at uid 0 + +Permissions settings changes: + + * / + * removed audio group handling because it has always conflicted with pam_console + * handle /var/log sub-directories in a generic manner + * /etc/rc.d/init.d/* + * corrected ssh related paths + * /etc/sysconfig + * /proc + * corrected gcc files + * rpm related files to avoid exposing what is installed + * /var/lock/subsys + * added a local.perm to allow modifications without modifying level perms + * rewritten in python diff --git a/share/Config.py b/share/Config.py new file mode 100644 index 0000000..ee2c10e --- /dev/null +++ b/share/Config.py @@ -0,0 +1,46 @@ +#--------------------------------------------------------------- +# Project : Linux-Mandrake +# Module : msec2 +# File : Config.py +# Version : $Id$ +# Author : Frederic Lepied +# Created On : Thu Dec 6 19:54:35 2001 +# Purpose : configuration settings +#--------------------------------------------------------------- + +import sys + +CONFIG='/etc/security/msec2.conf' + +_config={ 'root' : '', + 'run_commands': 1, + 'log': 'syslog', + } +try: + execfile(CONFIG, _config) +except IOError: + #sys.stderr.write("no config file in %s. Using default values.\n" % CONFIG) + pass + +def get_config(name, default=None): + try: + return _config[name] + except KeyError: + return default + +def set_config(name, value): + _config[name] = value + +def converthexa(array): + result="" + for c in array: + o=ord(c) + d=o/16 + u=o-(d*16) + result=result + "%x%x" % (d, u) + return result + +def hashstring(str): + return converthexa(md5.new(str).digest()) + +# Config.py ends here diff --git a/share/ConfigFile.py b/share/ConfigFile.py new file mode 100644 index 0000000..3e24b9b --- /dev/null +++ b/share/ConfigFile.py @@ -0,0 +1,376 @@ +#--------------------------------------------------------------- +# Project : Mandrake Linux +# Module : msec2 +# File : ConfigFile.py +# Version : $Id$ +# Author : Frederic Lepied +# Created On : Wed Dec 5 21:42:49 2001 +# Purpose : class abstraction to handle configuration +# files. +#--------------------------------------------------------------- + +import re +import string +import os +import stat +import Config +import commands +from Log import * +import gettext + +try: + cat = gettext.Catalog('msec') + _ = cat.gettext +except IOError: + _ = str + +BEFORE=0 +INSIDE=1 +AFTER=2 + +space = re.compile('\s') + +class ConfigFiles: + def __init__(self): + self.files = {} + self.modified_files = [] + self.action_assoc = [] + + def add(self, file, path): + self.files[path] = file + + def modified(self, path): + if not path in self.modified_files: + self.modified_files.append(path) + + def get_config_file(self, path, suffix): + try: + return self.files[path] + except KeyError: + return ConfigFile(path, suffix, self) + + def add_config_assoc(self, regex, action): + self.action_assoc.append((re.compile(regex), action)) + +all_files=ConfigFiles() + +def move(old, new): + try: + os.unlink(new) + except OSError: + pass + os.rename(old, new) + +class ConfigFile: + def __init__(self, path, suffix=None, meta=all_files): + self.meta=meta + self.path = Config.get_config('root', '') + path + self.is_modified = 0 + self.is_touched = 0 + self.is_deleted = 0 + self.is_moved = 0 + self.suffix = suffix + self.lines = None + self.sym_link = None + self.meta.add(self, path) + + def get_lines(self): + if self.lines == None: + file=None + try: + file = open(self.path, 'r') + except IOError: + if self.suffix: + try: + moved = self.path + self.suffix + file = open(moved, 'r') + move(moved, self.path) + self.meta.modified(self.path) + except IOError: + self.lines = [] + else: + self.lines = [] + if file: + self.lines = string.split(file.read(), "\n") + file.close() + return self.lines + + def append(self, value): + lines = self.lines + l = len(lines) + if l > 0 and lines[l - 1] == '': + lines.insert(l - 1, value) + else: + lines.append(value) + lines.append('') + + def modified(self): + self.is_modified = 1 + return self + + def touch(self): + self.is_touched = 1 + return self + + def symlink(self, link): + self.sym_link = link + return self + + def exists(self): + return os.path.exists(self.path) or (self.suffix and os.path.exists(self.path + self.suffix)) + + def move(self, suffix): + self.suffix = suffix + self.is_moved = 1 + + def unlink(self): + self.is_deleted = 1 + self.lines=[] + return self + + def write(self): + if self.is_deleted: + if self.exists(): + os.unlink(self.path) + log(_('deleted %s') % (self.path,)) + elif self.is_modified: + content = string.join(self.lines, "\n") + file = open(self.path, 'w') + file.write(content) + file.close() + self.meta.modified(self.path) + elif self.is_touched: + if os.path.exists(self.path): + os.utime(self.path, None) + elif self.suffix and os.path.exists(self.path + self.suffix): + move(self.path + self.suffix, self.path) + os.utime(self.path, None) + else: + self.lines = [] + self.is_modified = 1 + file = open(self.path, 'w') + file.close() + log(_('touched file %s') % (self.path,)) + elif self.sym_link: + done = 0 + if self.exists(): + full = os.lstat(self.path) + if stat.S_ISLNK(full[stat.ST_MODE]): + link = os.readlink(self.path) + # to be fixed: resolv relative symlink + done = (link == self.sym_link) + if not done: + os.unlink(self.path) + log(_('deleted %s') % (self.path,)) + if not done: + os.symlink(self.sym_link, self.path) + log(_('made symbolic link from %s to %s') % (self.sym_link, self.path)) + + if self.is_moved: + move(self.path, self.path + self.suffix) + log(_('moved file %s to %s') % (self.path, self.path + self.suffix)) + self.meta.modified(self.path) + self.is_touched = 0 + self.is_modified = 0 + self.is_deleted = 0 + self.is_moved = 0 + + def set_shell_variable(self, var, value, start=None, end=None): + regex = re.compile('^' + var + '="?([^#"]+)"?(.*)') + lines = self.get_lines() + idx=0 + value=str(value) + + if start: + status = BEFORE + start = re.compile(start) + else: + status = INSIDE + + if end: + end = re.compile(end) + + idx = None + for idx in range(0, len(lines)): + line = lines[idx] + if status == BEFORE: + if start.search(line): + status = INSIDE + else: + continue + elif end and end.search(line): + break + res = regex.search(line) + if res: + if res.group(1) != value: + if space.search(value): + lines[idx] = var + '="' + value + '"' + res.group(2) + else: + lines[idx] = var + '=' + value + res.group(2) + self.modified() + log(_('set variable %s to %s in %s') % (var, value, self.path,)) + return self + if space.search(value): + s = var + '="' + value + '"' + else: + s = var + '=' + value + if idx == None or idx == len(lines): + self.append(s) + else: + lines.insert(idx, s) + + self.modified() + log(_('set variable %s to %s in %s') % (var, value, self.path,)) + return self + + def get_shell_variable(self, var): + regex = re.compile('^' + var + '="?([^#"]+)"?(.*)') + lines = self.get_lines() + for idx in range(0, len(lines)): + res = regex.search(lines[idx]) + if res: + return res.group(1) + return None + + def get_match(self, regex, replace=None): + r=re.compile(regex) + lines = self.get_lines() + matches = 0 + for idx in range(0, len(lines)): + res = r.search(lines[idx]) + if res: + s = substitute_re_result(res, replace) + return s + return None + + def replace_line_matching(self, regex, value, at_end_if_not_found=0, all=0, start=None, end=None): + r=re.compile(regex) + lines = self.get_lines() + matches = 0 + + if start: + status = BEFORE + start = re.compile(start) + else: + status = INSIDE + + if end: + end = re.compile(end) + + idx = None + for idx in range(0, len(lines)): + line = lines[idx] + if status == BEFORE: + if start.search(line): + status = INSIDE + else: + continue + elif end and end.search(line): + break + res = r.search(line) + if res: + s = substitute_re_result(res, value) + matches = matches + 1 + if s != line: + log(_("replaced in %s the line %d:\n%s\nwith the line:\n%s") % (self.path, idx, line, s)) + lines[idx] = s + self.modified() + if not all: + return matches + if matches == 0 and at_end_if_not_found: + log(_("appended in %s the line:\n%s") % (self.path, value)) + if idx == None or idx == len(lines): + self.append(value) + else: + lines.insert(idx, value) + self.modified() + matches = matches + 1 + return matches + + def insert_after(self, regex, value, at_end_if_not_found=0, all=0): + matches = 0 + r=re.compile(regex) + lines = self.get_lines() + for idx in range(0, len(lines)): + res = r.search(lines[idx]) + if res: + s = substitute_re_result(res, value) + log(_("inserted in %s after the line %d:\n%s\nthe line:\n%s") % (self.path, idx, lines[idx], s)) + lines.insert(idx+1, s) + self.modified() + matches = matches + 1 + if not all: + return matches + if matches == 0 and at_end_if_not_found: + log(_("appended in %s the line:\n%s") % (self.path, value)) + self.append(value) + self.modified() + matches = matches + 1 + return matches + + def insert_at(self, idx, value): + lines = self.get_lines() + try: + lines.insert(idx, value) + log(_("inserted in %s at the line %d:\n%s") % (self.path, idx, value)) + self.modified() + return 1 + except KeyError: + return 0 + + def remove_line_matching(self, regex, all=0): + matches = 0 + r=re.compile(regex) + lines = self.get_lines() + for idx in range(len(lines) - 1, -1, -1): + res = r.search(lines[idx]) + if res: + log(_("removing in %s the line %d:\n%s") % (self.path, idx, lines[idx])) + lines.pop(idx) + self.modified() + matches = matches + 1 + if not all: + return matches + return matches + +# utility funtions + +def substitute_re_result(res, s): + for idx in range(0, (res.lastindex or 0) + 1): + subst = res.group(idx) or '' + s = string.replace(s, '@' + str(idx), subst) + return s + +def write_files(): + global all_files + + run_commands = Config.get_config('run_commands', 0) + for f in all_files.files.values(): + f.write() + + for f in all_files.modified_files: + for a in all_files.action_assoc: + res = a[0].search(f) + if res: + s = substitute_re_result(res, a[1]) + if run_commands != '0': + log(_('%s modified so launched command: %s') % (f, s)) + cmd = commands.getstatusoutput(s) + if cmd[0] == 0: + log(cmd[1]) + else: + error(cmd[1]) + else: + log(_('%s modified so should have run command: %s') % (f, s)) + +def get_config_file(path, suffix=None): + global all_files + + return all_files.get_config_file(path, suffix) + +def add_config_assoc(regex, action): + global all_files + + return all_files.add_config_assoc(regex, action) + +# ConfigFile.py ends here diff --git a/share/Log.py b/share/Log.py new file mode 100644 index 0000000..bcda819 --- /dev/null +++ b/share/Log.py @@ -0,0 +1,53 @@ +#--------------------------------------------------------------- +# Project : Mandrake Linux +# Module : msec2 +# File : Log.py +# Version : $Id$ +# Author : Frederic Lepied +# Created On : Wed Dec 5 23:50:29 2001 +# Purpose : write log through syslog conforming to +# the Mandrake Linux guideline for the explanations +# in tools. Errors are reported to stderr. +#--------------------------------------------------------------- + +import syslog +import sys +import string +import Config + +_name = '' +_use_syslog = 1 + +def initlog(name, facility = syslog.LOG_AUTH): + global _name + global _use_syslog + + _use_syslog = (Config.get_config('log', 'syslog') == 'syslog') + + if _use_syslog: + syslog.openlog(name, 0, facility) + + _name = name + +def log(s, level = syslog.LOG_INFO): + global _use_syslog + + if _use_syslog: + for l in string.split(s, '\n'): + syslog.syslog(level, l) + else: + sys.stderr.write(s + '\n') + return 1 + +def closelog(): + global _use_syslog + + if _use_syslog: + syslog.closelog() + +def error(s): + global _name + + sys.stderr.write(_name + ': ' + s + '\n') + +# Log.py ends here diff --git a/share/Perms.py b/share/Perms.py new file mode 100755 index 0000000..8a8c983 --- /dev/null +++ b/share/Perms.py @@ -0,0 +1,173 @@ +#!/usr/bin/python -O +#--------------------------------------------------------------- +# Project : Mandrake Linux +# Module : msec +# File : Perms.py +# Version : $Id$ +# Author : Frederic Lepied +# Created On : Fri Dec 7 23:33:49 2001 +# Purpose : fix permissions and owner/group of files +# and directories. +#--------------------------------------------------------------- + +import glob +import re +import string +import os +import stat +import pwd +import grp +import Config +from Log import * +import gettext + +try: + cat = gettext.Catalog('msec') + _ = cat.gettext +except IOError: + _ = str + +comment_regex = re.compile('^\s*#|^\s*$') + +user = {} +group = {} +userid = {} +groupid = {} + +def get_user_id(name): + try: + return user[name] + except KeyError: + try: + user[name] = pwd.getpwnam(name)[2] + except KeyError: + error(_('user name %s not found') % name) + user[name] = -1 + return user[name] + +def get_user_name(id): + try: + return userid[id] + except KeyError: + try: + userid[id] = pwd.getpwuid(id)[0] + except KeyError: + error(_('user name not found for id %d') % id) + userid[id] = str(id) + return userid[id] + +def get_group_id(name): + try: + return group[name] + except KeyError: + try: + group[name] = grp.getgrnam(name)[2] + except KeyError: + error(_('group name %s not found') % name) + group[name] = -1 + return group[name] + +def get_group_name(id): + try: + return groupid[id] + except KeyError: + try: + groupid[id] = grp.getgrgid(id)[0] + except KeyError: + error(_('group name not found for id %d') % id) + groupid[id] = str(id) + return groupid[id] + +assoc = {} + +def fix_perms(path): + try: + file = open(path, 'r') + except IOError: + return + root = Config.get_config('root', '') + lineno = 0 + for line in file.readlines(): + lineno = lineno + 1 + if comment_regex.search(line): + continue + fields = re.split('\s*', line) + newmode = int(fields[2], 8) + if fields[1] == 'current': + user = group = -1 + user_str = group_str = '' + else: + (user_str, group_str) = string.split(fields[1], '.') + user = get_user_id(user_str) + group = get_group_id(group_str) + if len(fields) == 4: + for f in glob.glob(fields[0]): + try: + full = os.stat(f) + except OSError: + continue + mode = stat.S_IMODE(full[stat.ST_MODE]) + newperm = newmode + if stat.S_ISDIR(full[stat.ST_MODE]): + if newperm & 0400: + newperm = newperm | 0100 + if newperm & 0040: + newperm = newperm | 0010 + if newperm & 0004: + newperm = newperm | 0001 + uid = full[stat.ST_UID] + gid = full[stat.ST_GID] + if f != '/' and f[-1] == '/': + f = f[:-1] + if f[-2:] == '/.': + f = f[:-2] + assoc[f] = (mode, uid, gid, newperm, user, group, user_str, group_str) + else: + error(_('invalid syntax in %s line %d') % (path, lineno)) + file.close() + +def act(): + for f in assoc.keys(): + (mode, uid, gid, newperm, user, group, user_str, group_str) = assoc[f] + #print f, (mode, uid, gid, newperm, user, group) + if mode != newperm: + log(_('changed mode of %s from %o to %o') % (f, mode, newperm)) + os.chmod(f, newperm) + if user != -1: + if user != uid: + log(_('changed owner of %s from %s to %s') % (f, get_user_name(uid), user_str)) + os.chown(f, user, -1) + if group != -1: + if group != gid: + log(_('changed group of %s from %s to %s') % (f, get_group_name(gid), group_str)) + os.chown(f, -1, group) + +def chmod(f, newperm): + try: + full = os.stat(f) + except OSError: + return 0 + mode = stat.S_IMODE(full[stat.ST_MODE]) + if stat.S_ISDIR(full[stat.ST_MODE]): + if newperm & 0400: + newperm = newperm | 0100 + if newperm & 0040: + newperm = newperm | 0010 + if newperm & 0004: + newperm = newperm | 0001 + if mode != newperm: + log(_('changed mode of %s from %o to %o') % (f, mode, newperm)) + os.chmod(f, newperm) + return 1 + +if __name__ == '__main__': + import sys + + initlog('msec') + + for p in sys.argv[1:]: + fix_perms(p) + + act() + +# Perms.py ends here diff --git a/share/README b/share/README new file mode 100644 index 0000000..76b6a8f --- /dev/null +++ b/share/README @@ -0,0 +1,66 @@ +****************** +Configurations files in /etc/security/msec/ +Shell scripts in /usr/share/msec. +****************** + +Suggest & Comment : +yoann@mandrakesoft.com + +****************** +Doc of the rewritting in python: + + 0 1 2 3 4 5 +root umask 022 022 022 022 022 077 +shell timeout 0 0 0 0 3600 900 +deny services none none none none local all +su only for wheel grp no no no no no yes +user umask 022 022 022 022 077 077 +shell history size default default default default 0 0 +direct root login yes yes yes yes no no +sulogin for single user no no no no yes yes +user list in [kg]dm yes yes yes yes no no +promisc check no no no no yes yes +ignore icmp echo no no no no yes yes +ignore bogus error responses no no no no yes yes +enable libasfe no no no no yes yes +allow reboot by user yes yes yes yes no no +allow crontab/at yes yes yes yes no no +password aging no no no no 60 30 +allow autologin yes yes yes no no no +console log no no no yes yes yes +issues yes yes yes local local no +ip spoofing protection no no no yes yes yes +log stange ip packets no no no yes yes yes +periodic security check no yes yes yes yes yes +allow X connections yes local local no no no +run msec by cron yes yes yes yes yes yes + +Periodic security checks by level: + + 0 1 2 3 4 5 +CHECK_SECURITY no yes yes yes yes yes +CHECK_PERMS no no no yes yes yes +CHECK_SUID_ROOT no no yes yes yes yes +CHECK_SUID_MD5 no no yes yes yes yes +CHECK_SUID_GROUP no no yes yes yes yes +CHECK_WRITEABLE no no yes yes yes yes +CHECK_UNOWNED no no no no yes yes +CHECK_PROMISC no no no no yes yes +CHECK_OPEN_PORT no no no yes yes yes +CHECK_PASSWD no no no yes yes yes +CHECK_SHADOW no no no yes yes yes +TTY_WARN no no no no yes yes +MAIL_WARN no no no yes yes yes +SYSLOG_WARN no no yes yes yes yes +RPM_CHECK no no no yes yes yes + +These variables are configured by the user: + +MAIL_USER the user to send the dayly reports. If not set, the email is +sent to root. + +PERM_LEVEL is used to determine which file to use to fix +permissions/owners/groups (in /etc/security/msec/perm.$PERM_LEVEL). If +not set, the SECURE_LEVEL is used instead. If the file +/etc/security/msec/perm.local exists, it's used too. + diff --git a/share/compile.py b/share/compile.py new file mode 100755 index 0000000..a325016 --- /dev/null +++ b/share/compile.py @@ -0,0 +1,17 @@ +#!/usr/bin/python -O +############################################################################# +# File : compile.py +# Package : rpmlint +# Author : Frederic Lepied +# Created on : Sat Oct 23 23:40:21 1999 +# Version : $Id$ +# Purpose : byte compile all python files given in arguments. +############################################################################# + +import py_compile +import sys + +for f in sys.argv[2:]: + py_compile.compile(f, f+"o", sys.argv[1] + f) + +# compile.py ends here diff --git a/share/libmsec.py b/share/libmsec.py new file mode 100644 index 0000000..330244a --- /dev/null +++ b/share/libmsec.py @@ -0,0 +1,488 @@ +#--------------------------------------------------------------- +# Project : Mandrake Linux +# Module : share +# File : libmsec.py +# Version : $Id$ +# Author : Frederic Lepied +# Created On : Mon Dec 10 22:52:17 2001 +#--------------------------------------------------------------- + +import ConfigFile +import Config +from Log import * +import os +import grp +import Perms +import gettext +import pwd +import re +import string +import commands + +try: + cat = gettext.Catalog('msec') + _ = cat.gettext +except IOError: + _ = str + +SUFFIX='.msec' +_interactive=0 + +# list of config files + +ATALLOW = '/etc/at.allow' +AUTOLOGIN = '/etc/sysconfig/autologin' +BASTILLENOLOGIN = '/etc/bastille-no-login' +CRON = '/etc/cron.d/msec' +CRONALLOW = '/etc/cron.allow' +GDM = '/etc/pam.d/gdm' +GDMCONF = '/etc/X11/gdm/gdm.conf' +HALT = '/etc/security/console.apps/halt' +HOSTCONF = '/etc/host.conf' +HOSTSDENY = '/etc/hosts.deny' +INITTAB = '/etc/inittab' +ISSUE = '/etc/issue' +ISSUENET = '/etc/issue.net' +KDE = '/etc/pam.d/kde' +KDMRC = '/usr/share/config/kdm/kdmrc' +LDSOPRELOAD = '/etc/ld.so.preload' +LILOCONF = '/etc/lilo.conf' +LOGINDEFS = '/etc/login.defs' +MENULST = '/boot/grub/menu.lst' +MSEC = '/etc/sysconfig/msec' +MSECBIN = '/usr/sbin/msec' +MSECCRON = '/etc/cron.hourly/msec' +MSEC_XINIT = '/etc/X11/xinit.d/msec' +PASSWD = '/etc/pam.d/passwd' +POWEROFF = '/etc/security/console.apps/poweroff' +REBOOT = '/etc/security/console.apps/reboot' +SECURETTY = '/etc/securetty' +SHADOW = '/etc/shadow' +SHUTDOWN = '/etc/security/console.apps/shutdown' +SHUTDOWNALLOW = '/etc/shutdown.allow' +SSHDCONFIG = '/etc/ssh/sshd_config' +SU = '/etc/pam.d/su' +SYSCTLCONF = '/etc/sysctl.conf' +SYSLOGCONF = '/etc/syslog.conf' +XDM = '/etc/pam.d/xdm' + +# config files => actions + +ConfigFile.add_config_assoc(INITTAB, '/sbin/telinit q') +ConfigFile.add_config_assoc('/etc(?:/rc.d)?/init.d/(.+)', '[ -f /var/lock/subsys/@1 ] && @0 reload') +ConfigFile.add_config_assoc(SYSCTLCONF, '/sbin/sysctl -e -p /etc/sysctl.conf; service network restart') +ConfigFile.add_config_assoc(SSHDCONFIG, '[ -f /var/lock/subsys/sshd ] && /etc/rc.d/init.d/sshd restart') +ConfigFile.add_config_assoc(LILOCONF, '[ `/usr/sbin/detectloader` = LILO ] && /sbin/lilo') +ConfigFile.add_config_assoc(SYSLOGCONF, '[ -f /var/lock/subsys/syslog ] && service syslog reload') +ConfigFile.add_config_assoc('^/etc/issue$', '/usr/bin/killall mingetty') + +# configuration rules + +def set_secure_level(level): + _interactive and log(_('Setting secure level to %s') % level) + msec = ConfigFile.get_config_file(MSEC) + msec.set_shell_variable('SECURE_LEVEL', level) + +def get_secure_level(): + msec = ConfigFile.get_config_file(MSEC) + return msec.get_shell_variable('SECURE_LEVEL') + +def set_root_umask(umask): + _interactive and log(_('Setting root umask to %s') % umask) + msec = ConfigFile.get_config_file(MSEC) + msec.set_shell_variable('UMASK_ROOT', umask) + +def set_user_umask(umask): + _interactive and log(_('Setting users umask to %s') % umask) + msec = ConfigFile.get_config_file(MSEC) + msec.set_shell_variable('UMASK_USER', umask) + +def allow_x_connections(): + _interactive and log(_('Allowing users to connect X server from everywhere')) + msec = ConfigFile.get_config_file(MSEC_XINIT) + msec.replace_line_matching('/usr/X11R6/bin/xhost', '/usr/X11R6/bin/xhost +', 1) + +def allow_local_x_connections(): + _interactive and log(_('Allowing users to connect X server from localhost')) + msec = ConfigFile.get_config_file(MSEC_XINIT) + msec.replace_line_matching('/usr/X11R6/bin/xhost', '/usr/X11R6/bin/xhost + localhost', 1) + +def restrict_x_connections(): + _interactive and log(_('Restricting X server connection to the console user')) + msec = ConfigFile.get_config_file(MSEC_XINIT) + msec.remove_line_matching('/usr/X11R6/bin/xhost', 1) + +def set_shell_timeout(val): + _interactive and log(_('Setting shell timeout to %s') % val) + msec = ConfigFile.get_config_file(MSEC) + msec.set_shell_variable('TMOUT', val) + +def set_shell_history_size(size): + if size >= 0: + _interactive and log(_('Setting shell history size to %s') % size) + msec = ConfigFile.get_config_file(MSEC) + msec.set_shell_variable('HISTFILESIZE', size) + else: + _interactive and log(_('Removing limit on shell history size')) + msec = ConfigFile.get_config_file(MSEC) + msec. remove_line_matching('^HISTFILESIZE=') + +def allow_reboot(): + _interactive and log(_('Allowing reboot to the console user')) + shutdownallow = ConfigFile.get_config_file(SHUTDOWNALLOW) + shutdownallow.exists() and shutdownallow.move(SUFFIX) + for f in [SHUTDOWN, POWEROFF, REBOOT, HALT]: + ConfigFile.get_config_file(f).touch() + sysctlconf = ConfigFile.get_config_file(SYSCTLCONF) + sysctlconf.set_shell_variable('kernel.sysrq', 1) + kdmrc = ConfigFile.get_config_file(KDMRC) + kdmrc.exists() and kdmrc.set_shell_variable('AllowShutdown', 'All', 'X-:\*-Greeter', '^\s*$') + gdmconf = ConfigFile.get_config_file(GDMCONF) + gdmconf.exists() and gdmconf.set_shell_variable('SystemMenu', 'true', '\[greeter\]', '^\s*$') + +def forbid_reboot(): + _interactive and log(_('Forbidding reboot to the console user')) + ConfigFile.get_config_file(SHUTDOWNALLOW, SUFFIX).touch() + for f in [SHUTDOWN, POWEROFF, REBOOT, HALT]: + ConfigFile.get_config_file(f).unlink() + sysctlconf = ConfigFile.get_config_file(SYSCTLCONF) + sysctlconf.set_shell_variable('kernel.sysrq', 0) + kdmrc = ConfigFile.get_config_file(KDMRC) + kdmrc.exists() and kdmrc.set_shell_variable('AllowShutdown', 'None', 'X-:\*-Greeter', '^\s*$') + gdmconf = ConfigFile.get_config_file(GDMCONF) + gdmconf.exists() and gdmconf.set_shell_variable('SystemMenu', 'false', '\[greeter\]', '^\s*$') + +def allow_user_list(): + _interactive and log(_('Allowing the listing of users in display managers')) + kdmrc = ConfigFile.get_config_file(KDMRC) + kdmrc.exists() and kdmrc.set_shell_variable('ShowUsers', 'All') + gdmconf = ConfigFile.get_config_file(GDMCONF) + gdmconf.exists() and gdmconf.set_shell_variable('Browser', '1') + +def forbid_user_list(): + _interactive and log(_('Disabling the listing of users in display managers')) + kdmrc = ConfigFile.get_config_file(KDMRC) + kdmrc.exists() and kdmrc.set_shell_variable('ShowUsers', 'None') + gdmconf = ConfigFile.get_config_file(GDMCONF) + gdmconf.exists() and gdmconf.set_shell_variable('Browser', '0') + +def allow_root_login(): + _interactive and log(_('Allowing root login')) + sshd_config = ConfigFile.get_config_file(SSHDCONFIG) + sshd_config.exists() and sshd_config.replace_line_matching('^\s*PermitRootLogin\s+no', + 'PermitRootLogin yes') + + kde = ConfigFile.get_config_file(KDE) + gdm = ConfigFile.get_config_file(GDM) + xdm = ConfigFile.get_config_file(XDM) + + for cnf in (kde, gdm, xdm): + cnf.exists() and cnf.remove_line_matching('^auth\s*required\s*/lib/security/pam_listfile.so.*bastille-no-login', 1) + + securetty = ConfigFile.get_config_file(SECURETTY) + for n in range(1, 7): + s = 'tty' + str(n) + securetty.replace_line_matching(s, s, 1) + s = 'vc/' + str(n) + securetty.replace_line_matching(s, s, 1) + +def forbid_root_login(): + _interactive and log(_('Forbidding root login')) + sshd_config = ConfigFile.get_config_file(SSHDCONFIG) + sshd_config.exists() and sshd_config.replace_line_matching('^\s*PermitRootLogin\s+yes', + 'PermitRootLogin no') + + bastillenologin = ConfigFile.get_config_file(BASTILLENOLOGIN) + bastillenologin.replace_line_matching('^\s*root', 'root', 1) + + kde = ConfigFile.get_config_file(KDE) + gdm = ConfigFile.get_config_file(GDM) + xdm = ConfigFile.get_config_file(XDM) + + for cnf in (kde, gdm, xdm): + cnf.exists() and (cnf.replace_line_matching('^auth\s*required\s*/lib/security/pam_listfile.so.*bastille-no-login', 'auth required /lib/security/pam_listfile.so onerr=succeed item=user sense=deny file=/etc/bastille-no-login') or \ + cnf.insert_at(0, 'auth required /lib/security/pam_listfile.so onerr=succeed item=user sense=deny file=/etc/bastille-no-login')) + + # TODO xdm support + securetty = ConfigFile.get_config_file(SECURETTY) + securetty.remove_line_matching('.+', 1) + +def enable_pam_wheel_for_su(): + _interactive and log(_('Allowing su only from wheel group members')) + try: + ent = grp.getgrnam('wheel') + except KeyError: + error(_('no wheel group')) + return + members = ent[3] + if members == [] or members == ['root']: + error(_('wheel group is empty')) + return + su = ConfigFile.get_config_file(SU) + su.exists() and (su.replace_line_matching('^auth\s+required\s+/lib/security/pam_wheel.so\s+use_uid\s*$', + 'auth required /lib/security/pam_wheel.so use_uid') or \ + su.insert_after('^auth\s+required', + 'auth required /lib/security/pam_wheel.so use_uid')) + +def disable_pam_wheel_for_su(): + _interactive and log(_('Allowing su for all')) + su = ConfigFile.get_config_file(SU) + su.exists() and su.remove_line_matching('^auth\s+required\s+/lib/security/pam_wheel.so\s+use_uid\s*$') + +def forbid_issues(allow_local=0): + if not allow_local: + _interactive and log(_('Disabling pre-login message')) + issue = ConfigFile.get_config_file(ISSUE) + issue.exists() and issue.move(SUFFIX) and issue.modified() + else: + _interactive and log(_('Allowing pre-login message')) + issue = ConfigFile.get_config_file(ISSUE, SUFFIX) + issue.exists() and issue.get_lines() + _interactive and log(_('Disabling network pre-login message')) + issuenet = ConfigFile.get_config_file(ISSUENET) + issuenet.exists() and issuenet.move(SUFFIX) + +def allow_issues(): + _interactive and log(_('Allowing RemoteRoot pre-login messages')) + issue = ConfigFile.get_config_file(ISSUE, SUFFIX) + issue.exists() and issue.get_lines() + issuenet = ConfigFile.get_config_file(ISSUENET, SUFFIX) + issuenet.exists() and issuenet.get_lines() + +def allow_autologin(): + _interactive and log(_('Allowing autologin')) + autologin = ConfigFile.get_config_file(AUTOLOGIN) + autologin.exists() and autologin.set_shell_variable('AUTOLOGIN', 'yes') + +def forbid_autologin(): + _interactive and log(_('Forbidding autologin')) + autologin = ConfigFile.get_config_file(AUTOLOGIN) + autologin.exists() and autologin.set_shell_variable('AUTOLOGIN', 'no') + +def password_loader(value): + _interactive and log(_('Activating password in boot loader')) + liloconf = ConfigFile.get_config_file(LILOCONF) + liloconf.exists() and (liloconf.replace_line_matching('^password=', 'password="' + value + '"', 0, 1) or \ + liloconf.insert_after('^boot=', 'password="' + value + '"')) and \ + Perms.chmod(liloconf.path, 0600) + # TODO encrypt password in grub + menulst = ConfigFile.get_config_file(MENULST) + menulst.exists() and (menulst.replace_line_matching('^password\s', 'password "' + value + '"') or \ + menulst.insert_at(0, 'password "' + value + '"')) and \ + Perms.chmod(menulst.path, 0600) + # TODO add yaboot support + +def nopassword_loader(): + _interactive and log(_('Removing password in boot loader')) + liloconf = ConfigFile.get_config_file(LILOCONF) + liloconf.exists() and liloconf.remove_line_matching('^password=', 1) + menulst = ConfigFile.get_config_file(MENULST) + menulst.exists() and menulst.remove_line_matching('^password\s') + +def enable_console_log(): + _interactive and log(_('Enabling log on console 12')) + syslogconf = ConfigFile.get_config_file(SYSLOGCONF) + syslogconf.exists() and syslogconf.replace_line_matching('\s*[^#]+/dev/tty12', '*.* /dev/tty12', 1) + +def disable_console_log(): + _interactive and log(_('Disabling log on console 12')) + syslogconf = ConfigFile.get_config_file(SYSLOGCONF) + syslogconf.exists() and syslogconf.remove_line_matching('\*\.\*\s*/dev/tty12') + +def enable_promisc_check(): + _interactive and log(_('Activating periodic promiscuity check')) + cron = ConfigFile.get_config_file(CRON) + cron.replace_line_matching('[^#]+/usr/share/msec/promisc_check.sh', '*/1 * * * * root /usr/share/msec/promisc_check.sh', 1) + +def disable_promisc_check(): + _interactive and log(_('Disabling periodic promiscuity check')) + cron = ConfigFile.get_config_file(CRON) + cron.remove_line_matching('[^#]+/usr/share/msec/promisc_check.sh') + +def enable_security_check(): + _interactive and log(_('Activating daily security check')) + cron = ConfigFile.get_config_file(CRON) + cron.replace_line_matching('[^#]+/usr/share/msec/security.sh', '0 4 * * * root /usr/share/msec/security.sh', 1) + +def disable_security_check(): + _interactive and log(_('Disabling daily security check')) + cron = ConfigFile.get_config_file(CRON) + cron.remove_line_matching('[^#]+/usr/share/msec/security.sh') + +def deny_all_services(): + _interactive and log(_('Disabling all services')) + hostsdeny = ConfigFile.get_config_file(HOSTSDENY) + hostsdeny.remove_line_matching('^ALL:ALL EXCEPT localhost:DENY', 1) + hostsdeny.replace_line_matching('^ALL:ALL:DENY$', 'ALL:ALL:DENY', 1) + +def deny_non_local_services(): + _interactive and log(_('Disabling non local services')) + hostsdeny = ConfigFile.get_config_file(HOSTSDENY) + hostsdeny.remove_line_matching('^ALL:ALL:DENY', 1) + hostsdeny.replace_line_matching('^ALL:ALL EXCEPT localhost:DENY$', 'ALL:ALL EXCEPT localhost:DENY', 1) + +def authorize_all_services(): + _interactive and log(_('Authorizing all services')) + hostsdeny = ConfigFile.get_config_file(HOSTSDENY) + hostsdeny.remove_line_matching('^ALL:ALL:DENY', 1) + hostsdeny.remove_line_matching('^ALL:ALL EXCEPT localhost:DENY', 1) + +def enable_ip_spoofing_protection(alert): + _interactive and log(_('Enabling ip spoofing protection')) + hostconf = ConfigFile.get_config_file(HOSTCONF) + hostconf.replace_line_matching('nospoof', 'nospoof on', 1) + hostconf.replace_line_matching('spoofalert', 'spoofalert on', (alert != 0)) + sysctlconf = ConfigFile.get_config_file(SYSCTLCONF) + sysctlconf.set_shell_variable('net.ipv4.conf.all.rp_filter', 1) + +def disable_ip_spoofing_protection(): + _interactive and log(_('Disabling ip spoofing protection')) + hostconf = ConfigFile.get_config_file(HOSTCONF) + hostconf.remove_line_matching('nospoof') + hostconf.remove_line_matching('spoofalert') + +def ignore_icmp_echo(): + _interactive and log(_('Ignoring icmp echo')) + sysctlconf = ConfigFile.get_config_file(SYSCTLCONF) + sysctlconf.set_shell_variable('net.ipv4.icmp_echo_ignore_all', 1) + sysctlconf.set_shell_variable('net.ipv4.icmp_echo_ignore_broadcasts', 1) + +def accept_icmp_echo(): + _interactive and log(_('Accepting icmp echo')) + sysctlconf = ConfigFile.get_config_file(SYSCTLCONF) + sysctlconf.set_shell_variable('net.ipv4.icmp_echo_ignore_all', 0) + sysctlconf.set_shell_variable('net.ipv4.icmp_echo_ignore_broadcasts', 0) + +def ignore_bogus_error_responses(): + _interactive and log(_('Ignoring bogus icmp error responses')) + sysctlconf = ConfigFile.get_config_file(SYSCTLCONF) + sysctlconf.set_shell_variable('net.ipv4.icmp_ignore_bogus_error_responses', 1) + +def accept_bogus_error_responses(): + _interactive and log(_('Accepting bogus icmp error responses')) + sysctlconf = ConfigFile.get_config_file(SYSCTLCONF) + sysctlconf.set_shell_variable('net.ipv4.icmp_ignore_bogus_error_responses', 0) + +def enable_log_strange_packets(): + _interactive and log(_('Enabling logging of strange packets')) + sysctlconf = ConfigFile.get_config_file(SYSCTLCONF) + sysctlconf.set_shell_variable('net.ipv4.conf.all.log_martians', 1) + +def disable_log_strange_packets(): + _interactive and log(_('Disabling logging of strange packets')) + sysctlconf = ConfigFile.get_config_file(SYSCTLCONF) + sysctlconf.set_shell_variable('net.ipv4.conf.all.log_martians', 0) + +def enable_libsafe(): + if os.path.exists(Config.get_config('root', '') + '/lib/libsafe.so.2'): + _interactive and log(_('Enabling libsafe')) + ldsopreload = ConfigFile.get_config_file(LDSOPRELOAD) + ldsopreload.replace_line_matching('[^#]*libsafe', '/lib/libsafe.so.2', 1) + +def disable_libsafe(): + _interactive and log(_('Disabling libsafe')) + ldsopreload = ConfigFile.get_config_file(LDSOPRELOAD) + ldsopreload.remove_line_matching('[^#]*libsafe') + +def password_length(length, ndigits=0, nupper=0): + _interactive and log(_('Setting minimum password length %d') % length) + passwd = ConfigFile.get_config_file(PASSWD) + passwd.exists() and (passwd.replace_line_matching('^(password\s+required\s+/lib/security/pam_cracklib.so.*?)(\sminlen=[0-9]+\s)(.*)', + '@1 minlen=%s @3' % length) or \ + passwd.replace_line_matching('^password\s+required\s+/lib/security/pam_cracklib.so.*', + '@0 minlen=%s ' % length)) + + passwd.exists() and (passwd.replace_line_matching('^(password\s+required\s+/lib/security/pam_cracklib.so.*?)(\sdcredit=[0-9]+\s)(.*)', + '@1 dcredit=%s @3' % ndigits) or \ + passwd.replace_line_matching('^password\s+required\s+/lib/security/pam_cracklib.so.*', + '@0 dcredit=%s ' % ndigits)) + + passwd.exists() and (passwd.replace_line_matching('^(password\s+required\s+/lib/security/pam_cracklib.so.*?)(\sucredit=[0-9]+\s)(.*)', + '@1 ucredit=%s @3' % nupper) or \ + passwd.replace_line_matching('^password\s+required\s+/lib/security/pam_cracklib.so.*', + '@0 ucredit=%s ' % nupper)) + +def enable_sulogin(): + _interactive and log(_('Enabling sulogin in single user runlevel')) + inittab = ConfigFile.get_config_file(INITTAB) + inittab.replace_line_matching('[^#]+:S:', '~~:S:wait:/sbin/sulogin', 1) + +def disable_sulogin(): + _interactive and log(_('Disabling sulogin in single user runlevel')) + inittab = ConfigFile.get_config_file(INITTAB) + inittab.remove_line_matching('~~:S:wait:/sbin/sulogin') + +def enable_msec_cron(): + _interactive and log(_('Enabling msec periodic runs')) + mseccron = ConfigFile.get_config_file(MSECCRON) + mseccron.symlink(MSECBIN) + +def disable_msec_cron(): + _interactive and log(_('Disabling msec periodic runs')) + mseccron = ConfigFile.get_config_file(MSECCRON) + mseccron.unlink() + +def disable_at_crontab(): + _interactive and log(_('Disabling crontab and at')) + cronallow = ConfigFile.get_config_file(CRONALLOW, SUFFIX) + cronallow.replace_line_matching('root', 'root', 1) + atallow = ConfigFile.get_config_file(ATALLOW, SUFFIX) + atallow.replace_line_matching('root', 'root', 1) + +def enable_at_crontab(): + _interactive and log(_('Enabling crontab and at')) + cronallow = ConfigFile.get_config_file(CRONALLOW) + cronallow.exists() and cronallow.move(SUFFIX) + atallow = ConfigFile.get_config_file(ATALLOW) + atallow.exists() and atallow.move(SUFFIX) + +maximum_regex = re.compile('^Maximum:\s*([0-9]+)', re.MULTILINE) + +# TODO FL Sat Dec 29 20:18:20 2001 +# replace chage calls and /etc/shadow parsing by a python API to the shadow functions. +def password_aging(max): + uid_min = 500 + _interactive and log(_('Setting password maximum aging for new user to %d') % max) + logindefs = ConfigFile.get_config_file(LOGINDEFS) + if logindefs.exists(): + logindefs.replace_line_matching('^\s*PASS_MAX_DAYS', 'PASS_MAX_DAYS ' + str(max)) + uid_min = logindefs.get_match('^\s*UID_MIN\s+([0-9]+)', '@1') + if uid_min: + uid_min = int(uid_min) + shadow = ConfigFile.get_config_file(SHADOW) + if shadow.exists(): + _interactive and log(_('Setting password maximum aging for users with id greater than %d to %d') % (uid_min, max)) + for line in shadow.get_lines(): + field = string.split(line, ':') + if len(field) < 2: + continue + name = field[0] + password = field[1] + entry = pwd.getpwnam(name) + if (len(password) > 0 and password[0] != '!') and password != '*' and password != 'x' and entry[2] >= uid_min: + cmd = '/usr/bin/chage -l %s' % entry[0] + ret = commands.getstatusoutput(cmd) + _interactive and log(_('got current maximum password aging for user %s with command \'%s\'') % (entry[0], cmd)) + if ret[0] == 0: + res = maximum_regex.search(ret[1]) + if res: + current_max = int(res.group(1)) + if max != current_max: + cmd = '/usr/bin/chage -M %d %s' % (max, entry[0]) + ret = commands.getstatusoutput(cmd) + log(_('changed maximum password aging for user %s with command %s') % (entry[0], cmd)) + if ret[0] != 0: + error(ret[1]) + else: + error(_('unable to parse chage output')) + else: + error(_('unable to run chage: %s') % ret[1]) + +# various + +def set_interactive(v): + global _interactive + + _interactive = v + +# libmsec.py ends here diff --git a/share/msec b/share/msec new file mode 100755 index 0000000..423766c --- /dev/null +++ b/share/msec @@ -0,0 +1,48 @@ +#!/bin/sh +#--------------------------------------------------------------- +# Project : Mandrake Linux +# Module : share +# File : msec +# Version : $Id$ +# Author : Frederic Lepied +# Created On : Thu Dec 13 11:36:50 2001 +#--------------------------------------------------------------- + +MSEC=/usr/share/msec/msec.py + +for a in "$@"; do + last="$a" +done + +if [ -n "$last" ]; then + case $last in + [0-5]) ;; + *) [ -x /usr/share/msec/$last.py ] && MSEC=/usr/share/msec/$last.py;; + esac +else + # no args so try to guess if a custom msec is needed + . /etc/sysconfig/msec + + case "$SECURE_LEVEL" in + [0-5]) ;; + *) MSEC=/usr/share/msec/$SECURE_LEVEL.py;; + esac +fi + +if [ ! -x $MSEC ]; then + echo "/usr/share/msec/$last.py not found or not executable. Aborting" 1>&2 + exit 1 +fi + +if $MSEC "$@"; then + . /etc/sysconfig/msec + + [ -z "$PERM_LEVEL" ] && PERM_LEVEL=$SECURE_LEVEL + + LOCAL= + [ -f /etc/security/msec/perm.local ] && LOCAL=/etc/security/msec/perm.local + + /usr/share/msec/Perms.py /etc/security/msec/perm.$PERM_LEVEL $LOCAL +fi + +# msec.sh ends here diff --git a/share/msec.py b/share/msec.py new file mode 100755 index 0000000..8ab0a3f --- /dev/null +++ b/share/msec.py @@ -0,0 +1,195 @@ +#!/usr/bin/python -O +#--------------------------------------------------------------- +# Project : Mandrake Linux +# Module : msec/share +# File : msec.py +# Version : $Id$ +# Author : Frederic Lepied +# Created On : Wed Dec 5 20:20:21 2001 +#--------------------------------------------------------------- + +from libmsec import * +from Log import * +from Log import _name +import Config +import sys +import os +import string +import getopt +import gettext + +try: + cat = gettext.Catalog('msec') + _ = cat.gettext +except IOError: + _ = str + +# program +_name = 'msec' + +sys.argv[0] = os.path.basename(sys.argv[0]) + +try: + (opt, args) = getopt.getopt(sys.argv[1:], 'o:', + ['option']) +except getopt.error: + error(_('Invalid option. Use %s (-o var=<val>...) ([0-5])') % sys.argv[0]) + sys.exit(1) + + +for o in opt: + if o[0] == '-o' or o[0] == '--option': + pair = string.split(o[1], '=') + if len(pair) != 2: + error(_('Invalid option format %s %s: use -o var=<val>') % (o[0], o[1])) + sys.exit(1) + else: + Config.set_config(pair[0], pair[1]) + +interactive = sys.stdin.isatty() +set_interactive(interactive) + +# initlog must be done after processing the option because we can change +# the way to report log with options... +if interactive: + import syslog + + initlog('msec', syslog.LOG_LOCAL1) +else: + initlog('msec') + +if len(args) == 0: + level = get_secure_level() + if level == None: + error(_('Secure level not set. Use %s <secure level> to set it.') % sys.argv[0]) + sys.exit(1) +else: + level = args[0] + +try: + level = int(level) +except ValueError: + error(_('Invalid secure level %s. Use %s [0-5] to set it.') % (level, sys.argv[0])) + sys.exit(1) + +if level < 0 or level > 5: + error(_('Invalid secure level %s. Use %s [0-5] to set it.') % (level, sys.argv[0])) + sys.exit(1) + +set_secure_level(level) + +server=(level in range(3, 6)) + +# for all levels: min length = 2 * (level - 1) and for level 4,5 makes mandatory +# to have at least one upper case character and one digit. +if level > 1: + password_length = (level - 1) * 2 +else: + password_length = 0 + +password_length(password_length, level / 4, level / 4) + +enable_ip_spoofing_protection(server) + +# differences between level 5 and others +if level == 5: + set_root_umask('077') + set_shell_timeout(900) + deny_all_services() + enable_pam_wheel_for_su() +else: + set_root_umask('022') + if level == 4: + set_shell_timeout(3600) + deny_non_local_services() + else: + set_shell_timeout(0) + authorize_all_services() + disable_pam_wheel_for_su() + +# differences between level 4,5 and others +if level >= 4: + set_user_umask('077') + set_shell_history_size(10) + forbid_root_login() + enable_sulogin() + forbid_user_list() + enable_promisc_check() + ignore_icmp_echo() + ignore_bogus_error_responses() + enable_libsafe() + forbid_reboot() + disable_at_crontab() + if level == 4: + password_aging(60) + else: + password_aging(30) +else: + set_user_umask('022') + set_shell_history_size(-1) + allow_root_login() + disable_sulogin() + allow_user_list() + disable_promisc_check() + accept_icmp_echo() + accept_bogus_error_responses() + disable_libsafe() + allow_reboot() + enable_at_crontab() + password_aging(99999) + +# differences between level 3,4,5 and others +if server: + forbid_autologin() + enable_console_log() + forbid_issues((level != 5)) + enable_log_strange_packets() +else: + allow_autologin() + disable_console_log() + allow_issues() + disable_log_strange_packets() + +# differences between level 0 and others +if level != 0: + enable_security_check() + if level < 3: + allow_local_x_connections() + else: + restrict_x_connections() +else: + disable_security_check() + allow_x_connections() + +# msec cron +enable_msec_cron() + +# 0 1 2 3 4 5 +FILE_CHECKS = {'CHECK_SECURITY' : ('no', 'yes', 'yes', 'yes', 'yes', 'yes', ), + 'CHECK_PERMS' : ('no', 'no', 'no', 'yes', 'yes', 'yes', ), + 'CHECK_SUID_ROOT' : ('no', 'no', 'yes', 'yes', 'yes', 'yes', ), + 'CHECK_SUID_MD5' : ('no', 'no', 'yes', 'yes', 'yes', 'yes', ), + 'CHECK_SUID_GROUP' : ('no', 'no', 'yes', 'yes', 'yes', 'yes', ), + 'CHECK_WRITEABLE' : ('no', 'no', 'yes', 'yes', 'yes', 'yes', ), + 'CHECK_UNOWNED' : ('no', 'no', 'no', 'no', 'yes', 'yes', ), + 'CHECK_PROMISC' : ('no', 'no', 'no', 'no', 'yes', 'yes', ), + 'CHECK_OPEN_PORT' : ('no', 'no', 'no', 'yes', 'yes', 'yes', ), + 'CHECK_PASSWD' : ('no', 'no', 'no', 'yes', 'yes', 'yes', ), + 'CHECK_SHADOW' : ('no', 'no', 'no', 'yes', 'yes', 'yes', ), + 'TTY_WARN' : ('no', 'no', 'no', 'no', 'yes', 'yes', ), + 'MAIL_WARN' : ('no', 'no', 'no', 'yes', 'yes', 'yes', ), + 'SYSLOG_WARN' : ('no', 'no', 'yes', 'yes', 'yes', 'yes', ), + 'RPM_CHECK' : ('no', 'no', 'no', 'yes', 'yes', 'yes', ), + } + +interactive and log(_('Configuring periodic files checks')) +securityconf = ConfigFile.get_config_file('/etc/security/msec/security.conf') +for k in FILE_CHECKS.keys(): + securityconf.set_shell_variable(k, FILE_CHECKS[k][level]) + +interactive and log(_('Writing config files and then taking needed actions')) +ConfigFile.write_files() + +closelog() + +# msec.py ends here |