From 813dfe501348a671eeb3655cc7406c8e37a3860c Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Mon, 25 Oct 2010 17:58:37 -0400 Subject: Use kerberos password policy. This lets the KDC count password failures and can lock out accounts for a period of time. This only works for KDC >= 1.8. There currently is no way to unlock a locked account across a replica. MIT Kerberos 1.9 is adding support for doing so. Once that is available unlock will be added. The concept of a "global" password policy has changed. When we were managing the policy using the IPA password plugin it was smart enough to search up the tree looking for a policy. The KDC is not so smart and relies on the krbpwdpolicyreference to find the policy. For this reason every user entry requires this attribute. I've created a new global_policy entry to store the default password policy. All users point at this now. The group policy works the same and can override this setting. As a result the special "GLOBAL" name has been replaced with global_policy. This policy works like any other and is the default if a name is not provided on the command-line. ticket 51 --- ipalib/plugins/pwpolicy.py | 49 ++++++++++++++++++++++++++++++++-------------- ipalib/plugins/user.py | 1 + 2 files changed, 35 insertions(+), 15 deletions(-) (limited to 'ipalib') diff --git a/ipalib/plugins/pwpolicy.py b/ipalib/plugins/pwpolicy.py index 893473611..53989def3 100644 --- a/ipalib/plugins/pwpolicy.py +++ b/ipalib/plugins/pwpolicy.py @@ -63,6 +63,7 @@ from ipalib import api from ipalib import Int, Str from ipalib.plugins.baseldap import * from ipalib import _ +from ipapython.ipautil import run class cosentry(LDAPObject): """ @@ -154,8 +155,7 @@ class cosentry_find(LDAPSearch): api.register(cosentry_find) -GLOBAL_POLICY_NAME = u'GLOBAL' - +global_policy_dn = 'cn=global_policy,cn=%s,cn=kerberos,%s' % (api.env.realm, api.env.basedn) class pwpolicy(LDAPObject): """ @@ -168,7 +168,37 @@ class pwpolicy(LDAPObject): default_attributes = [ 'cn', 'cospriority', 'krbmaxpwdlife', 'krbminpwdlife', 'krbpwdhistorylength', 'krbpwdmindiffchars', 'krbpwdminlength', + 'krbpwdmaxfailure', 'krbpwdfailurecountinterval', + 'krbpwdlockoutduration', ] + has_lockout = False + lockout_params = () + (stdout, stderr, rc) = run(['klist', '-V'], raiseonerr=False) + if rc == 0: + if stdout.find('version 1.8') > -1: + has_lockout = True + + if has_lockout: + lockout_params = ( + Int('krbpwdmaxfailure?', + cli_name='maxfail', + label=_('Max failures'), + doc=_('Consecutive failures before lockout'), + minvalue=0, + ), + Int('krbpwdfailurecountinterval?', + cli_name='failinterval', + label=_('Failure reset interval'), + doc=_('Period after which failure count will be reset (seconds)'), + minvalue=0, + ), + Int('krbpwdlockoutduration?', + cli_name='lockouttime', + label=_('Lockout duration'), + doc=_('Period for which lockout is enforced (seconds)'), + minvalue=0, + ), + ) label = _('Password Policy') @@ -216,14 +246,14 @@ class pwpolicy(LDAPObject): doc=_('Priority of the policy (higher number means lower priority'), minvalue=0, ), - ) + ) + lockout_params def get_dn(self, *keys, **options): if keys[-1] is not None: return self.backend.make_dn_from_attr( self.primary_key.name, keys[-1], self.container_dn ) - return self.api.env.container_accounts + return global_policy_dn def convert_time_for_output(self, entry_attrs, **options): # Convert seconds to hours and days for displaying to user @@ -348,8 +378,6 @@ class pwpolicy_mod(LDAPUpdate): if not options.get('raw', False): if options.get('cospriority') is not None: entry_attrs['cospriority'] = [unicode(options['cospriority'])] - if keys[-1] is None: - entry_attrs['cn'] = GLOBAL_POLICY_NAME self.obj.convert_time_for_output(entry_attrs, **options) return dn @@ -394,8 +422,6 @@ class pwpolicy_show(LDAPRetrieve): entry_attrs['cospriority'] = cos_entry['cospriority'] except errors.NotFound: pass - else: - entry_attrs['cn'] = GLOBAL_POLICY_NAME self.obj.convert_time_for_output(entry_attrs, **options) return dn @@ -418,13 +444,6 @@ class pwpolicy_find(LDAPSearch): except errors.NotFound: pass self.obj.convert_time_for_output(e[1], **options) - if not args[-1]: - global_entry = self.api.Command.pwpolicy_show( - all=options.get('all', False), raw=options.get('raw', False) - )['result'] - dn = global_entry['dn'] - del global_entry['dn'] - entries.insert(0, (dn, global_entry)) api.register(pwpolicy_find) diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py index 6bfb7b6fb..086dc3933 100644 --- a/ipalib/plugins/user.py +++ b/ipalib/plugins/user.py @@ -177,6 +177,7 @@ class user_add(LDAPCreate): home_dir = '%s/%s' % (homes_root, keys[-1]) home_dir = home_dir.replace('//', '/').rstrip('/') entry_attrs['homedirectory'] = home_dir + entry_attrs.setdefault('krbpwdpolicyreference', 'cn=global_policy,cn=%s,cn=kerberos,%s' % (api.env.realm, api.env.basedn)) if ldap.has_upg(): # User Private Groups - uidNumber == gidNumber -- cgit