| Index: third_party/pyftpdlib/demo/unix_ftpd.py
|
| ===================================================================
|
| --- third_party/pyftpdlib/demo/unix_ftpd.py (revision 0)
|
| +++ third_party/pyftpdlib/demo/unix_ftpd.py (revision 0)
|
| @@ -0,0 +1,88 @@
|
| +#!/usr/bin/env python
|
| +# unix_ftpd.py
|
| +
|
| +"""A ftpd using local unix account database to authenticate users
|
| +(users must already exist).
|
| +
|
| +It also provides a mechanism to (temporarily) impersonate the system
|
| +users every time they are going to perform filesystem operations.
|
| +"""
|
| +
|
| +import os
|
| +import pwd, spwd, crypt
|
| +
|
| +from pyftpdlib import ftpserver
|
| +
|
| +
|
| +class UnixAuthorizer(ftpserver.DummyAuthorizer):
|
| +
|
| + # the uid/gid the daemon runs under
|
| + PROCESS_UID = os.getuid()
|
| + PROCESS_GID = os.getgid()
|
| +
|
| + def add_user(self, username, homedir=None, **kwargs):
|
| + """Add a "real" system user to the virtual users table.
|
| +
|
| + If no home argument is specified the user's home directory will
|
| + be used.
|
| +
|
| + The keyword arguments in kwargs are the same 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 ftpserver.AuthorizerError('No such user "%s".' %username)
|
| + if not homedir:
|
| + homedir = pwd.getpwnam(username).pw_dir
|
| + ftpserver.DummyAuthorizer.add_user(self, username, '', homedir,**kwargs)
|
| +
|
| + def add_anonymous(self, homedir=None, realuser="nobody", **kwargs):
|
| + """Add an anonymous user to the virtual users table.
|
| +
|
| + If no homedir argument is specified the realuser's home
|
| + directory will possibly be determined and used.
|
| +
|
| + realuser argument specifies the system user to use for managing
|
| + anonymous sessions. On many UNIX systems "nobody" is tipically
|
| + used but it may change (e.g. "ftp").
|
| + """
|
| + users = [entry.pw_name for entry in pwd.getpwall()]
|
| + if not realuser in users:
|
| + raise ftpserver.AuthorizerError('No such user "%s".' %realuser)
|
| + if not homedir:
|
| + homedir = pwd.getpwnam(realuser).pw_dir
|
| + ftpserver.DummyAuthorizer.add_anonymous(self, homedir, **kwargs)
|
| + self.anon_user = realuser
|
| +
|
| + def validate_authentication(self, username, password):
|
| + if (username == "anonymous") and self.has_user('anonymous'):
|
| + username = self.anon_user
|
| + pw1 = spwd.getspnam(username).sp_pwd
|
| + pw2 = crypt.crypt(password, pw1)
|
| + return pw1 == pw2
|
| +
|
| + def impersonate_user(self, username, password):
|
| + if (username == "anonymous") and self.has_user('anonymous'):
|
| + username = self.anon_user
|
| + uid = pwd.getpwnam(username).pw_uid
|
| + gid = pwd.getpwnam(username).pw_gid
|
| + os.setegid(gid)
|
| + os.seteuid(uid)
|
| +
|
| + def terminate_impersonation(self):
|
| + os.setegid(self.PROCESS_GID)
|
| + os.seteuid(self.PROCESS_UID)
|
| +
|
| +
|
| +if __name__ == "__main__":
|
| + authorizer = UnixAuthorizer()
|
| + # add a user (note: user must already exists)
|
| + authorizer.add_user('user', perm='elradfmw')
|
| + authorizer.add_anonymous(os.getcwd())
|
| + ftp_handler = ftpserver.FTPHandler
|
| + ftp_handler.authorizer = authorizer
|
| + address = ('', 21)
|
| + ftpd = ftpserver.FTPServer(address, ftp_handler)
|
| + ftpd.serve_forever()
|
|
|