Normalize uid in user principal to lower-case and do validation

Use same normalization and validation in passwd plugin and add some
tests for invalid principals

https://fedorahosted.org/freeipa/ticket/1778
This commit is contained in:
Rob Crittenden
2011-09-16 09:35:48 -04:00
committed by Martin Kosek
parent 37836a2e6c
commit a1430dcb2c
5 changed files with 114 additions and 16 deletions

View File

@@ -1830,7 +1830,7 @@ output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDA
output: Output('value', <type 'unicode'>, "The primary_key value of the entry, e.g. 'jdoe' for a user")
command: passwd
args: 2,0,3
arg: Str('principal', autofill=True, cli_name='user', create_default=<lambda>, label=Gettext('User name', domain='ipa', localedir=None), primary_key=True)
arg: Str('principal', validate_principal, autofill=True, cli_name='user', create_default=<lambda>, label=Gettext('User name', domain='ipa', localedir=None), normalizer=<lambda>, primary_key=True)
arg: Password('password', label=Gettext('Password', domain='ipa', localedir=None))
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), 'User-friendly description of action performed')
output: Output('result', <type 'bool'>, 'True means the operation was successful')
@@ -2729,7 +2729,7 @@ option: Str('initials', attribute=True, autofill=True, cli_name='initials', defa
option: Str('homedirectory', attribute=True, cli_name='homedir', default_from=DefaultFrom(<lambda>, 'uid'), label=Gettext('Home directory', domain='ipa', localedir=None), multivalue=False, required=False)
option: Str('gecos', attribute=True, autofill=True, cli_name='gecos', default_from=DefaultFrom(<lambda>, 'givenname', 'sn'), label=Gettext('GECOS field', domain='ipa', localedir=None), multivalue=False, required=False)
option: Str('loginshell', attribute=True, cli_name='shell', default=u'/bin/sh', label=Gettext('Login shell', domain='ipa', localedir=None), multivalue=False, required=False)
option: Str('krbprincipalname', attribute=True, autofill=True, cli_name='principal', default_from=DefaultFrom(<lambda>, 'uid'), flags=['no_update'], label=Gettext('Kerberos principal', domain='ipa', localedir=None), multivalue=False, required=False)
option: Str('krbprincipalname', validate_principal, attribute=True, autofill=True, cli_name='principal', default_from=DefaultFrom(<lambda>, 'uid'), flags=['no_update'], label=Gettext('Kerberos principal', domain='ipa', localedir=None), multivalue=False, normalizer=<lambda>, required=False)
option: Str('mail', attribute=True, cli_name='email', label=Gettext('Email address', domain='ipa', localedir=None), multivalue=True, required=False)
option: Password('userpassword', attribute=True, cli_name='password', exclude='webui', label=Gettext('Password', domain='ipa', localedir=None), multivalue=False, required=False)
option: Int('uidnumber', attribute=True, autofill=True, cli_name='uid', default=999, label=Gettext('UID', domain='ipa', localedir=None), minvalue=1, multivalue=False, required=False)
@@ -2786,7 +2786,7 @@ option: Str('initials', attribute=True, autofill=False, cli_name='initials', def
option: Str('homedirectory', attribute=True, autofill=False, cli_name='homedir', default_from=DefaultFrom(<lambda>, 'uid'), label=Gettext('Home directory', domain='ipa', localedir=None), multivalue=False, query=True, required=False)
option: Str('gecos', attribute=True, autofill=False, cli_name='gecos', default_from=DefaultFrom(<lambda>, 'givenname', 'sn'), label=Gettext('GECOS field', domain='ipa', localedir=None), multivalue=False, query=True, required=False)
option: Str('loginshell', attribute=True, autofill=False, cli_name='shell', default=u'/bin/sh', label=Gettext('Login shell', domain='ipa', localedir=None), multivalue=False, query=True, required=False)
option: Str('krbprincipalname', attribute=True, autofill=False, cli_name='principal', default_from=DefaultFrom(<lambda>, 'uid'), flags=['no_update'], label=Gettext('Kerberos principal', domain='ipa', localedir=None), multivalue=False, query=True, required=False)
option: Str('krbprincipalname', validate_principal, attribute=True, autofill=False, cli_name='principal', default_from=DefaultFrom(<lambda>, 'uid'), flags=['no_update'], label=Gettext('Kerberos principal', domain='ipa', localedir=None), multivalue=False, normalizer=<lambda>, query=True, required=False)
option: Str('mail', attribute=True, autofill=False, cli_name='email', label=Gettext('Email address', domain='ipa', localedir=None), multivalue=True, query=True, required=False)
option: Password('userpassword', attribute=True, autofill=False, cli_name='password', exclude='webui', label=Gettext('Password', domain='ipa', localedir=None), multivalue=False, query=True, required=False)
option: Int('uidnumber', attribute=True, autofill=False, cli_name='uid', default=999, label=Gettext('UID', domain='ipa', localedir=None), minvalue=1, multivalue=False, query=True, required=False)

View File

@@ -22,6 +22,7 @@ from ipalib import Command
from ipalib import Str, Password
from ipalib import _
from ipalib import output
from ipalib.plugins.user import split_principal, validate_principal, normalize_principal
__doc__ = _("""
Set a user's password
@@ -46,12 +47,13 @@ class passwd(Command):
__doc__ = _("Set a user's password.")
takes_args = (
Str('principal',
Str('principal', validate_principal,
cli_name='user',
label=_('User name'),
primary_key=True,
autofill=True,
create_default=lambda **kw: util.get_current_principal(),
normalizer=lambda value: normalize_principal(value),
),
Password('password',
label=_('Password'),
@@ -75,13 +77,6 @@ class passwd(Command):
"""
ldap = self.api.Backend.ldap2
if principal.find('@') != -1:
principal_parts = principal.split('@')
if len(principal_parts) > 2:
raise errors.MalformedUserPrincipal(principal=principal)
else:
principal = '%s@%s' % (principal, self.api.env.realm)
(dn, entry_attrs) = ldap.find_entry_by_attr(
'krbprincipalname', principal, 'posixaccount', [''],
",".join([api.env.container_user, api.env.basedn])

View File

@@ -84,6 +84,48 @@ def convert_nsaccountlock(entry_attrs):
nsaccountlock = Bool('temp')
entry_attrs['nsaccountlock'] = nsaccountlock.convert(entry_attrs['nsaccountlock'][0])
def split_principal(principal):
"""
Split the principal into its components and do some basic validation.
Automatically append our realm if it wasn't provided.
"""
realm = None
parts = principal.split('@')
user = parts[0].lower()
if len(parts) > 2:
raise errors.MalformedUserPrincipal(
principal=principal
)
if len(parts) == 2:
realm = parts[1].upper()
# At some point we'll support multiple realms
if realm != api.env.realm:
raise errors.RealmMismatch()
else:
realm = api.env.realm
return (user, realm)
def validate_principal(ugettext, principal):
"""
All the real work is done in split_principal.
"""
(user, realm) = split_principal(principal)
return None
def normalize_principal(principal):
"""
Ensure that the name in the principal is lower-case. The realm is
upper-case by convention but it isn't required.
The principal is validated at this point.
"""
(user, realm) = split_principal(principal)
return unicode('%s@%s' % (user, realm))
class user(LDAPObject):
"""
User object.
@@ -169,12 +211,13 @@ class user(LDAPObject):
label=_('Login shell'),
default=u'/bin/sh',
),
Str('krbprincipalname?',
Str('krbprincipalname?', validate_principal,
cli_name='principal',
label=_('Kerberos principal'),
default_from=lambda uid: '%s@%s' % (uid, api.env.realm),
default_from=lambda uid: '%s@%s' % (uid.lower(), api.env.realm),
autofill=True,
flags=['no_update'],
normalizer=lambda value: normalize_principal(value),
),
Str('mail*',
cli_name='email',

View File

@@ -42,9 +42,9 @@ class test_hbactest(XMLRPC_test):
test_user = u'hbacrule_test_user'
test_group = u'hbacrule_test_group'
test_host = u'hbacrule._test_host'
test_host = u'hbacrule.test-host'
test_hostgroup = u'hbacrule_test_hostgroup'
test_sourcehost = u'hbacrule._test_src_host'
test_sourcehost = u'hbacrule.test-src-host'
test_sourcehostgroup = u'hbacrule_test_src_hostgroup'
test_service = u'ssh'

View File

@@ -466,7 +466,6 @@ class test_user(Declarative):
),
dict(
desc='Create %r' % user1,
command=(
@@ -704,4 +703,65 @@ class test_user(Declarative):
),
dict(
desc='Create user %r with upper-case principal' % user1,
command=(
'user_add', [user1], dict(givenname=u'Test', sn=u'User1',
krbprincipalname=user1.upper())
),
expected=dict(
value=user1,
summary=u'Added user "tuser1"',
result=dict(
gecos=[u'Test User1'],
givenname=[u'Test'],
homedirectory=[u'/home/tuser1'],
krbprincipalname=[u'tuser1@' + api.env.realm],
loginshell=[u'/bin/sh'],
objectclass=objectclasses.user,
sn=[u'User1'],
uid=[user1],
uidnumber=[fuzzy_digits],
gidnumber=[fuzzy_digits],
displayname=[u'Test User1'],
cn=[u'Test User1'],
initials=[u'TU'],
ipauniqueid=[fuzzy_uuid],
krbpwdpolicyreference=lambda x: [DN(i) for i in x] == \
[DN(('cn','global_policy'),('cn',api.env.realm),
('cn','kerberos'),api.env.basedn)],
mepmanagedentry=lambda x: [DN(i) for i in x] == \
[DN(('cn',user1),('cn','groups'),('cn','accounts'),
api.env.basedn)],
memberof_group=[u'ipausers'],
has_keytab=False,
has_password=False,
dn=lambda x: DN(x) == \
DN(('uid','tuser1'),('cn','users'),('cn','accounts'),
api.env.basedn),
),
),
),
dict(
desc='Create user %r with bad realm in principal' % user1,
command=(
'user_add', [user1], dict(givenname=u'Test', sn=u'User1',
krbprincipalname='%s@NOTFOUND.ORG' % user1)
),
expected=errors.RealmMismatch()
),
dict(
desc='Create user %r with malformed principal' % user1,
command=(
'user_add', [user1], dict(givenname=u'Test', sn=u'User1',
krbprincipalname='%s@BAD@NOTFOUND.ORG' % user1)
),
expected=errors.MalformedUserPrincipal(principal='%s@BAD@NOTFOUND.ORG' % user1),
),
]