aboutsummaryrefslogtreecommitdiffstats
path: root/src/msec/libmsec.py
diff options
context:
space:
mode:
authorEugeni Dodonov <eugeni@mandriva.org>2009-03-05 16:31:58 +0000
committerEugeni Dodonov <eugeni@mandriva.org>2009-03-05 16:31:58 +0000
commit522c53299a1e6b1376d95cd93fae7f87b3baf20e (patch)
treeb296f5105291cf6086b5f32c1f29e0ba65371b46 /src/msec/libmsec.py
parentc23b287246c21d8fedae4aa22c90ef143e88d570 (diff)
downloadmsec-522c53299a1e6b1376d95cd93fae7f87b3baf20e.tar
msec-522c53299a1e6b1376d95cd93fae7f87b3baf20e.tar.gz
msec-522c53299a1e6b1376d95cd93fae7f87b3baf20e.tar.bz2
msec-522c53299a1e6b1376d95cd93fae7f87b3baf20e.tar.xz
msec-522c53299a1e6b1376d95cd93fae7f87b3baf20e.zip
Added PAM plugin.
Diffstat (limited to 'src/msec/libmsec.py')
-rwxr-xr-xsrc/msec/libmsec.py278
1 files changed, 54 insertions, 224 deletions
diff --git a/src/msec/libmsec.py b/src/msec/libmsec.py
index 551ba12..6c1d8b9 100755
--- a/src/msec/libmsec.py
+++ b/src/msec/libmsec.py
@@ -93,20 +93,16 @@ OPASSWD = '/etc/security/opasswd'
PASSWD = '/etc/pam.d/passwd'
POWEROFF = '/usr/bin/poweroff'
REBOOT = '/usr/bin/reboot'
-SECURETTY = '/etc/securetty'
SECURITYCRON = '/etc/cron.daily/msec'
SECURITYSH = '/usr/share/msec/security.sh'
SERVER = '/etc/security/msec/server'
SHADOW = '/etc/shadow'
SHUTDOWN = '/usr/bin/shutdown'
SHUTDOWNALLOW = '/etc/shutdown.allow'
-SIMPLE_ROOT_AUTHEN = '/etc/pam.d/simple_root_authen'
SSHDCONFIG = '/etc/ssh/sshd_config'
STARTX = '/usr/bin/startx'
-SU = '/etc/pam.d/su'
SYSCTLCONF = '/etc/sysctl.conf'
SYSLOGCONF = '/etc/syslog.conf'
-SYSTEM_AUTH = '/etc/pam.d/system-auth'
XDM = '/etc/pam.d/xdm'
XSERVERS = '/etc/X11/xdm/Xservers'
EXPORT = '/root/.xauth/export'
@@ -121,6 +117,7 @@ AFTER=2
# regexps
space = re.compile('\s')
# X server
+SECURETTY = '/etc/securetty'
STARTX_REGEXP = '(\s*serverargs=".*) -nolisten tcp(.*")'
XSERVERS_REGEXP = '(\s*[^#]+/usr/bin/X .*) -nolisten tcp(.*)'
GDMCONF_REGEXP = '(\s*command=.*/X.*?) -nolisten tcp(.*)$'
@@ -131,22 +128,12 @@ CTRALTDEL_REGEXP = '^ca::ctrlaltdel:/sbin/shutdown.*'
CONSOLE_HELPER = 'consolehelper'
# ssh PermitRootLogin
PERMIT_ROOT_LOGIN_REGEXP = '^\s*PermitRootLogin\s+(no|yes|without-password|forced-commands-only)'
-# pam
-SUCCEED_MATCH = '^auth\s+sufficient\s+pam_succeed_if.so\s+use_uid\s+user\s+ingroup\s+wheel\s*$'
-SUCCEED_LINE = 'auth sufficient pam_succeed_if.so use_uid user ingroup wheel'
# cron
CRON_ENTRY = '*/1 * * * * root /usr/share/msec/promisc_check.sh'
CRON_REGEX = '[^#]+/usr/share/msec/promisc_check.sh'
# tcp_wrappers
ALL_REGEXP = '^ALL:ALL:DENY'
ALL_LOCAL_REGEXP = '^ALL:ALL EXCEPT 127\.0\.0\.1:DENY'
-# password stuff
-LENGTH_REGEXP = re.compile('^(password\s+required\s+(?:/lib/security/)?pam_cracklib.so.*?)\sminlen=([0-9]+)\s(.*)')
-NDIGITS_REGEXP = re.compile('^(password\s+required\s+(?:/lib/security/)?pam_cracklib.so.*?)\sdcredit=([0-9]+)\s(.*)')
-UCREDIT_REGEXP = re.compile('^(password\s+required\s+(?:/lib/security/)?pam_cracklib.so.*?)\sucredit=([0-9]+)\s(.*)')
-PASSWORD_REGEXP = '^\s*auth\s+sufficient\s+(?:/lib/security/)?pam_permit.so'
-UNIX_REGEXP = re.compile('(^\s*password\s+sufficient\s+(?:/lib/security/)?pam_unix.so.*)\sremember=([0-9]+)(.*)')
-PAM_TCB_REGEXP = re.compile('(^\s*password\s+sufficient\s+(?:/lib/security/)?pam_tcb.so.*)')
# sulogin
SULOGIN_REGEXP = '~~:S:wait:/sbin/sulogin'
@@ -1088,59 +1075,6 @@ class MSEC:
self.log.info(_("Forbidding list of users in GDM"))
gdmconf.set_shell_variable('Browser', 'false')
- def allow_root_login(self, arg):
- ''' Allow direct root login on terminal.'''
- securetty = self.configfiles.get_config_file(SECURETTY)
- kde = self.configfiles.get_config_file(KDE)
- gdm = self.configfiles.get_config_file(GDM)
- gdmconf = self.configfiles.get_config_file(GDMCONF)
- xdm = self.configfiles.get_config_file(XDM)
-
- val = {}
- val_kde = kde.get_match('auth required (?:/lib/security/)?pam_listfile.so onerr=succeed item=user sense=deny file=/etc/bastille-no-login')
- val_gdm = gdm.get_match('auth required (?:/lib/security/)?pam_listfile.so onerr=succeed item=user sense=deny file=/etc/bastille-no-login')
- val_xdm = xdm.get_match('auth required (?:/lib/security/)?pam_listfile.so onerr=succeed item=user sense=deny file=/etc/bastille-no-login')
- num = 0
- for n in range(1, 7):
- s = 'tty' + str(n)
- if securetty.get_match(s):
- num = num + 1
- s = 'vc/' + str(n)
- if securetty.get_match(s):
- num = num + 1
-
- if arg == "yes":
- if val_kde or val_gdm or val_xdm or num != 12:
- self.log.info(_('Allowing direct root login'))
- if gdmconf.exists():
- gdmconf.set_shell_variable('ConfigAvailable', 'true', '\[greeter\]', '^\s*$')
-
- for cnf in [kde, gdm, xdm]:
- if cnf.exists():
- cnf.remove_line_matching('^auth\s*required\s*(?:/lib/security/)?pam_listfile.so.*bastille-no-login', 1)
-
- 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)
- else:
- if gdmconf.exists():
- gdmconf.set_shell_variable('ConfigAvailable', 'false', '\[greeter\]', '^\s*$')
- if (kde.exists() and not val_kde) or (gdm.exists() and not val_gdm) or (xdm.exists() and not val_xdm) or num > 0:
- self.log.info(_('Forbidding direct root login'))
-
- bastillenologin = self.configfiles.get_config_file(BASTILLENOLOGIN)
- bastillenologin.replace_line_matching('^\s*root', 'root', 1)
-
- # TODO: simplify this
- for cnf in [kde, gdm, xdm]:
- if cnf.exists():
- (cnf.replace_line_matching('^auth\s*required\s*(?:/lib/security/)?pam_listfile.so.*bastille-no-login',
- 'auth required pam_listfile.so onerr=succeed item=user sense=deny file=/etc/bastille-no-login') or
- cnf.insert_at(0, 'auth required pam_listfile.so onerr=succeed item=user sense=deny file=/etc/bastille-no-login'))
- securetty.remove_line_matching('.+', 1)
-
def allow_remote_root_login(self, arg):
''' Allow remote root login via sshd. If yes, login is allowed. If without-password, only public-key authentication logins are allowed. See sshd_config(5) man page for more information.'''
sshd_config = self.configfiles.get_config_file(SSHDCONFIG)
@@ -1164,62 +1098,6 @@ class MSEC:
sshd_config.exists() and sshd_config.replace_line_matching(PERMIT_ROOT_LOGIN_REGEXP,
'PermitRootLogin without-password', 1)
- def enable_pam_wheel_for_su(self, arg):
- ''' Allow only users in wheel grup to su to root.'''
- su = self.configfiles.get_config_file(SU)
-
- val = su.get_match('^auth\s+required\s+(?:/lib/security/)?pam_wheel.so\s+use_uid\s*$')
-
- if arg == "yes":
- if not val:
- self.log.info(_('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']:
- self.log.error(_('wheel group is empty'))
- return
- if su.exists():
- (su.replace_line_matching('^[#\s]*auth\s+required\s+(?:/lib/security/)?pam_wheel.so\s+use_uid\s*$',
- 'auth required pam_wheel.so use_uid') or \
- su.insert_before('^auth\s+include', 'auth required pam_wheel.so use_uid'))
- else:
- if val:
- self.log.info(_('Allowing su for all'))
- if su.exists():
- su.replace_line_matching('^auth\s+required\s+(?:/lib/security/)?pam_wheel.so\s+use_uid\s*$',
- '# auth required pam_wheel.so use_uid')
-
- def enable_pam_root_from_wheel(self, arg):
- ''' Allow root access without password for the members of the wheel group.'''
- su = self.configfiles.get_config_file(SU)
- simple = self.configfiles.get_config_file(SIMPLE_ROOT_AUTHEN)
-
- if not su.exists():
- return
-
- val = su.get_match(SUCCEED_MATCH)
-
- val_simple = simple.get_match(SUCCEED_MATCH)
-
- if arg == "yes":
- if not val or not val_simple:
- self.log.info(_('Allowing transparent root access for wheel group members'))
- if not val:
- su.insert_before('^auth\s+sufficient', SUCCEED_LINE)
- if simple.exists() and not val_simple:
- simple.insert_before('^auth\s+sufficient', SUCCEED_LINE)
- else:
- if val or val_simple:
- self.log.info(_('Disabling transparent root access for wheel group members'))
- if val:
- su.remove_line_matching(SUCCEED_MATCH)
- if simple.exists() and val_simple:
- simple.remove_line_matching(SUCCEED_MATCH)
-
def allow_autologin(self, arg):
''' Allow autologin.'''
autologin = self.configfiles.get_config_file(AUTOLOGIN)
@@ -1368,107 +1246,6 @@ class MSEC:
''' Enable logging of strange network packets.'''
self.set_zero_one_variable(SYSCTLCONF, 'net.ipv4.conf.all.log_martians', arg, 'Enabling logging of strange packets', 'Disabling logging of strange packets')
- def password_length(self, arg):
- ''' Set the password minimum length and minimum number of digit and minimum number of capitalized letters, using length,ndigits,nupper format.'''
-
- try:
- length, ndigits, nupper = arg.split(",")
- length = int(length)
- ndigits = int(ndigits)
- nupper = int(nupper)
- except:
- self.log.error(_('Invalid password length "%s". Use "length,ndigits,nupper" as parameter') % arg)
- return
-
- passwd = self.configfiles.get_config_file(SYSTEM_AUTH)
-
- val_length = val_ndigits = val_ucredit = 999999
-
- if passwd.exists():
- val_length = passwd.get_match(LENGTH_REGEXP, '@2')
- if val_length:
- val_length = int(val_length)
-
- val_ndigits = passwd.get_match(NDIGITS_REGEXP, '@2')
- if val_ndigits:
- val_ndigits = int(val_ndigits)
-
- val_ucredit = passwd.get_match(UCREDIT_REGEXP, '@2')
- if val_ucredit:
- val_ucredit = int(val_ucredit)
-
- if passwd.exists() and (val_length != length or val_ndigits != ndigits or val_ucredit != nupper):
- self.log.info(_('Setting minimum password length %d') % length)
- (passwd.replace_line_matching(LENGTH_REGEXP,
- '@1 minlen=%s @3' % length) or \
- passwd.replace_line_matching('^password\s+required\s+(?:/lib/security/)?pam_cracklib.so.*',
- '@0 minlen=%s ' % length))
-
- (passwd.replace_line_matching(NDIGITS_REGEXP,
- '@1 dcredit=%s @3' % ndigits) or \
- passwd.replace_line_matching('^password\s+required\s+(?:/lib/security/)?pam_cracklib.so.*',
- '@0 dcredit=%s ' % ndigits))
-
- (passwd.replace_line_matching(UCREDIT_REGEXP,
- '@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_password(self, arg):
- ''' Use password to authenticate users. Take EXTREMELY care when disabling passwords, as it will leave the machine vulnerable.'''
- system_auth = self.configfiles.get_config_file(SYSTEM_AUTH)
-
- val = system_auth.get_match(PASSWORD_REGEXP)
-
- if arg == "yes":
- if val:
- self.log.info(_('Using password to authenticate users'))
- system_auth.remove_line_matching(PASSWORD_REGEXP)
- else:
- if not val:
- self.log.info(_('Don\'t use password to authenticate users'))
- system_auth.replace_line_matching(PASSWORD_REGEXP, 'auth sufficient pam_permit.so') or \
- system_auth.insert_before('auth\s+sufficient', 'auth sufficient pam_permit.so')
-
- def password_history(self, arg):
- ''' Set the password history length to prevent password reuse. This is not supported by pam_tcb. '''
-
- system_auth = self.configfiles.get_config_file(SYSTEM_AUTH)
-
- pam_tcb = system_auth.get_match(PAM_TCB_REGEXP)
- if pam_tcb:
- self.log.info(_('Password history not supported with pam_tcb.'))
- return
-
- # verify parameter validity
- # max
- try:
- history = int(arg)
- except:
- self.log.error(_('Invalid maximum password history length: "%s"') % arg)
- return
-
- if system_auth.exists():
- val = system_auth.get_match(UNIX_REGEXP, '@2')
-
- if val and val != '':
- val = int(val)
- else:
- val = 0
- else:
- val = 0
-
- if history != val:
- if history > 0:
- self.log.info(_('Setting password history to %d.') % history)
- system_auth.replace_line_matching(UNIX_REGEXP, '@1 remember=%d@3' % history) or \
- system_auth.replace_line_matching('(^\s*password\s+sufficient\s+(?:/lib/security/)?pam_unix.so.*)', '@1 remember=%d' % history)
- opasswd = self.configfiles.get_config_file(OPASSWD)
- opasswd.exists() or opasswd.touch()
- else:
- self.log.info(_('Disabling password history'))
- system_auth.replace_line_matching(UNIX_REGEXP, '@1@3')
-
def enable_sulogin(self, arg):
''' Ask for root password when going to single user level (man sulogin(8)).'''
inittab = self.configfiles.get_config_file(INITTAB)
@@ -1550,6 +1327,59 @@ class MSEC:
self.log.info(_('Disabling periodic promiscuity check'))
cron.remove_line_matching('[^#]+/usr/share/msec/promisc_check.sh')
+ def allow_root_login(self, arg):
+ ''' Allow direct root login on terminal.'''
+ securetty = self.configfiles.get_config_file(SECURETTY)
+ kde = self.configfiles.get_config_file(KDE)
+ gdm = self.configfiles.get_config_file(GDM)
+ gdmconf = self.configfiles.get_config_file(GDMCONF)
+ xdm = self.configfiles.get_config_file(XDM)
+
+ val = {}
+ val_kde = kde.get_match('auth required (?:/lib/security/)?pam_listfile.so onerr=succeed item=user sense=deny file=/etc/bastille-no-login')
+ val_gdm = gdm.get_match('auth required (?:/lib/security/)?pam_listfile.so onerr=succeed item=user sense=deny file=/etc/bastille-no-login')
+ val_xdm = xdm.get_match('auth required (?:/lib/security/)?pam_listfile.so onerr=succeed item=user sense=deny file=/etc/bastille-no-login')
+ num = 0
+ for n in range(1, 7):
+ s = 'tty' + str(n)
+ if securetty.get_match(s):
+ num = num + 1
+ s = 'vc/' + str(n)
+ if securetty.get_match(s):
+ num = num + 1
+
+ if arg == "yes":
+ if val_kde or val_gdm or val_xdm or num != 12:
+ self.log.info(_('Allowing direct root login'))
+ if gdmconf.exists():
+ gdmconf.set_shell_variable('ConfigAvailable', 'true', '\[greeter\]', '^\s*$')
+
+ for cnf in [kde, gdm, xdm]:
+ if cnf.exists():
+ cnf.remove_line_matching('^auth\s*required\s*(?:/lib/security/)?pam_listfile.so.*bastille-no-login', 1)
+
+ 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)
+ else:
+ if gdmconf.exists():
+ gdmconf.set_shell_variable('ConfigAvailable', 'false', '\[greeter\]', '^\s*$')
+ if (kde.exists() and not val_kde) or (gdm.exists() and not val_gdm) or (xdm.exists() and not val_xdm) or num > 0:
+ self.log.info(_('Forbidding direct root login'))
+
+ bastillenologin = self.configfiles.get_config_file(BASTILLENOLOGIN)
+ bastillenologin.replace_line_matching('^\s*root', 'root', 1)
+
+ # TODO: simplify this
+ for cnf in [kde, gdm, xdm]:
+ if cnf.exists():
+ (cnf.replace_line_matching('^auth\s*required\s*(?:/lib/security/)?pam_listfile.so.*bastille-no-login',
+ 'auth required pam_listfile.so onerr=succeed item=user sense=deny file=/etc/bastille-no-login') or
+ cnf.insert_at(0, 'auth required pam_listfile.so onerr=succeed item=user sense=deny file=/etc/bastille-no-login'))
+ securetty.remove_line_matching('.+', 1)
+
# The following checks are run from crontab. We only have these functions here
# to get their descriptions.