Change user and group validators to match shadow-utils

This sets the regex to [a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,30}[a-zA-Z0-9_.$-]?

Also change the validators to return True/False

450613, 457124
This commit is contained in:
Rob Crittenden
2008-08-07 11:21:33 -04:00
parent fbc74a0cb4
commit 110f60da8e
12 changed files with 171 additions and 79 deletions
+7 -4
View File
@@ -27,6 +27,7 @@ try:
import ipa.ipautil as ipautil import ipa.ipautil as ipautil
import ipa.config import ipa.config
import ipa.ipaerror import ipa.ipaerror
import ipa.ipaadminutil as ipaadminutil
import xmlrpclib import xmlrpclib
import kerberos import kerberos
@@ -82,18 +83,20 @@ def main():
usage() usage()
if (len(args) != 2): if (len(args) != 2):
cn = ipautil.user_input("Group name", allow_empty = False) cn = ipautil.user_input_name("Group name")
else: else:
cn = args[1] cn = args[1]
if (ipavalidate.String(cn, notEmpty=True)): try:
print "Please enter a value" ipaadminutil.check_name(cn)
except ValueError, e:
print "Group name " + str(e)
return 1 return 1
if not options.desc: if not options.desc:
desc = ipautil.user_input("Description", allow_empty = False) desc = ipautil.user_input("Description", allow_empty = False)
else: else:
desc = options.desc desc = options.desc
if (ipavalidate.String(desc, notEmpty=True)): if (not ipavalidate.String(desc, notEmpty=True)):
print "Please enter a value" print "Please enter a value"
return 1 return 1
-1
View File
@@ -23,7 +23,6 @@ try:
import ipa import ipa
import ipa.user import ipa.user
import ipa.ipaclient as ipaclient import ipa.ipaclient as ipaclient
import ipa.ipavalidate as ipavalidate
import ipa.ipautil as ipautil import ipa.ipautil as ipautil
import ipa.config import ipa.config
+9 -6
View File
@@ -26,6 +26,7 @@ try:
import ipa.ipavalidate as ipavalidate import ipa.ipavalidate as ipavalidate
import ipa.ipautil as ipautil import ipa.ipautil as ipautil
import ipa.config import ipa.config
import ipa.ipaadminutil as ipaadminutil
import xmlrpclib import xmlrpclib
import kerberos import kerberos
@@ -118,7 +119,7 @@ def main():
givenname = ipautil.user_input("First name", allow_empty = False) givenname = ipautil.user_input("First name", allow_empty = False)
else: else:
givenname = options.gn givenname = options.gn
if (ipavalidate.String(givenname, notEmpty=True)): if (not ipavalidate.String(givenname, notEmpty=True)):
print "Please enter a value" print "Please enter a value"
return 1 return 1
@@ -126,16 +127,18 @@ def main():
lastname = ipautil.user_input("Last name", allow_empty = False) lastname = ipautil.user_input("Last name", allow_empty = False)
else: else:
lastname = options.sn lastname = options.sn
if (ipavalidate.String(lastname, notEmpty=True)): if (not ipavalidate.String(lastname, notEmpty=True)):
print "Please enter a value" print "Please enter a value"
return 1 return 1
if (len(args) != 2): if (len(args) != 2):
username = ipautil.user_input_plain("Login name", allow_empty = False, allow_spaces = False) username = ipautil.user_input_name("Login name")
else: else:
username = args[1] username = args[1]
if (ipavalidate.Plain(username, notEmpty=True, allowSpaces=False)): try:
print "Username is required and may only include letters and numbers" ipaadminutil.check_name(username)
except ValueError, e:
print "Login name " + str(e)
return 1 return 1
if options.password_prompt: if options.password_prompt:
@@ -155,7 +158,7 @@ def main():
if options.mail: if options.mail:
mail = options.mail mail = options.mail
if (ipavalidate.Email(mail)): if (not ipavalidate.Email(mail)):
print "The email provided seem not a valid email." print "The email provided seem not a valid email."
return 1 return 1
+3 -3
View File
@@ -143,7 +143,7 @@ def main():
givenname = ipautil.user_input("First name", user.getValue('givenname'), allow_empty = False) givenname = ipautil.user_input("First name", user.getValue('givenname'), allow_empty = False)
else: else:
givenname = options.gn givenname = options.gn
if (ipavalidate.String(givenname, notEmpty=True)): if (not ipavalidate.String(givenname, notEmpty=True)):
print "Please enter a value" print "Please enter a value"
return 1 return 1
@@ -151,7 +151,7 @@ def main():
lastname = ipautil.user_input("Last name", user.getValue('sn'), allow_empty = False) lastname = ipautil.user_input("Last name", user.getValue('sn'), allow_empty = False)
else: else:
lastname = options.sn lastname = options.sn
if (ipavalidate.String(lastname, notEmpty=True)): if (not ipavalidate.String(lastname, notEmpty=True)):
print "Please enter a value" print "Please enter a value"
return 1 return 1
@@ -159,7 +159,7 @@ def main():
mail = ipautil.user_input_email("E-mail address", user.getValue('mail'), allow_empty = True) mail = ipautil.user_input_email("E-mail address", user.getValue('mail'), allow_empty = True)
else: else:
mail = options.mail mail = options.mail
if (ipavalidate.Email(mail)): if (not ipavalidate.Email(mail)):
print "E-mail must include a user and domain name" print "E-mail must include a user and domain name"
return 1 return 1
+9
View File
@@ -22,6 +22,7 @@ import tempfile
import logging import logging
import subprocess import subprocess
import os import os
import ipa.ipavalidate as ipavalidate
def select_user(counter, users): def select_user(counter, users):
"""counter is the number of User objects in users """counter is the number of User objects in users
@@ -82,3 +83,11 @@ def select_group(counter, groups):
print "Please enter a number between 1 and %s" % counter print "Please enter a number between 1 and %s" % counter
return groupindex return groupindex
def check_name(name):
"""Helper to ensure that a user or group name is legal"""
if (not ipavalidate.GoodName(name, notEmpty=True)):
raise ValueError("may only include letters, numbers, _, -, . and $")
return
+12 -3
View File
@@ -30,6 +30,7 @@ import stat
import shutil import shutil
from ipa import ipavalidate from ipa import ipavalidate
from ipa import ipaadminutil
from types import * from types import *
import re import re
@@ -529,13 +530,13 @@ def user_input_email(prompt, default = None, allow_empty = False):
ret = user_input(prompt, default, allow_empty) ret = user_input(prompt, default, allow_empty)
if allow_empty and ret.lower() == "none": if allow_empty and ret.lower() == "none":
return "" return ""
if not ipavalidate.Email(ret, not allow_empty): if ipavalidate.Email(ret, not allow_empty):
return ret.strip() return ret.strip()
def user_input_plain(prompt, default = None, allow_empty = True, allow_spaces = True): def user_input_plain(prompt, default = None, allow_empty = True, allow_spaces = True):
while True: while True:
ret = user_input(prompt, default, allow_empty) ret = user_input(prompt, default, allow_empty)
if not ipavalidate.Plain(ret, not allow_empty, allow_spaces): if ipavalidate.Plain(ret, not allow_empty, allow_spaces):
return ret return ret
def user_input_path(prompt, default = None, allow_empty = True): def user_input_path(prompt, default = None, allow_empty = True):
@@ -545,9 +546,17 @@ def user_input_path(prompt, default = None, allow_empty = True):
ret = user_input(prompt, default, allow_empty) ret = user_input(prompt, default, allow_empty)
if allow_empty and ret.lower() == "none": if allow_empty and ret.lower() == "none":
return "" return ""
if not ipavalidate.Path(ret, not allow_empty): if ipavalidate.Path(ret, not allow_empty):
return ret return ret
def user_input_name(prompt, default = None):
while True:
ret = user_input(prompt, default, False)
try:
ipaadminutil.check_name(ret)
return ret
except ValueError, e:
print prompt + " " + str(e)
class AttributeValueCompleter: class AttributeValueCompleter:
''' '''
+52 -24
View File
@@ -21,8 +21,8 @@ import re
def Email(mail, notEmpty=True): def Email(mail, notEmpty=True):
"""Do some basic validation of an e-mail address. """Do some basic validation of an e-mail address.
Return 0 if ok Return True if ok
Return 1 if not Return False if not
If notEmpty is True the this will return an error if the field If notEmpty is True the this will return an error if the field
is "" or None. is "" or None.
@@ -32,61 +32,61 @@ def Email(mail, notEmpty=True):
if not mail or mail is None: if not mail or mail is None:
if notEmpty is True: if notEmpty is True:
return 1 return False
else: else:
return 0 return True
mail = mail.strip() mail = mail.strip()
s = mail.split('@', 1) s = mail.split('@', 1)
try: try:
username, domain=s username, domain=s
except ValueError: except ValueError:
return 1 return False
if not usernameRE.search(username): if not usernameRE.search(username):
return 1 return False
if not domainRE.search(domain): if not domainRE.search(domain):
return 1 return False
return 0 return True
def Plain(text, notEmpty=False, allowSpaces=True): def Plain(text, notEmpty=False, allowSpaces=True):
"""Do some basic validation of a plain text field """Do some basic validation of a plain text field
Return 0 if ok Return True if ok
Return 1 if not Return False if not
If notEmpty is True the this will return an error if the field If notEmpty is True the this will return an error if the field
is "" or None. is "" or None.
""" """
if (text is None) or (not text.strip()): if (text is None) or (not text.strip()):
if notEmpty is True: if notEmpty is True:
return 1 return False
else: else:
return 0 return True
if allowSpaces: if allowSpaces:
textRE = re.compile(r"^[a-zA-Z_\-0-9\'\ ]*$") textRE = re.compile(r"^[a-zA-Z_\-0-9\'\ ]*$")
else: else:
textRE = re.compile(r"^[a-zA-Z_\-0-9\']*$") textRE = re.compile(r"^[a-zA-Z_\-0-9\']*$")
if not textRE.search(text): if not textRE.search(text):
return 1 return False
return 0 return True
def String(text, notEmpty=False): def String(text, notEmpty=False):
"""A string type. This is much looser in what it allows than plain""" """A string type. This is much looser in what it allows than plain"""
if text is None or not text.strip(): if text is None or not text.strip():
if notEmpty is True: if notEmpty is True:
return 1 return False
else: else:
return 0 return True
return 0 return True
def Path(text, notEmpty=False): def Path(text, notEmpty=False):
"""Do some basic validation of a path """Do some basic validation of a path
Return 0 if ok Return True if ok
Return 1 if not Return False if not
If notEmpty is True the this will return an error if the field If notEmpty is True the this will return an error if the field
is "" or None. is "" or None.
@@ -94,16 +94,44 @@ def Path(text, notEmpty=False):
textRE = re.compile(r"^[a-zA-Z_\-0-9\\ \.\/\\:]*$") textRE = re.compile(r"^[a-zA-Z_\-0-9\\ \.\/\\:]*$")
if not text and notEmpty is True: if not text and notEmpty is True:
return 1 return False
if text is None: if text is None:
if notEmpty is True: if notEmpty is True:
return 1 return False
else: else:
return 0 return True
if not textRE.search(text): if not textRE.search(text):
return 1 return False
return 0 return True
def GoodName(text, notEmpty=False):
"""From shadow-utils:
User/group names must match gnu e-regex:
[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,30}[a-zA-Z0-9_.$-]?
as a non-POSIX, extension, allow "$" as the last char for
sake of Samba 3.x "add machine script"
Return True if ok
Return False if not
"""
textRE = re.compile(r"^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,30}[a-zA-Z0-9_.$-]?$")
if not text and notEmpty is True:
return False
if text is None:
if notEmpty is True:
return False
else:
return True
m = textRE.match(text)
if not m or text != m.group(0):
return False
return True
+1 -1
View File
@@ -347,7 +347,7 @@ def validate_nastype(nastype, variable_name=None):
return True return True
def validate_desc(desc, variable_name=None): def validate_desc(desc, variable_name=None):
if ipavalidate.Plain(desc) != 0: if not ipavalidate.Plain(desc):
print valid_desc_msg print valid_desc_msg
return False return False
return True return True
+46 -34
View File
@@ -32,54 +32,66 @@ class TestValidate(unittest.TestCase):
pass pass
def test_validEmail(self): def test_validEmail(self):
self.assertEqual(0, ipavalidate.Email("test@freeipa.org")) self.assertEqual(True, ipavalidate.Email("test@freeipa.org"))
self.assertEqual(0, ipavalidate.Email("", notEmpty=False)) self.assertEqual(True, ipavalidate.Email("", notEmpty=False))
def test_invalidEmail(self): def test_invalidEmail(self):
self.assertEqual(1, ipavalidate.Email("test")) self.assertEqual(False, ipavalidate.Email("test"))
self.assertEqual(1, ipavalidate.Email("test@freeipa")) self.assertEqual(False, ipavalidate.Email("test@freeipa"))
self.assertEqual(1, ipavalidate.Email("test@.com")) self.assertEqual(False, ipavalidate.Email("test@.com"))
self.assertEqual(1, ipavalidate.Email("")) self.assertEqual(False, ipavalidate.Email(""))
self.assertEqual(1, ipavalidate.Email(None)) self.assertEqual(False, ipavalidate.Email(None))
def test_validPlain(self): def test_validPlain(self):
self.assertEqual(0, ipavalidate.Plain("Joe User")) self.assertEqual(True, ipavalidate.Plain("Joe User"))
self.assertEqual(0, ipavalidate.Plain("Joe O'Malley")) self.assertEqual(True, ipavalidate.Plain("Joe O'Malley"))
self.assertEqual(0, ipavalidate.Plain("", notEmpty=False)) self.assertEqual(True, ipavalidate.Plain("", notEmpty=False))
self.assertEqual(0, ipavalidate.Plain(None, notEmpty=False)) self.assertEqual(True, ipavalidate.Plain(None, notEmpty=False))
self.assertEqual(0, ipavalidate.Plain("JoeUser", allowSpaces=False)) self.assertEqual(True, ipavalidate.Plain("JoeUser", allowSpaces=False))
self.assertEqual(0, ipavalidate.Plain("JoeUser", allowSpaces=True)) self.assertEqual(True, ipavalidate.Plain("JoeUser", allowSpaces=True))
def test_invalidPlain(self): def test_invalidPlain(self):
self.assertEqual(1, ipavalidate.Plain("Joe (User)")) self.assertEqual(False, ipavalidate.Plain("Joe (User)"))
self.assertEqual(1, ipavalidate.Plain("Joe C. User")) self.assertEqual(False, ipavalidate.Plain("Joe C. User"))
self.assertEqual(1, ipavalidate.Plain("", notEmpty=True)) self.assertEqual(False, ipavalidate.Plain("", notEmpty=True))
self.assertEqual(1, ipavalidate.Plain(None, notEmpty=True)) self.assertEqual(False, ipavalidate.Plain(None, notEmpty=True))
self.assertEqual(1, ipavalidate.Plain("Joe User", allowSpaces=False)) self.assertEqual(False, ipavalidate.Plain("Joe User", allowSpaces=False))
self.assertEqual(False, ipavalidate.Plain("Joe C. User"))
def test_validString(self): def test_validString(self):
self.assertEqual(0, ipavalidate.String("Joe User")) self.assertEqual(True, ipavalidate.String("Joe User"))
self.assertEqual(0, ipavalidate.String("Joe O'Malley")) self.assertEqual(True, ipavalidate.String("Joe O'Malley"))
self.assertEqual(1, ipavalidate.Plain("Joe C. User")) self.assertEqual(True, ipavalidate.String("", notEmpty=False))
self.assertEqual(0, ipavalidate.String("", notEmpty=False)) self.assertEqual(True, ipavalidate.String(None, notEmpty=False))
self.assertEqual(0, ipavalidate.String(None, notEmpty=False)) self.assertEqual(True, ipavalidate.String("Joe C. User"))
def test_invalidString(self): def test_invalidString(self):
self.assertEqual(1, ipavalidate.String("", notEmpty=True)) self.assertEqual(False, ipavalidate.String("", notEmpty=True))
self.assertEqual(1, ipavalidate.String(None, notEmpty=True)) self.assertEqual(False, ipavalidate.String(None, notEmpty=True))
def test_validPath(self): def test_validPath(self):
self.assertEqual(0, ipavalidate.Path("/")) self.assertEqual(True, ipavalidate.Path("/"))
self.assertEqual(0, ipavalidate.Path("/home/user")) self.assertEqual(True, ipavalidate.Path("/home/user"))
self.assertEqual(0, ipavalidate.Path("../home/user")) self.assertEqual(True, ipavalidate.Path("../home/user"))
self.assertEqual(0, ipavalidate.Path("", notEmpty=False)) self.assertEqual(True, ipavalidate.Path("", notEmpty=False))
self.assertEqual(0, ipavalidate.Path(None, notEmpty=False)) self.assertEqual(True, ipavalidate.Path(None, notEmpty=False))
def test_invalidPath(self): def test_invalidPath(self):
self.assertEqual(1, ipavalidate.Path("(foo)")) self.assertEqual(False, ipavalidate.Path("(foo)"))
self.assertEqual(1, ipavalidate.Path("", notEmpty=True)) self.assertEqual(False, ipavalidate.Path("", notEmpty=True))
self.assertEqual(1, ipavalidate.Path(None, notEmpty=True)) self.assertEqual(False, ipavalidate.Path(None, notEmpty=True))
def test_validName(self):
self.assertEqual(True, ipavalidate.GoodName("foo"))
self.assertEqual(True, ipavalidate.GoodName("1foo"))
self.assertEqual(True, ipavalidate.GoodName("foo.bar"))
self.assertEqual(True, ipavalidate.GoodName("foo.bar$"))
def test_invalidName(self):
self.assertEqual(False, ipavalidate.GoodName("foo bar"))
self.assertEqual(False, ipavalidate.GoodName("foo%bar"))
self.assertEqual(False, ipavalidate.GoodName("*foo"))
self.assertEqual(False, ipavalidate.GoodName("$foo.bar$"))
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
+2 -2
View File
@@ -36,7 +36,7 @@ class GroupFields(object):
dn_to_info_json = widgets.HiddenField(name="dn_to_info_json") dn_to_info_json = widgets.HiddenField(name="dn_to_info_json")
class GroupNewValidator(validators.Schema): class GroupNewValidator(validators.Schema):
cn = validators.String(not_empty=True) cn = GoodName(not_empty=True)
description = validators.String(not_empty=False) description = validators.String(not_empty=False)
@@ -59,7 +59,7 @@ class GroupNewForm(widgets.Form):
class GroupEditValidator(validators.Schema): class GroupEditValidator(validators.Schema):
cn = validators.String(not_empty=False) cn = GoodName(not_empty=False)
gidnumber = validators.Int(not_empty=False) gidnumber = validators.Int(not_empty=False)
description = validators.String(not_empty=False) description = validators.String(not_empty=False)
+2 -1
View File
@@ -86,7 +86,7 @@ class UserFields(object):
custom_fields = [] custom_fields = []
class UserNewValidator(validators.Schema): class UserNewValidator(validators.Schema):
uid = validators.PlainText(not_empty=True) uid = GoodName(not_empty=True)
krbprincipalkey = validators.String(not_empty=False) krbprincipalkey = validators.String(not_empty=False)
krbprincipalkey_confirm = validators.String(not_empty=False) krbprincipalkey_confirm = validators.String(not_empty=False)
givenname = validators.String(not_empty=True) givenname = validators.String(not_empty=True)
@@ -129,6 +129,7 @@ class UserNewForm(widgets.Form):
super(UserNewForm,self).update_params(params) super(UserNewForm,self).update_params(params)
class UserEditValidator(validators.Schema): class UserEditValidator(validators.Schema):
uid = GoodName(not_empty=False)
krbprincipalkey = validators.String(not_empty=False) krbprincipalkey = validators.String(not_empty=False)
krbprincipalkey_confirm = validators.String(not_empty=False) krbprincipalkey_confirm = validators.String(not_empty=False)
givenname = validators.String(not_empty=True) givenname = validators.String(not_empty=True)
@@ -63,3 +63,31 @@ class UniqueList(FancyValidator):
if orig > check: if orig > check:
raise Invalid(self.message('notunique', state), raise Invalid(self.message('notunique', state),
value, state) value, state)
class GoodName(Regex):
"""
Test that the field contains only letters, numbers, underscore,
dash, hyphen and $.
Examples::
>>> GoodName.to_python('_this9_')
'_this9_'
>>> GoodName.from_python(' this ')
' this '
>>> GoodName(accept_python=False).from_python(' this ')
Traceback (most recent call last):
...
Invalid: Enter only letters, numbers, _ (underscore), - (dash) or $')
>>> GoodName(strip=True).to_python(' this ')
'this'
>>> GoodName(strip=True).from_python(' this ')
'this'
"""
regex = r"^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,30}[a-zA-Z0-9_.$-]?$"
messages = {
'invalid': _('Enter only letters, numbers, _ (underscore), - (dash) or
$'),
}