# -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 by Jan Dittberner. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. # # Version: $Id$ from gnuviechadmin.exceptions import * from gnuviechadmin.util import passwordutils, getenttools from settings import config from BackendTo import * from BackendEntity import * from BackendEntityHandler import * import os class SysuserEntity(BackendEntity): """Entity class for system users.""" def __init__(self, delegate, verbose = False, **kwargs): BackendEntity.__init__(self, delegate, verbose) for (key, value) in kwargs.items(): self.__setattr__(key, value) if not self.delegateto.username: self.delegateto.username = self._get_next_sysusername() if not self.delegateto.usertype: self.delegateto.usertype = self._get_default_sysusertype() if not self.delegateto.home: self.delegateto.home = self._get_home(self.delegateto.username) if not self.delegateto.shell: self.delegateto.shell = self._get_default_shell() (self.delegateto.clearpass, self.delegateto.md5pass) = \ passwordutils.get_pw_tuple(self.delegateto.clearpass) if not self.delegateto.sysuid: self.delegateto.sysuid = self._get_next_sysuid() self.validate() def _get_next_sysusername(self): prefix = config.get('sysuser', 'nameprefix') self.logger.debug("looking for next user with prefix %s" % (prefix)) usernames = [user.username for user in \ getenttools.find_user_by_prefix(prefix)] if usernames: maxid = max([int(username[len(prefix):]) \ for username in usernames]) maxid += 2 for number in range(1, maxid): username = "%s%02d" % (prefix, number) if not username in usernames: return username else: return "%s%02d" % (prefix, 1) def _get_default_sysusertype(self): return 1 def _get_home(self, sysusername): """Gets a valid home directory for the given user name.""" return os.path.join(config.get('sysuser', 'homedirbase'), sysusername) def _get_default_shell(self): return False def _get_shell_binary(self): if self.delegateto.shell: return config.get('sysuser', 'shellyes') return config.get('sysuser', 'shellno') def _get_next_sysuid(self): return getenttools.get_next_uid(int(config.get('sysuser', 'minuid')), int(config.get('sysuser', 'maxuid'))) def _populate_home(self): templatedir = get_template_dir(config.get('sysuser', 'hometemplate')) olddir = os.getcwd() os.chdir(templatedir) cmd1 = 'find . -depth \! -regex ".*\.svn.*" \! -name "*~" -print0' cmd2 = 'cpio --pass-through --owner=%(username)s.%(group)s --null ' + \ '--make-directories %(home)s' % { 'username': self.delegateto.username, 'group': config.get('sysuser', 'defaultgroup'), 'home': self.delegateto.home} self.supipe((cmd1, cmd2)) os.chdir(olddir) def _mail_sysuser(self): template = get_template(config.get('common', 'mailtemplates'), config.get('sysuser', 'create.mail')) text = template.substitute({ 'uid': self.delegateto.sysuid, 'firstname': self.delegateto.client.firstname, 'lastname': self.delegateto.client.lastname, 'email': self.delegateto.client.email, 'username': self.delegateto.username, 'password': self.delegateto.clearpass, 'home': self.delegateto.home, 'shell': self._get_shell_binary()}) template = get_template_string(config.get('sysuser', 'create_subject')) subject = template.substitute({ 'username': self.delegateto.username}) self.send_mail(subject, text) def create_hook(self, session): gecos = config.get('sysuser', 'gecos') % (self.delegateto.username) cmdline = 'adduser --home "%(home)s" --shell "%(shell)s" ' + \ '--no-create-home --uid %(sysuid)d --ingroup "%(group)s" ' + \ '--disabled-password --gecos "%(gecos)s" %(username)s' % { 'home': self.delegateto.home, 'shell': self._get_shell_binary(), 'sysuid': self.delegateto.sysuid, 'group': config.get('sysuser', 'defaultgroup'), 'gecos': gecos, 'username': self.delegateto.username} self.sucommand(cmdline) cmdline = 'chpasswd --encrypted' inline = '%(username)s:%(md5pass)s' % { 'username': self.delegateto.username, 'md5pass': self.delegateto.md5pass} self.sucommand(cmdline, inline) self._populate_home() self._mail_sysuser() def delete_hook(self, session): if self.delegateto.domains: raise CannotDeleteError( self.delegateto, "it still has the following domains assigned: %s" % ( ", ".join([domain.name for domain in \ self.delegateto.domains]))) backupdir = os.path.join(config.get('common', 'backupdir'), config.get('sysuser', 'homebackupdir')) if not os.path.isdir(backupdir): cmdline = 'mkdir -p "%(backupdir)s"' % { 'backupdir': backupdir} status = self.sucommand(cmdline) if status != 0: raise Exception("could not create backup directory") cmdline = 'deluser --remove-home --backup --backup-to ' + \ ' "%(backupdir)s" %(username)s' % { 'backupdir': backupdir, 'username': self.delegateto.username} self.sucommand(cmdline) class SysuserHandler(BackendEntityHandler): """BackendEntityHandler for Sysuser entities.""" def __init__(self, verbose = False): BackendEntityHandler.__init__(self, SysuserEntity, Sysuser, verbose)