2 * Part of Very Secure FTPd
16 #include "sysdeputil.h"
18 #include "parseconf.h"
19 #include "oneprocess.h"
20 #include "twoprocess.h"
21 #include "standalone.h"
27 * Forward decls of helper functions
29 static void die_unless_privileged(void);
30 static void do_sanity_checks(void);
31 static void session_init(struct vsf_session
* p_sess
);
32 static void env_init(void);
33 static void limits_init(void);
36 main(int argc
, const char* argv
[])
38 struct vsf_session the_session
=
40 /* Control connection */
43 -1, 0, -1, 0, 0, 0, 0,
45 1, 0, INIT_MYSTR
, INIT_MYSTR
,
47 0, 1, INIT_MYSTR
, 0, 0,
54 /* Pre-chroot() cache */
55 INIT_MYSTR
, INIT_MYSTR
, INIT_MYSTR
, INIT_MYSTR
, 1,
57 -1, -1, INIT_MYSTR
, 0, 0, 0, INIT_MYSTR
, 0,
59 INIT_MYSTR
, INIT_MYSTR
,
60 /* Parent <-> child comms */
62 /* Number of clients */
66 /* Secure connection state */
67 0, 0, 0, 0, 0, INIT_MYSTR
, 0, -1, -1,
71 int config_loaded
= 0;
73 tunables_load_defaults();
74 /* This might need to open /dev/zero on systems lacking MAP_ANON. Needs
75 * to be done early (i.e. before config file parse, which may use
78 vsf_sysutil_map_anon_pages_init();
79 /* Argument parsing. Any argument not starting with "-" is a config file,
80 * loaded in the order encountered. -o opt=value options are loading in the
81 * order encountered, including correct ordering with respect intermingled
83 * If we see -v (version) or an unknown option, parsing bails and exits.
87 die("vsftpd: missing argv[0]");
89 for (i
= 1; i
< argc
; ++i
)
91 const char* p_arg
= argv
[i
];
95 vsf_parseconf_load_file(p_arg
, 1);
101 vsf_exit("vsftpd: version " VSF_VERSION
"\n");
103 else if (p_arg
[1] == 'o')
105 vsf_parseconf_load_setting(&p_arg
[2], 1);
109 die2("unrecognise option: ", p_arg
);
113 /* Parse default config file if necessary */
114 if (!config_loaded
) {
115 struct vsf_sysutil_statbuf
* p_statbuf
= 0;
116 int retval
= vsf_sysutil_stat(VSFTP_DEFAULT_CONFIG
, &p_statbuf
);
117 if (!vsf_sysutil_retval_is_error(retval
))
119 vsf_parseconf_load_file(VSFTP_DEFAULT_CONFIG
, 1);
121 vsf_sysutil_free(p_statbuf
);
123 /* Resolve pasv_address if required */
124 if (tunable_pasv_address
&& tunable_pasv_addr_resolve
)
126 struct vsf_sysutil_sockaddr
* p_addr
= 0;
127 const char* p_numeric_addr
;
128 vsf_sysutil_dns_resolve(&p_addr
, tunable_pasv_address
);
129 vsf_sysutil_free((char*) tunable_pasv_address
);
130 p_numeric_addr
= vsf_sysutil_inet_ntop(p_addr
);
131 tunable_pasv_address
= vsf_sysutil_strdup(p_numeric_addr
);
132 vsf_sysutil_free(p_addr
);
134 if (!tunable_run_as_launching_user
)
136 /* Just get out unless we start with requisite privilege */
137 die_unless_privileged();
139 if (tunable_setproctitle_enable
)
141 /* Warning -- warning -- may nuke argv, environ */
142 vsf_sysutil_setproctitle_init(argc
, argv
);
144 /* Initialize the SSL system here if needed - saves the overhead of each
145 * child doing this itself.
147 if (tunable_ssl_enable
)
149 ssl_init(&the_session
);
151 if (tunable_listen
|| tunable_listen_ipv6
)
153 /* Standalone mode */
154 struct vsf_client_launch ret
= vsf_standalone_main();
155 the_session
.num_clients
= ret
.num_children
;
156 the_session
.num_this_ip
= ret
.num_this_ip
;
158 if (tunable_tcp_wrappers
)
160 the_session
.tcp_wrapper_ok
= vsf_tcp_wrapper_ok(VSFTP_COMMAND_FD
);
163 const char* p_load_conf
= vsf_sysutil_getenv("VSFTPD_LOAD_CONF");
166 vsf_parseconf_load_file(p_load_conf
, 1);
169 /* Sanity checks - exit with a graceful error message if our STDIN is not
170 * a socket. Also check various config options don't collide.
173 /* Initializes session globals - e.g. IP addr's etc. */
174 session_init(&the_session
);
175 /* Set up "environment", e.g. process group etc. */
177 /* Set up resource limits. */
179 /* Set up logging - must come after global init because we need the remote
180 * address to convert into text
182 vsf_log_init(&the_session
);
183 str_alloc_text(&the_session
.remote_ip_str
,
184 vsf_sysutil_inet_ntop(the_session
.p_remote_addr
));
185 /* Set up options on the command socket */
186 vsf_cmdio_sock_setup();
187 if (tunable_setproctitle_enable
)
189 vsf_sysutil_set_proctitle_prefix(&the_session
.remote_ip_str
);
190 vsf_sysutil_setproctitle("connected");
192 /* We might chroot() very soon (one process model), so we need to open
193 * any required config files here.
195 /* SSL may have been enabled by a per-IP configuration.. */
196 if (tunable_ssl_enable
)
198 ssl_init(&the_session
);
199 ssl_add_entropy(&the_session
);
201 if (tunable_deny_email_enable
)
203 int retval
= str_fileread(&the_session
.banned_email_str
,
204 tunable_banned_email_file
, VSFTP_CONF_FILE_MAX
);
205 if (vsf_sysutil_retval_is_error(retval
))
207 die2("cannot read anon e-mail list file:", tunable_banned_email_file
);
210 if (tunable_banner_file
)
212 int retval
= str_fileread(&the_session
.banner_str
, tunable_banner_file
,
213 VSFTP_CONF_FILE_MAX
);
214 if (vsf_sysutil_retval_is_error(retval
))
216 die2("cannot read banner file:", tunable_banner_file
);
219 if (tunable_secure_email_list_enable
)
221 int retval
= str_fileread(&the_session
.email_passwords_str
,
222 tunable_email_password_file
,
223 VSFTP_CONF_FILE_MAX
);
224 if (vsf_sysutil_retval_is_error(retval
))
226 die2("cannot read email passwords file:", tunable_email_password_file
);
229 if (tunable_run_as_launching_user
)
231 tunable_one_process_model
= 1;
232 if (!vsf_sysutil_running_as_root())
234 tunable_connect_from_port_20
= 0;
235 tunable_chown_uploads
= 0;
238 if (tunable_one_process_model
)
240 vsf_one_process_start(&the_session
);
244 vsf_two_process_start(&the_session
);
247 bug("should not get here: main");
252 die_unless_privileged(void)
254 if (!vsf_sysutil_running_as_root())
256 die("vsftpd: must be started as root (see run_as_launching_user option)");
261 do_sanity_checks(void)
264 struct vsf_sysutil_statbuf
* p_statbuf
= 0;
265 vsf_sysutil_fstat(VSFTP_COMMAND_FD
, &p_statbuf
);
266 if (!vsf_sysutil_statbuf_is_socket(p_statbuf
))
268 die("vsftpd: not configured for standalone, must be started from inetd");
270 vsf_sysutil_free(p_statbuf
);
272 if (tunable_one_process_model
)
274 if (tunable_local_enable
)
276 die("vsftpd: security: 'one_process_model' is anonymous only");
278 if (!vsf_sysdep_has_capabilities_as_non_root())
280 die("vsftpd: security: 'one_process_model' needs a better OS");
283 if (!tunable_local_enable
&& !tunable_anonymous_enable
)
285 die("vsftpd: both local and anonymous access disabled!");
287 if (!tunable_ftp_enable
&& !tunable_http_enable
)
289 die("vsftpd: both FTP and HTTP disabled!");
291 if (tunable_http_enable
&& !tunable_one_process_model
)
293 die("vsftpd: HTTP needs 'one_process_model' for now");
300 vsf_sysutil_make_session_leader();
301 /* Set up a secure umask - we'll set the proper one after login */
302 vsf_sysutil_set_umask(VSFTP_SECURE_UMASK
);
303 /* Fire up libc's timezone initialisation, before we chroot()! */
305 /* Signals. We'll always take -EPIPE rather than a rude signal, thanks */
306 vsf_sysutil_install_null_sighandler(kVSFSysUtilSigPIPE
);
312 unsigned long limit
= VSFTP_AS_LIMIT
;
313 if (tunable_text_userdb_names
)
315 /* Turns out, LDAP lookups for lots of userid -> name mappings can really
316 * bloat memory usage.
320 vsf_sysutil_set_address_space_limit(limit
);
324 session_init(struct vsf_session
* p_sess
)
326 /* Get the addresses of the control connection */
327 vsf_sysutil_getpeername(VSFTP_COMMAND_FD
, &p_sess
->p_remote_addr
);
328 vsf_sysutil_getsockname(VSFTP_COMMAND_FD
, &p_sess
->p_local_addr
);
329 /* If anonymous mode is active, fetch the uid of the anonymous user */
330 if (tunable_anonymous_enable
)
332 const struct vsf_sysutil_user
* p_user
=
333 vsf_sysutil_getpwnam(tunable_ftp_username
);
336 die2("vsftpd: cannot locate user specified in 'ftp_username':",
337 tunable_ftp_username
);
339 p_sess
->anon_ftp_uid
= vsf_sysutil_user_getuid(p_user
);
341 if (tunable_guest_enable
)
343 const struct vsf_sysutil_user
* p_user
=
344 vsf_sysutil_getpwnam(tunable_guest_username
);
347 die2("vsftpd: cannot locate user specified in 'guest_username':",
348 tunable_guest_username
);
350 p_sess
->guest_user_uid
= vsf_sysutil_user_getuid(p_user
);
352 if (tunable_chown_uploads
)
354 const struct vsf_sysutil_user
* p_user
=
355 vsf_sysutil_getpwnam(tunable_chown_username
);
358 die2("vsftpd: cannot locate user specified in 'chown_username':",
359 tunable_chown_username
);
361 p_sess
->anon_upload_chown_uid
= vsf_sysutil_user_getuid(p_user
);