OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/env python |
| 2 # unix_ftpd.py |
| 3 |
| 4 """A ftpd using local unix account database to authenticate users |
| 5 (users must already exist). |
| 6 |
| 7 It also provides a mechanism to (temporarily) impersonate the system |
| 8 users every time they are going to perform filesystem operations. |
| 9 """ |
| 10 |
| 11 import os |
| 12 import pwd, spwd, crypt |
| 13 |
| 14 from pyftpdlib import ftpserver |
| 15 |
| 16 |
| 17 class UnixAuthorizer(ftpserver.DummyAuthorizer): |
| 18 |
| 19 # the uid/gid the daemon runs under |
| 20 PROCESS_UID = os.getuid() |
| 21 PROCESS_GID = os.getgid() |
| 22 |
| 23 def add_user(self, username, homedir=None, **kwargs): |
| 24 """Add a "real" system user to the virtual users table. |
| 25 |
| 26 If no home argument is specified the user's home directory will |
| 27 be used. |
| 28 |
| 29 The keyword arguments in kwargs are the same expected by the |
| 30 original add_user method: "perm", "msg_login" and "msg_quit". |
| 31 """ |
| 32 # get the list of all available users on the system and check |
| 33 # if provided username exists |
| 34 users = [entry.pw_name for entry in pwd.getpwall()] |
| 35 if not username in users: |
| 36 raise ftpserver.AuthorizerError('No such user "%s".' %username) |
| 37 if not homedir: |
| 38 homedir = pwd.getpwnam(username).pw_dir |
| 39 ftpserver.DummyAuthorizer.add_user(self, username, '', homedir,**kwargs) |
| 40 |
| 41 def add_anonymous(self, homedir=None, realuser="nobody", **kwargs): |
| 42 """Add an anonymous user to the virtual users table. |
| 43 |
| 44 If no homedir argument is specified the realuser's home |
| 45 directory will possibly be determined and used. |
| 46 |
| 47 realuser argument specifies the system user to use for managing |
| 48 anonymous sessions. On many UNIX systems "nobody" is tipically |
| 49 used but it may change (e.g. "ftp"). |
| 50 """ |
| 51 users = [entry.pw_name for entry in pwd.getpwall()] |
| 52 if not realuser in users: |
| 53 raise ftpserver.AuthorizerError('No such user "%s".' %realuser) |
| 54 if not homedir: |
| 55 homedir = pwd.getpwnam(realuser).pw_dir |
| 56 ftpserver.DummyAuthorizer.add_anonymous(self, homedir, **kwargs) |
| 57 self.anon_user = realuser |
| 58 |
| 59 def validate_authentication(self, username, password): |
| 60 if (username == "anonymous") and self.has_user('anonymous'): |
| 61 username = self.anon_user |
| 62 pw1 = spwd.getspnam(username).sp_pwd |
| 63 pw2 = crypt.crypt(password, pw1) |
| 64 return pw1 == pw2 |
| 65 |
| 66 def impersonate_user(self, username, password): |
| 67 if (username == "anonymous") and self.has_user('anonymous'): |
| 68 username = self.anon_user |
| 69 uid = pwd.getpwnam(username).pw_uid |
| 70 gid = pwd.getpwnam(username).pw_gid |
| 71 os.setegid(gid) |
| 72 os.seteuid(uid) |
| 73 |
| 74 def terminate_impersonation(self): |
| 75 os.setegid(self.PROCESS_GID) |
| 76 os.seteuid(self.PROCESS_UID) |
| 77 |
| 78 |
| 79 if __name__ == "__main__": |
| 80 authorizer = UnixAuthorizer() |
| 81 # add a user (note: user must already exists) |
| 82 authorizer.add_user('user', perm='elradfmw') |
| 83 authorizer.add_anonymous(os.getcwd()) |
| 84 ftp_handler = ftpserver.FTPHandler |
| 85 ftp_handler.authorizer = authorizer |
| 86 address = ('', 21) |
| 87 ftpd = ftpserver.FTPServer(address, ftp_handler) |
| 88 ftpd.serve_forever() |
OLD | NEW |