From 1de06aa63ecb0261e7f692141ba6aea3315eb76b Mon Sep 17 00:00:00 2001 From: Ryan Harper Date: Fri, 23 Oct 2015 15:21:13 -0500 Subject: [PATCH] Implement username field protection man 8 useradd says: It is usually recommended to only use usernames that begin with a lower case letter or an underscore, followed by lower case letters, digits, underscores, or dashes. They can end with a dollar sign. In regular expression terms: [a-z_][a-z0-9_-]*[$]? On Debian, the only constraints are that usernames must neither start with a dash ('-') nor plus ('+') nor tilde ('~') nor contain a colon (':'), a comma (','), or a whitespace (space: ' ', end of line: '\n', tabulation: '\t', etc.). Note that using a slash ('/') may break the default algorithm for the definition of the user's home directory. Usernames may only be up to 32 characters long. In this patch we implement most of this. Subset of the regular expression suggested above is used to limit input into the username field. We've not yet determined how to provide a fixed width widget so at this time, user can input more than 32 characters, but upon selectin done, we raise and error and reset the state. Signed-off-by: Ryan Harper --- subiquity/ui/interactive.py | 21 +++++++++++++++++++++ subiquity/ui/views/identity.py | 12 ++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/subiquity/ui/interactive.py b/subiquity/ui/interactive.py index 2df33a50..33478323 100644 --- a/subiquity/ui/interactive.py +++ b/subiquity/ui/interactive.py @@ -18,6 +18,7 @@ from urwid import (Edit, IntEdit, RadioButton, WidgetWrap) import logging +import re log = logging.getLogger("subiquity.ui.input") @@ -59,6 +60,26 @@ class PasswordEditor(StringEditor): super().__init__(caption, mask=mask) +class UsernameEditor(StringEditor): + """ Username input prompt with input rules + """ + + def keypress(self, size, key): + ''' restrict what chars we allow for username ''' + + userlen = len(self.value) + if userlen == 0: + username = r'[a-z_]' + else: + username = r'[a-z0-9_-]' + + # don't allow non username chars + if re.match(username, key) is None: + return False + + return super().keypress(size, key) + + class IntegerEditor(WidgetWrap): """ IntEdit input class """ diff --git a/subiquity/ui/views/identity.py b/subiquity/ui/views/identity.py index 5b9c729c..c2db83d7 100644 --- a/subiquity/ui/views/identity.py +++ b/subiquity/ui/views/identity.py @@ -21,7 +21,9 @@ Welcome provides user with language selection import logging from urwid import (Pile, Columns, Text, ListBox) from subiquity.ui.buttons import done_btn, cancel_btn -from subiquity.ui.interactive import StringEditor, PasswordEditor +from subiquity.ui.interactive import (PasswordEditor, + StringEditor, + UsernameEditor) from subiquity.ui.utils import Padding, Color from subiquity.view import ViewPolicy @@ -34,7 +36,7 @@ class IdentityView(ViewPolicy): self.signal = signal self.items = [] self.realname = StringEditor(caption="") - self.username = StringEditor(caption="") + self.username = UsernameEditor(caption="") self.password = PasswordEditor(caption="") self.error = Text("", align="center") self.confirm_password = PasswordEditor(caption="") @@ -105,6 +107,12 @@ class IdentityView(ViewPolicy): self.password.value = "" self.confirm_password.value = "" return + + if len(self.username.value) > 32: + self.error.set_text("Username too long, must be < 32") + self.username.value = "" + return + cpassword = self.model.encrypt_password(self.password.value) log.debug("*crypted* User input: {} {} {}".format( self.username.value, cpassword, cpassword))