| Index: third_party/pyftpdlib/demo/winnt_ftpd.py
|
| ===================================================================
|
| --- third_party/pyftpdlib/demo/winnt_ftpd.py (revision 0)
|
| +++ third_party/pyftpdlib/demo/winnt_ftpd.py (revision 0)
|
| @@ -0,0 +1,115 @@
|
| +#!/usr/bin/env python
|
| +# winnt_ftpd.py
|
| +
|
| +"""A ftpd using local Windows NT 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 win32security, win32net, pywintypes, win32con
|
| +
|
| +from pyftpdlib import ftpserver
|
| +
|
| +
|
| +def get_profile_dir(username):
|
| + """Return the user's profile directory."""
|
| + import _winreg, win32api
|
| + sid = win32security.ConvertSidToStringSid(
|
| + win32security.LookupAccountName(None, username)[0])
|
| + try:
|
| + key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
|
| + r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"+"\\"+sid)
|
| + except WindowsError:
|
| + raise ftpserver.AuthorizerError("No profile directory defined for %s "
|
| + "user" %username)
|
| + value = _winreg.QueryValueEx(key, "ProfileImagePath")[0]
|
| + return win32api.ExpandEnvironmentStrings(value)
|
| +
|
| +
|
| +class WinNtAuthorizer(ftpserver.DummyAuthorizer):
|
| +
|
| + def add_user(self, username, homedir=None, **kwargs):
|
| + """Add a "real" system user to the virtual users table.
|
| +
|
| + If no homedir argument is specified the user's profile
|
| + directory will possibly be determined and 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['name'] for entry in win32net.NetUserEnum(None, 0)[0]]
|
| + if not username in users:
|
| + raise ftpserver.AuthorizerError('No such user "%s".' %username)
|
| + if not homedir:
|
| + homedir = get_profile_dir(username)
|
| + ftpserver.DummyAuthorizer.add_user(self, username, '', homedir,
|
| + **kwargs)
|
| +
|
| + def add_anonymous(self, homedir=None, realuser="Guest",
|
| + password="", **kwargs):
|
| + """Add an anonymous user to the virtual users table.
|
| +
|
| + If no homedir argument is specified the realuser's profile
|
| + directory will possibly be determined and used.
|
| +
|
| + realuser and password arguments are the credentials to use for
|
| + managing anonymous sessions.
|
| + The same behaviour is followed in IIS where the Guest account
|
| + is used to do so (note: it must be enabled first).
|
| + """
|
| + users = [entry['name'] for entry in win32net.NetUserEnum(None, 0)[0]]
|
| + if not realuser in users:
|
| + raise ftpserver.AuthorizerError('No such user "%s".' %realuser)
|
| + if not homedir:
|
| + homedir = get_profile_dir(realuser)
|
| + # make sure provided credentials are valid, otherwise an exception
|
| + # will be thrown; to do so we actually impersonate the user
|
| + self.impersonate_user(realuser, password)
|
| + self.terminate_impersonation()
|
| + ftpserver.DummyAuthorizer.add_anonymous(self, homedir, **kwargs)
|
| + self.anon_user = realuser
|
| + self.anon_pwd = password
|
| +
|
| + def validate_authentication(self, username, password):
|
| + if (username == "anonymous") and self.has_user('anonymous'):
|
| + username = self.anon_user
|
| + password = self.anon_pwd
|
| + try:
|
| + win32security.LogonUser(username, None, password,
|
| + win32con.LOGON32_LOGON_INTERACTIVE,
|
| + win32con.LOGON32_PROVIDER_DEFAULT)
|
| + return True
|
| + except pywintypes.error:
|
| + return False
|
| +
|
| + def impersonate_user(self, username, password):
|
| + if (username == "anonymous") and self.has_user('anonymous'):
|
| + username = self.anon_user
|
| + password = self.anon_pwd
|
| + handler = win32security.LogonUser(username, None, password,
|
| + win32con.LOGON32_LOGON_INTERACTIVE,
|
| + win32con.LOGON32_PROVIDER_DEFAULT)
|
| + win32security.ImpersonateLoggedOnUser(handler)
|
| + handler.Close()
|
| +
|
| + def terminate_impersonation(self):
|
| + win32security.RevertToSelf()
|
| +
|
| +
|
| +if __name__ == "__main__":
|
| + authorizer = WinNtAuthorizer()
|
| + # add a user (note: user must already exists)
|
| + authorizer.add_user('user', perm='elradfmw')
|
| + # add an anonymous user using Guest account to handle the anonymous
|
| + # sessions (note: Guest must be enabled first)
|
| + authorizer.add_anonymous(os.getcwd())
|
| + ftp_handler = ftpserver.FTPHandler
|
| + ftp_handler.authorizer = authorizer
|
| + address = ('', 21)
|
| + ftpd = ftpserver.FTPServer(address, ftp_handler)
|
| + ftpd.serve_forever()
|
|
|