예제 #1
0
        def add_anonymous(self, homedir=None, realuser="******", **kwargs):
            """Add an anonymous user to the virtual users table.

             - (string) homedir:
                The anonymous user home directory.  If this is not
                specified the "realuser" home directory will be
                determined (if any) and used.

             - (string) realuser:
                specifies the system user to use for managing anonymous
                sessions.  On some UNIX systems "ftp" is available and
                usually used by end-user FTP servers but it can vary
                (e.g. "nobody").

             - (dict) **kwargs:
                the same keyword arguments expected by the original
                add_user method: "perm", "msg_login" and "msg_quit".
            """
            users = [entry.pw_name for entry in pwd.getpwall()]
            if not realuser in users:
                raise AuthorizerError('No such user "%s".' % realuser)
            if not homedir:
                homedir = pwd.getpwnam(realuser).pw_dir
                self._dynamic_home_users.append(realuser)
            DummyAuthorizer.add_anonymous(self, homedir, **kwargs)
            self._anon_user = realuser
예제 #2
0
        def __init__(self,
                     global_perm="elradfmw",
                     allowed_users=[],
                     rejected_users=[],
                     require_valid_shell=True,
                     anonymous_user=None,
                     msg_login="******",
                     msg_quit="Goodbye."):
            """Parameters:

             - (string) global_perm:
                a series of letters referencing the users permissions;
                defaults to "elradfmw" which means full read and write
                access for everybody (except anonymous).

             - (list) allowed_users:
                a list of users which are accepted for authenticating
                against the FTP server; defaults to [] (no restrictions).

             - (list) rejected_users:
                a list of users which are not accepted for authenticating
                against the FTP server; defaults to [] (no restrictions).

             - (bool) require_valid_shell:
                Deny access for those users which do not have a valid shell
                binary listed in /etc/shells.
                If /etc/shells cannot be found this is a no-op.
                Anonymous user is not subject to this option, and is free
                to not have a valid shell defined.
                Defaults to True (a valid shell is required for login).

             - (string) anonymous_user:
                specify it if you intend to provide anonymous access.
                The value expected is a string representing the system user
                to use for managing anonymous sessions;  defaults to None
                (anonymous access disabled).

             - (string) msg_login:
                the string sent when client logs in.

             - (string) msg_quit:
                the string sent when client quits.
            """
            BaseUnixAuthorizer.__init__(self, anonymous_user)
            self.global_perm = global_perm
            self.allowed_users = allowed_users
            self.rejected_users = rejected_users
            self.anonymous_user = anonymous_user
            self.require_valid_shell = require_valid_shell
            self.msg_login = msg_login
            self.msg_quit = msg_quit

            self._dummy_authorizer = DummyAuthorizer()
            self._dummy_authorizer._check_permissions('', global_perm)
            _Base.__init__(self)
            if require_valid_shell:
                for username in self.allowed_users:
                    if not self._has_valid_shell(username):
                        raise ValueError("user %s has not a valid shell" %
                                         username)
예제 #3
0
def main():
    authorizer = DummyAuthorizer()
    authorizer.add_user('user', '12345', '.', perm='elradfmw')
    authorizer.add_anonymous('.')
    handler = AntiFloodHandler
    handler.authorizer = authorizer
    ftpd = FTPServer(('', 21), handler)
    ftpd.serve_forever(timeout=1)
예제 #4
0
        def __init__(self,
                     global_perm="elradfmw",
                     allowed_users=[],
                     rejected_users=[],
                     anonymous_user=None,
                     anonymous_password=None,
                     msg_login="******",
                     msg_quit="Goodbye."):
            """Parameters:

             - (string) global_perm:
                a series of letters referencing the users permissions;
                defaults to "elradfmw" which means full read and write
                access for everybody (except anonymous).

             - (list) allowed_users:
                a list of users which are accepted for authenticating
                against the FTP server; defaults to [] (no restrictions).

             - (list) rejected_users:
                a list of users which are not accepted for authenticating
                against the FTP server; defaults to [] (no restrictions).

             - (string) anonymous_user:
                specify it if you intend to provide anonymous access.
                The value expected is a string representing the system user
                to use for managing anonymous sessions.
                As for IIS, it is recommended to use Guest account.
                The common practice is to first enable the Guest user, which
                is disabled by default and then assign an empty password.
                Defaults to None (anonymous access disabled).

             - (string) anonymous_password:
                the password of the user who has been chosen to manage the
                anonymous sessions.  Defaults to None (empty password).

             - (string) msg_login:
                the string sent when client logs in.

             - (string) msg_quit:
                the string sent when client quits.
            """
            self.global_perm = global_perm
            self.allowed_users = allowed_users
            self.rejected_users = rejected_users
            self.anonymous_user = anonymous_user
            self.anonymous_password = anonymous_password
            self.msg_login = msg_login
            self.msg_quit = msg_quit
            self._dummy_authorizer = DummyAuthorizer()
            self._dummy_authorizer._check_permissions('', global_perm)
            _Base.__init__(self)
            # actually try to impersonate the user
            if self.anonymous_user is not None:
                self.impersonate_user(self.anonymous_user,
                                      self.anonymous_password)
                self.terminate_impersonation()
예제 #5
0
        def __init__(self, global_perm="elradfmw",
                           allowed_users=[],
                           rejected_users=[],
                           require_valid_shell=True,
                           anonymous_user=None,
                           msg_login="******",
                           msg_quit="Goodbye."):
            """Parameters:

             - (string) global_perm:
                a series of letters referencing the users permissions;
                defaults to "elradfmw" which means full read and write
                access for everybody (except anonymous).

             - (list) allowed_users:
                a list of users which are accepted for authenticating
                against the FTP server; defaults to [] (no restrictions).

             - (list) rejected_users:
                a list of users which are not accepted for authenticating
                against the FTP server; defaults to [] (no restrictions).

             - (bool) require_valid_shell:
                Deny access for those users which do not have a valid shell
                binary listed in /etc/shells.
                If /etc/shells cannot be found this is a no-op.
                Anonymous user is not subject to this option, and is free
                to not have a valid shell defined.
                Defaults to True (a valid shell is required for login).

             - (string) anonymous_user:
                specify it if you intend to provide anonymous access.
                The value expected is a string representing the system user
                to use for managing anonymous sessions;  defaults to None
                (anonymous access disabled).

             - (string) msg_login:
                the string sent when client logs in.

             - (string) msg_quit:
                the string sent when client quits.
            """
            BaseUnixAuthorizer.__init__(self, anonymous_user)
            self.global_perm = global_perm
            self.allowed_users = allowed_users
            self.rejected_users = rejected_users
            self.anonymous_user = anonymous_user
            self.require_valid_shell = require_valid_shell
            self.msg_login = msg_login
            self.msg_quit = msg_quit

            self._dummy_authorizer = DummyAuthorizer()
            self._dummy_authorizer._check_permissions('', global_perm)
            _Base.__init__(self)
            if require_valid_shell:
                for username in self.allowed_users:
                    if not self._has_valid_shell(username):
                        raise ValueError("user %s has not a valid shell"
                                         % username)
예제 #6
0
        def __init__(self, global_perm="elradfmw",
                           allowed_users=[],
                           rejected_users=[],
                           anonymous_user=None,
                           anonymous_password=None,
                           msg_login="******",
                           msg_quit="Goodbye."):
            """Parameters:

             - (string) global_perm:
                a series of letters referencing the users permissions;
                defaults to "elradfmw" which means full read and write
                access for everybody (except anonymous).

             - (list) allowed_users:
                a list of users which are accepted for authenticating
                against the FTP server; defaults to [] (no restrictions).

             - (list) rejected_users:
                a list of users which are not accepted for authenticating
                against the FTP server; defaults to [] (no restrictions).

             - (string) anonymous_user:
                specify it if you intend to provide anonymous access.
                The value expected is a string representing the system user
                to use for managing anonymous sessions.
                As for IIS, it is recommended to use Guest account.
                The common practice is to first enable the Guest user, which
                is disabled by default and then assign an empty password.
                Defaults to None (anonymous access disabled).

             - (string) anonymous_password:
                the password of the user who has been chosen to manage the
                anonymous sessions.  Defaults to None (empty password).

             - (string) msg_login:
                the string sent when client logs in.

             - (string) msg_quit:
                the string sent when client quits.
            """
            self.global_perm = global_perm
            self.allowed_users = allowed_users
            self.rejected_users = rejected_users
            self.anonymous_user = anonymous_user
            self.anonymous_password = anonymous_password
            self.msg_login = msg_login
            self.msg_quit = msg_quit
            self._dummy_authorizer = DummyAuthorizer()
            self._dummy_authorizer._check_permissions('', global_perm)
            _Base.__init__(self)
            # actually try to impersonate the user
            if self.anonymous_user is not None:
                self.impersonate_user(self.anonymous_user,
                                      self.anonymous_password)
                self.terminate_impersonation()
예제 #7
0
        def add_user(self, username, homedir=None, **kwargs):
            """Add a "real" system user to the virtual users table.

             - (string) homedir:
                The user home directory.  If this is not specified the
                real user home directory will be determined (if any)
                and used.

             - (dict) **kwargs:
                the same keyword arguments expected by the original
                add_user method: "perm", "msg_login" and "msg_quit".
            """
            # get the list of all available users on the system and check
            # if provided username exists
            users = [entry.pw_name for entry in pwd.getpwall()]
            if not username in users:
                raise AuthorizerError('No such user "%s".' % username)
            if not homedir:
                homedir = pwd.getpwnam(username).pw_dir
                self._dynamic_home_users.append(username)
            DummyAuthorizer.add_user(self, username, '', homedir, **kwargs)
예제 #8
0
def main():
    authorizer = DummyAuthorizer()
    authorizer.add_user('user', '12345', '.', perm='elradfmw')
    authorizer.add_anonymous('.')
    handler = AntiFloodHandler
    handler.authorizer = authorizer
    ftpd = FTPServer(('', 21), handler)
    ftpd.serve_forever(timeout=1)
예제 #9
0
 def __init__(self):
     if os.geteuid() != 0 or not spwd.getspall():
         raise RuntimeError("root privileges are required")
     DummyAuthorizer.__init__(self)
     self._anon_user = ''
     self._dynamic_home_users = []
예제 #10
0
    class WindowsAuthorizer(_Base, BaseWindowsAuthorizer):
        """A wrapper on top of BaseWindowsAuthorizer providing options
        to specify what users should be allowed to login, per-user
        options, etc.

        Example usages:

         >>> from pyftpdlib.contrib.authorizers import WindowsAuthorizer
         >>> # accept all except Administrator
         >>> auth = UnixAuthorizer(rejected_users=["Administrator"])
         >>>
         >>> # accept some users only
         >>> auth = UnixAuthorizer(allowed_users=["matt", "jay"])
         >>>
         >>> # set specific options for a user
         >>> auth.override_user("matt", password="******", perm="elr")
        """

        # --- public API

        def __init__(self,
                     global_perm="elradfmw",
                     allowed_users=[],
                     rejected_users=[],
                     anonymous_user=None,
                     anonymous_password=None,
                     msg_login="******",
                     msg_quit="Goodbye."):
            """Parameters:

             - (string) global_perm:
                a series of letters referencing the users permissions;
                defaults to "elradfmw" which means full read and write
                access for everybody (except anonymous).

             - (list) allowed_users:
                a list of users which are accepted for authenticating
                against the FTP server; defaults to [] (no restrictions).

             - (list) rejected_users:
                a list of users which are not accepted for authenticating
                against the FTP server; defaults to [] (no restrictions).

             - (string) anonymous_user:
                specify it if you intend to provide anonymous access.
                The value expected is a string representing the system user
                to use for managing anonymous sessions.
                As for IIS, it is recommended to use Guest account.
                The common practice is to first enable the Guest user, which
                is disabled by default and then assign an empty password.
                Defaults to None (anonymous access disabled).

             - (string) anonymous_password:
                the password of the user who has been chosen to manage the
                anonymous sessions.  Defaults to None (empty password).

             - (string) msg_login:
                the string sent when client logs in.

             - (string) msg_quit:
                the string sent when client quits.
            """
            self.global_perm = global_perm
            self.allowed_users = allowed_users
            self.rejected_users = rejected_users
            self.anonymous_user = anonymous_user
            self.anonymous_password = anonymous_password
            self.msg_login = msg_login
            self.msg_quit = msg_quit
            self._dummy_authorizer = DummyAuthorizer()
            self._dummy_authorizer._check_permissions('', global_perm)
            _Base.__init__(self)
            # actually try to impersonate the user
            if self.anonymous_user is not None:
                self.impersonate_user(self.anonymous_user,
                                      self.anonymous_password)
                self.terminate_impersonation()

        def override_user(self,
                          username,
                          password=None,
                          homedir=None,
                          perm=None,
                          msg_login=None,
                          msg_quit=None):
            """Overrides the options specified in the class constructor
            for a specific user.
            """
            _Base.override_user(self, username, password, homedir, perm,
                                msg_login, msg_quit)

        # --- overridden / private API

        def validate_authentication(self, username, password):
            """Authenticates against Windows user database; return
            True on success.
            """
            if username == "anonymous":
                return self.anonymous_user is not None
            if self.allowed_users and username not in self.allowed_users:
                return False
            if self.rejected_users and username in self.rejected_users:
                return False

            overridden_password = self._get_key(username, 'pwd')
            if overridden_password:
                return overridden_password == password
            else:
                return BaseWindowsAuthorizer.validate_authentication(
                    self, username, password)

        def impersonate_user(self, username, password):
            """Impersonate the security context of another user."""
            if username == "anonymous":
                username = self.anonymous_user or ""
                password = self.anonymous_password or ""
            return BaseWindowsAuthorizer.impersonate_user(
                self, username, password)

        @replace_anonymous
        def has_user(self, username):
            if self._is_rejected_user(username):
                return False
            return username in self._get_system_users()

        @replace_anonymous
        def get_home_dir(self, username):
            overridden_home = self._get_key(username, 'home')
            if overridden_home:
                home = overridden_home
            else:
                home = BaseWindowsAuthorizer.get_home_dir(self, username)
            if not PY3 and not isinstance(home, unicode):
                home = home.decode('utf8')
            return home
예제 #11
0
    class UnixAuthorizer(_Base, BaseUnixAuthorizer):
        """A wrapper on top of BaseUnixAuthorizer providing options
        to specify what users should be allowed to login, per-user
        options, etc.

        Example usages:

         >>> from pyftpdlib.contrib.authorizers import UnixAuthorizer
         >>> # accept all except root
         >>> auth = UnixAuthorizer(rejected_users=["root"])
         >>>
         >>> # accept some users only
         >>> auth = UnixAuthorizer(allowed_users=["matt", "jay"])
         >>>
         >>> # accept everybody and don't care if they have not a valid shell
         >>> auth = UnixAuthorizer(require_valid_shell=False)
         >>>
         >>> # set specific options for a user
         >>> auth.override_user("matt", password="******", perm="elr")
        """

        # --- public API

        def __init__(self,
                     global_perm="elradfmw",
                     allowed_users=[],
                     rejected_users=[],
                     require_valid_shell=True,
                     anonymous_user=None,
                     msg_login="******",
                     msg_quit="Goodbye."):
            """Parameters:

             - (string) global_perm:
                a series of letters referencing the users permissions;
                defaults to "elradfmw" which means full read and write
                access for everybody (except anonymous).

             - (list) allowed_users:
                a list of users which are accepted for authenticating
                against the FTP server; defaults to [] (no restrictions).

             - (list) rejected_users:
                a list of users which are not accepted for authenticating
                against the FTP server; defaults to [] (no restrictions).

             - (bool) require_valid_shell:
                Deny access for those users which do not have a valid shell
                binary listed in /etc/shells.
                If /etc/shells cannot be found this is a no-op.
                Anonymous user is not subject to this option, and is free
                to not have a valid shell defined.
                Defaults to True (a valid shell is required for login).

             - (string) anonymous_user:
                specify it if you intend to provide anonymous access.
                The value expected is a string representing the system user
                to use for managing anonymous sessions;  defaults to None
                (anonymous access disabled).

             - (string) msg_login:
                the string sent when client logs in.

             - (string) msg_quit:
                the string sent when client quits.
            """
            BaseUnixAuthorizer.__init__(self, anonymous_user)
            self.global_perm = global_perm
            self.allowed_users = allowed_users
            self.rejected_users = rejected_users
            self.anonymous_user = anonymous_user
            self.require_valid_shell = require_valid_shell
            self.msg_login = msg_login
            self.msg_quit = msg_quit

            self._dummy_authorizer = DummyAuthorizer()
            self._dummy_authorizer._check_permissions('', global_perm)
            _Base.__init__(self)
            if require_valid_shell:
                for username in self.allowed_users:
                    if not self._has_valid_shell(username):
                        raise ValueError("user %s has not a valid shell" %
                                         username)

        def override_user(self,
                          username,
                          password=None,
                          homedir=None,
                          perm=None,
                          msg_login=None,
                          msg_quit=None):
            """Overrides the options specified in the class constructor
            for a specific user.
            """
            if self.require_valid_shell and username != 'anonymous':
                if not self._has_valid_shell(username):
                    raise ValueError("user %s has not a valid shell" %
                                     username)
            _Base.override_user(self, username, password, homedir, perm,
                                msg_login, msg_quit)

        # --- overridden / private API

        def validate_authentication(self, username, password):
            if username == "anonymous":
                return self.anonymous_user is not None
            if self._is_rejected_user(username):
                return False
            if self.require_valid_shell and username != 'anonymous':
                if not self._has_valid_shell(username):
                    return False
            overridden_password = self._get_key(username, 'pwd')
            if overridden_password:
                return overridden_password == password

            return BaseUnixAuthorizer.validate_authentication(
                self, username, password)

        @replace_anonymous
        def has_user(self, username):
            if self._is_rejected_user(username):
                return False
            return username in self._get_system_users()

        @replace_anonymous
        def get_home_dir(self, username):
            overridden_home = self._get_key(username, 'home')
            if overridden_home:
                return overridden_home
            return BaseUnixAuthorizer.get_home_dir(self, username)

        @staticmethod
        def _has_valid_shell(username):
            """Return True if the user has a valid shell binary listed
            in /etc/shells. If /etc/shells can't be found return True.
            """
            file = None
            try:
                try:
                    file = open('/etc/shells', 'r')
                except IOError:
                    err = sys.exc_info()[1]
                    if err.errno == errno.ENOENT:
                        return True
                    raise
                else:
                    try:
                        shell = pwd.getpwnam(username).pw_shell
                    except KeyError:  # invalid user
                        return False
                    for line in file:
                        if line.startswith('#'):
                            continue
                        line = line.strip()
                        if line == shell:
                            return True
                    return False
            finally:
                if file is not None:
                    file.close()
예제 #12
0
    class WindowsAuthorizer(_Base, BaseWindowsAuthorizer):
        """A wrapper on top of BaseWindowsAuthorizer providing options
        to specify what users should be allowed to login, per-user
        options, etc.

        Example usages:

         >>> from pyftpdlib.contrib.authorizers import WindowsAuthorizer
         >>> # accept all except Administrator
         >>> auth = UnixAuthorizer(rejected_users=["Administrator"])
         >>>
         >>> # accept some users only
         >>> auth = UnixAuthorizer(allowed_users=["matt", "jay"])
         >>>
         >>> # set specific options for a user
         >>> auth.override_user("matt", password="******", perm="elr")
        """

        # --- public API

        def __init__(self, global_perm="elradfmw",
                           allowed_users=[],
                           rejected_users=[],
                           anonymous_user=None,
                           anonymous_password=None,
                           msg_login="******",
                           msg_quit="Goodbye."):
            """Parameters:

             - (string) global_perm:
                a series of letters referencing the users permissions;
                defaults to "elradfmw" which means full read and write
                access for everybody (except anonymous).

             - (list) allowed_users:
                a list of users which are accepted for authenticating
                against the FTP server; defaults to [] (no restrictions).

             - (list) rejected_users:
                a list of users which are not accepted for authenticating
                against the FTP server; defaults to [] (no restrictions).

             - (string) anonymous_user:
                specify it if you intend to provide anonymous access.
                The value expected is a string representing the system user
                to use for managing anonymous sessions.
                As for IIS, it is recommended to use Guest account.
                The common practice is to first enable the Guest user, which
                is disabled by default and then assign an empty password.
                Defaults to None (anonymous access disabled).

             - (string) anonymous_password:
                the password of the user who has been chosen to manage the
                anonymous sessions.  Defaults to None (empty password).

             - (string) msg_login:
                the string sent when client logs in.

             - (string) msg_quit:
                the string sent when client quits.
            """
            self.global_perm = global_perm
            self.allowed_users = allowed_users
            self.rejected_users = rejected_users
            self.anonymous_user = anonymous_user
            self.anonymous_password = anonymous_password
            self.msg_login = msg_login
            self.msg_quit = msg_quit
            self._dummy_authorizer = DummyAuthorizer()
            self._dummy_authorizer._check_permissions('', global_perm)
            _Base.__init__(self)
            # actually try to impersonate the user
            if self.anonymous_user is not None:
                self.impersonate_user(self.anonymous_user,
                                      self.anonymous_password)
                self.terminate_impersonation()

        def override_user(self, username, password=None, homedir=None, perm=None,
                          msg_login=None, msg_quit=None):
            """Overrides the options specified in the class constructor
            for a specific user.
            """
            _Base.override_user(self, username, password, homedir, perm,
                                msg_login, msg_quit)

        # --- overridden / private API

        def validate_authentication(self, username, password):
            """Authenticates against Windows user database; return
            True on success.
            """
            if username == "anonymous":
                return self.anonymous_user is not None
            if self.allowed_users and username not in self.allowed_users:
                return False
            if self.rejected_users and username in self.rejected_users:
                return False

            overridden_password = self._get_key(username, 'pwd')
            if overridden_password:
                return overridden_password == password
            else:
                return BaseWindowsAuthorizer.validate_authentication(self,
                                                            username, password)

        def impersonate_user(self, username, password):
            """Impersonate the security context of another user."""
            if username == "anonymous":
                username = self.anonymous_user or ""
                password = self.anonymous_password or ""
            return BaseWindowsAuthorizer.impersonate_user(self, username, password)

        @replace_anonymous
        def has_user(self, username):
            if self._is_rejected_user(username):
                return False
            return username in self._get_system_users()

        @replace_anonymous
        def get_home_dir(self, username):
            overridden_home = self._get_key(username, 'home')
            if overridden_home:
                home = overridden_home
            else:
                home = BaseWindowsAuthorizer.get_home_dir(self, username)
            if not PY3 and not isinstance(home, unicode):
                home = home.decode('utf8')
            return home
예제 #13
0
    class UnixAuthorizer(_Base, BaseUnixAuthorizer):
        """A wrapper on top of BaseUnixAuthorizer providing options
        to specify what users should be allowed to login, per-user
        options, etc.

        Example usages:

         >>> from pyftpdlib.contrib.authorizers import UnixAuthorizer
         >>> # accept all except root
         >>> auth = UnixAuthorizer(rejected_users=["root"])
         >>>
         >>> # accept some users only
         >>> auth = UnixAuthorizer(allowed_users=["matt", "jay"])
         >>>
         >>> # accept everybody and don't care if they have not a valid shell
         >>> auth = UnixAuthorizer(require_valid_shell=False)
         >>>
         >>> # set specific options for a user
         >>> auth.override_user("matt", password="******", perm="elr")
        """

        # --- public API

        def __init__(self, global_perm="elradfmw",
                           allowed_users=[],
                           rejected_users=[],
                           require_valid_shell=True,
                           anonymous_user=None,
                           msg_login="******",
                           msg_quit="Goodbye."):
            """Parameters:

             - (string) global_perm:
                a series of letters referencing the users permissions;
                defaults to "elradfmw" which means full read and write
                access for everybody (except anonymous).

             - (list) allowed_users:
                a list of users which are accepted for authenticating
                against the FTP server; defaults to [] (no restrictions).

             - (list) rejected_users:
                a list of users which are not accepted for authenticating
                against the FTP server; defaults to [] (no restrictions).

             - (bool) require_valid_shell:
                Deny access for those users which do not have a valid shell
                binary listed in /etc/shells.
                If /etc/shells cannot be found this is a no-op.
                Anonymous user is not subject to this option, and is free
                to not have a valid shell defined.
                Defaults to True (a valid shell is required for login).

             - (string) anonymous_user:
                specify it if you intend to provide anonymous access.
                The value expected is a string representing the system user
                to use for managing anonymous sessions;  defaults to None
                (anonymous access disabled).

             - (string) msg_login:
                the string sent when client logs in.

             - (string) msg_quit:
                the string sent when client quits.
            """
            BaseUnixAuthorizer.__init__(self, anonymous_user)
            self.global_perm = global_perm
            self.allowed_users = allowed_users
            self.rejected_users = rejected_users
            self.anonymous_user = anonymous_user
            self.require_valid_shell = require_valid_shell
            self.msg_login = msg_login
            self.msg_quit = msg_quit

            self._dummy_authorizer = DummyAuthorizer()
            self._dummy_authorizer._check_permissions('', global_perm)
            _Base.__init__(self)
            if require_valid_shell:
                for username in self.allowed_users:
                    if not self._has_valid_shell(username):
                        raise ValueError("user %s has not a valid shell"
                                         % username)

        def override_user(self, username, password=None, homedir=None, perm=None,
                          msg_login=None, msg_quit=None):
            """Overrides the options specified in the class constructor
            for a specific user.
            """
            if self.require_valid_shell and username != 'anonymous':
                if not self._has_valid_shell(username):
                    raise ValueError("user %s has not a valid shell"
                                     % username)
            _Base.override_user(self, username, password, homedir, perm,
                                msg_login, msg_quit)

        # --- overridden / private API

        def validate_authentication(self, username, password):
            if username == "anonymous":
                return self.anonymous_user is not None
            if self._is_rejected_user(username):
                return False
            if self.require_valid_shell and username != 'anonymous':
                if not self._has_valid_shell(username):
                    return False
            overridden_password = self._get_key(username, 'pwd')
            if overridden_password:
                return overridden_password == password

            return BaseUnixAuthorizer.validate_authentication(self, username, password)

        @replace_anonymous
        def has_user(self, username):
            if self._is_rejected_user(username):
                return False
            return username in self._get_system_users()

        @replace_anonymous
        def get_home_dir(self, username):
            overridden_home = self._get_key(username, 'home')
            if overridden_home:
                return overridden_home
            return BaseUnixAuthorizer.get_home_dir(self, username)

        @staticmethod
        def _has_valid_shell(username):
            """Return True if the user has a valid shell binary listed
            in /etc/shells. If /etc/shells can't be found return True.
            """
            file = None
            try:
                try:
                    file = open('/etc/shells', 'r')
                except IOError:
                    err = sys.exc_info()[1]
                    if err.errno == errno.ENOENT:
                        return True
                    raise
                else:
                    try:
                        shell = pwd.getpwnam(username).pw_shell
                    except KeyError:  # invalid user
                        return False
                    for line in file:
                        if line.startswith('#'):
                            continue
                        line = line.strip()
                        if line == shell:
                            return True
                    return False
            finally:
                if file is not None:
                    file.close()