#!/usr/bin/env python3 import hashlib import os import pyftpdlib.authorizers import pyftpdlib.handlers import pyftpdlib.servers class SHA256Authorizer(pyftpdlib.authorizers.DummyAuthorizer): def validate_authentication(self, username, password, handler): # pyftpdlib/authorizers.py", line 110, in add_user # dic = {'pwd': str(password), # so we can not compare against .digest() password_hash = hashlib.sha256(password.encode()).hexdigest() if self.user_table[username]['pwd'] != password_hash.lower(): raise pyftpdlib.authorizers.AuthenticationFailed() def serve(root_dir_path, username, password_sha256_hexdigest, control_port, passive_port): assert os.path.isdir(root_dir_path), root_dir_path authorizer = SHA256Authorizer() authorizer.add_user( username, password_sha256_hexdigest.lower(), homedir=root_dir_path, # https://pyftpdlib.readthedocs.io/en/latest/api.html#pyftpdlib.authorizers.DummyAuthorizer.add_user # e: change dir # m: mkdir # w: write perm='emw', msg_login='renshi ni hen gaoxing', msg_quit='zaijian', ) handler = pyftpdlib.handlers.FTPHandler handler.authorizer = authorizer handler.banner = 'ni hao' # handler.masquerade_address = '192.168.1.1' handler.passive_ports = (passive_port,) server = pyftpdlib.servers.FTPServer((None, control_port), handler) # apparently requires +1 for unknown reasons server.max_cons = 1 + 1 server.serve_forever() def _init_argparser(): import argparse argparser = argparse.ArgumentParser() argparser.add_argument( '--root', '--root-dir', metavar='path', dest='root_dir_path', required=True, ) argparser.add_argument( '--user', '--username', metavar='username', dest='username', required=True, ) argparser.add_argument( '--pwd-hash', '--password-hash', metavar='sha256_hexdigest', dest='password_sha256_hexdigest', required=True, ) argparser.add_argument( '--ctrl-port', '--control-port', metavar='port', dest='control_port', default=2121, ) argparser.add_argument( '--pasv-port', '--passive-port', metavar='port', dest='passive_port', default=62121, ) return argparser def main(argv): argparser = _init_argparser() args = argparser.parse_args(argv[1:]) serve(**vars(args)) return 0 if __name__ == "__main__": import sys sys.exit(main(sys.argv))