From 3a69958165c459d17538bb02ea60666dd8b19860 Mon Sep 17 00:00:00 2001 From: James Valleroy Date: Thu, 14 Jul 2016 07:05:47 -0400 Subject: [PATCH] users: Avoid username conflicts with system users When creating or renaming a user, check if the new username is in use by any system user. --- plinth/modules/first_boot/forms.py | 13 +++++++++++++ plinth/modules/users/forms.py | 27 +++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/plinth/modules/first_boot/forms.py b/plinth/modules/first_boot/forms.py index 759312813..77f1e582c 100644 --- a/plinth/modules/first_boot/forms.py +++ b/plinth/modules/first_boot/forms.py @@ -22,6 +22,7 @@ Forms for first boot module. import json import logging import requests +import subprocess from django import forms from django.contrib import auth @@ -46,6 +47,18 @@ class State1Form(auth.forms.UserCreationForm): self.request = kwargs.pop('request') super().__init__(*args, **kwargs) + def clean(self): + """Check for username collisions with system users.""" + username = self.cleaned_data['username'] + try: + subprocess.run(['getent', 'passwd', username], check=True) + # Exit code 0 means that the username is already in use. + raise ValidationError(_('Username is reserved')) + except subprocess.CalledProcessError: + pass + + return super().clean() + def save(self, commit=True): """Create and log the user in.""" user = super().save(commit=commit) diff --git a/plinth/modules/users/forms.py b/plinth/modules/users/forms.py index 0ebf27ebd..12d637787 100644 --- a/plinth/modules/users/forms.py +++ b/plinth/modules/users/forms.py @@ -15,10 +15,13 @@ # along with this program. If not, see . # +import subprocess + from django import forms from django.contrib import messages from django.contrib.auth.models import User, Group from django.contrib.auth.forms import UserCreationForm, SetPasswordForm +from django.core.exceptions import ValidationError from django.utils.translation import ugettext as _, ugettext_lazy from plinth import actions @@ -55,6 +58,18 @@ class CreateUserForm(UserCreationForm): self.request = request super(CreateUserForm, self).__init__(*args, **kwargs) + def clean(self): + """Check for username collisions with system users.""" + username = self.cleaned_data['username'] + try: + subprocess.run(['getent', 'passwd', username], check=True) + # Exit code 0 means that the username is already in use. + raise ValidationError(_('Username is reserved')) + except subprocess.CalledProcessError: + pass + + return super().clean() + def save(self, commit=True): """Save the user model and create LDAP user if required.""" user = super(CreateUserForm, self).save(commit) @@ -116,6 +131,18 @@ class UserUpdateForm(forms.ModelForm): self.username = username super(UserUpdateForm, self).__init__(*args, **kwargs) + def clean(self): + """Check for username collisions with system users.""" + username = self.cleaned_data['username'] + try: + subprocess.run(['getent', 'passwd', username], check=True) + # Exit code 0 means that the username is already in use. + raise ValidationError(_('Username is reserved')) + except subprocess.CalledProcessError: + pass + + return super().clean() + def save(self, commit=True): """Update LDAP user name and groups after saving user model.""" user = super(UserUpdateForm, self).save(commit)