-
Notifications
You must be signed in to change notification settings - Fork 6
/
faetus-server
executable file
·127 lines (99 loc) · 4.76 KB
/
faetus-server
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#!/usr/bin/env python
import sys
import logging
from optparse import OptionParser
from socket import gethostbyname, gaierror
from pyftpdlib import ftpserver
from faetus.server import FaetusFTPHandler, FaetusAuthorizer, FaetusFS
from faetus.constants import version, default_address, default_port
def dict_from_string(string):
""" Transform a colon-separated pair into a dict."""
# Ugh. ''.split(":") is [''], not [] as it should be.
if (string): return dict([string.split(":")])
else: return dict()
def setup_log(log_file=None):
''' Setup Logging '''
def log(log_type, msg):
log_type(msg)
ftpserver.log = lambda msg: log(logging.info, msg)
ftpserver.logline = lambda msg: log(logging.debug, msg)
ftpserver.logerror = lambda msg: log(logging.error, msg)
log_format = '%(asctime)-15s - %(levelname)s - %(message)s'
logging.basicConfig(filename=log_file,
format=log_format,
level=logging.DEBUG)
def main():
''' Main function'''
parser = OptionParser(usage="faetus-server [OPTIONS].....")
parser.add_option('-p', '--port',
type="int",
dest="port",
default=default_port,
help="Port to bind the server: %d" % (default_port))
parser.add_option('-r', '--range',
type="str",
dest="range",
default="",
help="Range to use for passive ports (min,max) inclusive: %d,%d"
% (60000, 65000))
parser.add_option('-b', '--bind-address',
type="str",
dest="bind_address",
default=default_address,
help="Address to bind default: %s." % (default_address))
parser.add_option('-l', '--log-file',
type="str",
dest="log_file",
default=None,
help="Log File: Default stdout")
parser.add_option('-u', '--username-transform-map',
type="str",
dest="username_transform_map_str",
default=None,
help="mapping from ftp username to AWS_ACCESS_KEY_ID: username:AWS_ACCESS_KEY. Default: none.")
parser.add_option('-v', '--password-transform-map',
type="str",
dest="password_transform_map_str",
default=None,
help="mapping from ftp password to AWS_SECRET_ACCESS_KEY: password:AWS_SECRET_ACCESS_KEY.\n Default: none. WARNING: This is not secure against local user eavesdropping!")
parser.add_option('-a', '--allowed-users',
type="str",
dest="allowed_users_str",
default=None,
help="comma-separated list of allowed logins: ftp_username1, ftp_username2. " +
"Set this option to prevent using this server as an 'open relay' to S3 account." +
"Username is checked against this list *before* username-transform-map is applied." +
"Default: none")
(options, _) = parser.parse_args()
setup_log(options.log_file)
ftp_handler = FaetusFTPHandler
ftp_handler.banner = 'Faetus %s using %s' % \
(version, ftp_handler.banner)
username_transform_map = dict_from_string(options.username_transform_map_str)
password_transform_map = dict_from_string(options.password_transform_map_str)
ftpserver.log("Using username map: %s " % (username_transform_map))
# Check for None, not false here. If the server
# really wants to allow an empty list of allowed users,
# then allow no users.
if options.allowed_users_str is not None:
allowed_users = options.allowed_users_str.split(",")
else:
allowed_users = None
ftp_handler.authorizer = FaetusAuthorizer(allowed_users, username_transform_map, password_transform_map)
ftp_handler.abstracted_fs = FaetusFS
# Port range must include both start and end to be valid.
range_spec = options.range.split(",")
if len(range_spec) >= 2:
(min_port, max_port) = (int(range_spec[0]), int(range_spec[1]))
ftp_handler.passive_ports = range(min_port, max_port)
ftpserver.log("Passive mode port range: %i-%i" % (min_port, max_port))
ftpd = ftpserver.FTPServer((options.bind_address,
options.port),
ftp_handler)
try:
ftp_handler.masquerade_address = gethostbyname(options.bind_address)
except gaierror, (_, errmsg):
sys.exit('Address error: %s' % errmsg)
ftpd.serve_forever()
if __name__ == '__main__':
main()