do not let the user choose a reserved username

using the same logic as d-i
This commit is contained in:
Michael Hudson-Doyle 2018-07-17 10:32:48 +12:00
parent 0004174bd5
commit 67ebf6ad35
3 changed files with 138 additions and 4 deletions

107
reserved-usernames Normal file
View File

@ -0,0 +1,107 @@
# Static users from base-passwd/passwd.master (3.5.11).
root
daemon
bin
sys
sync
games
man
lp
mail
news
uucp
proxy
www-data
backup
list
irc
gnats
nobody
# Other static groups from base-passwd/group.master (3.5.11).
adm
tty
disk
kmem
dialout
fax
voice
cdrom
floppy
tape
sudo
audio
dip
operator
src
shadow
utmp
video
sasl
plugdev
staff
users
nogroup
# Reserved usernames listed in base-passwd/README (3.5.11).
netplan
ftn
mysql
tac-plus
alias
qmail
qmaild
qmails
qmailr
qmailq
qmaill
qmailp
asterisk
vpopmail
vchkpw
# Ubuntu creates the admin group and adds the first user to it in order to
# grant them sudo privileges.
admin
# Other miscellaneous system users/groups created by common packages. While
# it's useful to add things here that people might run into, it's not
# absolutely critical; the worst that will happen is that the installation
# will fail at some later point.
Debian-exim
bind
crontab
cupsys
dcc
dhcp
dictd
dovecot
fetchmail
firebird
ftp
fuse
gdm
haldaemon
hplilp
identd
jwhois
klog
lpadmin
maas
messagebus
mythtv
netdev
powerdev
radvd
saned
sbuild
scanner
slocate
ssh
sshd
ssl-cert
sslwrap
statd
syslog
telnetd
tftpd

View File

@ -57,9 +57,11 @@ parts:
echo "get passwd/user-default-groups" | \ echo "get passwd/user-default-groups" | \
debconf-communicate user-setup | \ debconf-communicate user-setup | \
cut -d ' ' -f 2- > users-and-groups cut -d ' ' -f 2- > users-and-groups
cp /usr/lib/user-setup/reserved-usernames .
stage-packages: [libc6] stage-packages: [libc6]
stage: stage:
- users-and-groups - users-and-groups
- reserved-usernames
kbdnames: kbdnames:
plugin: dump plugin: dump
build-packages: build-packages:

View File

@ -14,6 +14,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import logging import logging
import os
import re import re
from urwid import ( from urwid import (
@ -116,6 +117,10 @@ _ssh_import_data = {
class IdentityForm(Form): class IdentityForm(Form):
def __init__(self, reserved_usernames):
self.reserved_usernames = reserved_usernames
super().__init__()
realname = RealnameField(_("Your name:")) realname = RealnameField(_("Your name:"))
hostname = UsernameField( hostname = UsernameField(
_("Your server's name:"), _("Your server's name:"),
@ -151,15 +156,21 @@ class IdentityForm(Form):
return _("Hostname must match NAME_REGEX, i.e. [a-z_][a-z0-9_-]*") return _("Hostname must match NAME_REGEX, i.e. [a-z_][a-z0-9_-]*")
def validate_username(self): def validate_username(self):
if len(self.username.value) < 1: username = self.username.value
if len(username) < 1:
return _("Username missing") return _("Username missing")
if len(self.username.value) > USERNAME_MAXLEN: if len(username) > USERNAME_MAXLEN:
return _("Username too long, must be < ") + str(USERNAME_MAXLEN) return _("Username too long, must be < ") + str(USERNAME_MAXLEN)
if not re.match(r'[a-z_][a-z0-9_-]*', self.username.value): if not re.match(r'[a-z_][a-z0-9_-]*', username):
return _("Username must match NAME_REGEX, i.e. [a-z_][a-z0-9_-]*") return _("Username must match NAME_REGEX, i.e. [a-z_][a-z0-9_-]*")
if username in self.reserved_usernames:
return _(
'The username "{username}" is reserved for use by the system.'
).format(username=username)
def validate_password(self): def validate_password(self):
if len(self.password.value) < 1: if len(self.password.value) < 1:
return _("Password must be set") return _("Password must be set")
@ -293,7 +304,21 @@ class IdentityView(BaseView):
self.opts = opts self.opts = opts
self.items = [] self.items = []
self.form = IdentityForm() reserved_usernames_path = (
os.path.join(os.environ.get("SNAP", "."), "reserved-usernames"))
reserved_usernames = set()
if os.path.exists(reserved_usernames_path):
with open(reserved_usernames_path) as fp:
for line in fp:
line = line.strip()
if line.startswith('#') or not line:
continue
reserved_usernames.add(line)
else:
reserved_usernames.add('root')
self.form = IdentityForm(reserved_usernames)
connect_signal(self.form, 'submit', self.done) connect_signal(self.form, 'submit', self.done)
connect_signal(self.form.confirm_password.widget, 'change', connect_signal(self.form.confirm_password.widget, 'change',
self._check_password) self._check_password)