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);
35 main(int argc
, const char* argv
[])
37 struct vsf_session the_session
=
39 /* Control connection */
42 -1, 0, -1, 0, 0, 0, 0,
44 1, 0, INIT_MYSTR
, INIT_MYSTR
,
46 0, 1, INIT_MYSTR
, 0, 0,
51 /* Pre-chroot() cache */
52 INIT_MYSTR
, INIT_MYSTR
, INIT_MYSTR
, INIT_MYSTR
, 1,
54 -1, -1, INIT_MYSTR
, 0, 0, 0, INIT_MYSTR
, 0,
56 INIT_MYSTR
, INIT_MYSTR
,
57 /* Parent <-> child comms */
59 /* Number of clients */
63 /* Secure connection state */
64 0, 0, 0, 0, 0, INIT_MYSTR
, 0, -1, -1,
68 int config_specified
= 0;
69 const char* p_config_name
= VSFTP_DEFAULT_CONFIG
;
70 /* Zero or one argument supported. If one argument is passed, it is the
71 * path to the config file
75 die("vsftpd: too many arguments (I take an optional config file only)");
79 die("vsftpd: missing argv[0]");
83 if (!vsf_sysutil_strcmp(argv
[1], "-v"))
85 vsf_exit("vsftpd: version " VSF_VERSION
"\n");
87 p_config_name
= argv
[1];
90 /* This might need to open /dev/zero on systems lacking MAP_ANON. Needs
91 * to be done early (i.e. before config file parse, which may use
94 vsf_sysutil_map_anon_pages_init();
95 /* Parse config file if it's there */
97 struct vsf_sysutil_statbuf
* p_statbuf
= 0;
98 int retval
= vsf_sysutil_stat(p_config_name
, &p_statbuf
);
99 if (!vsf_sysutil_retval_is_error(retval
))
101 vsf_parseconf_load_file(p_config_name
, 1);
103 else if (config_specified
)
105 die2("vsftpd: cannot open config file:", p_config_name
);
107 vsf_sysutil_free(p_statbuf
);
109 /* Resolve pasv_address if required */
110 if (tunable_pasv_address
&& tunable_pasv_addr_resolve
)
112 struct vsf_sysutil_sockaddr
* p_addr
= 0;
113 const char* p_numeric_addr
;
114 vsf_sysutil_dns_resolve(&p_addr
, tunable_pasv_address
);
115 vsf_sysutil_free((char*) tunable_pasv_address
);
116 p_numeric_addr
= vsf_sysutil_inet_ntop(p_addr
);
117 tunable_pasv_address
= vsf_sysutil_strdup(p_numeric_addr
);
118 vsf_sysutil_free(p_addr
);
120 if (!tunable_run_as_launching_user
)
122 /* Just get out unless we start with requisite privilege */
123 die_unless_privileged();
125 if (tunable_setproctitle_enable
)
127 /* Warning -- warning -- may nuke argv, environ */
128 vsf_sysutil_setproctitle_init(argc
, argv
);
130 /* Initialize the SSL system here if needed - saves the overhead of each
131 * child doing this itself.
133 if (tunable_ssl_enable
)
135 ssl_init(&the_session
);
137 if (tunable_listen
|| tunable_listen_ipv6
)
139 /* Standalone mode */
140 struct vsf_client_launch ret
= vsf_standalone_main();
141 the_session
.num_clients
= ret
.num_children
;
142 the_session
.num_this_ip
= ret
.num_this_ip
;
144 if (tunable_tcp_wrappers
)
146 the_session
.tcp_wrapper_ok
= vsf_tcp_wrapper_ok(VSFTP_COMMAND_FD
);
149 const char* p_load_conf
= vsf_sysutil_getenv("VSFTPD_LOAD_CONF");
152 vsf_parseconf_load_file(p_load_conf
, 1);
155 /* Sanity checks - exit with a graceful error message if our STDIN is not
156 * a socket. Also check various config options don't collide.
159 /* Initializes session globals - e.g. IP addr's etc. */
160 session_init(&the_session
);
161 /* Set up "environment", e.g. process group etc. */
163 /* Set up logging - must come after global init because we need the remote
164 * address to convert into text
166 vsf_log_init(&the_session
);
167 str_alloc_text(&the_session
.remote_ip_str
,
168 vsf_sysutil_inet_ntop(the_session
.p_remote_addr
));
169 /* Set up options on the command socket */
170 vsf_cmdio_sock_setup();
171 if (tunable_setproctitle_enable
)
173 vsf_sysutil_set_proctitle_prefix(&the_session
.remote_ip_str
);
174 vsf_sysutil_setproctitle("connected");
176 /* We might chroot() very soon (one process model), so we need to open
177 * any required config files here.
179 /* SSL may have been enabled by a per-IP configuration.. */
180 if (tunable_ssl_enable
)
182 ssl_init(&the_session
);
184 if (tunable_deny_email_enable
)
186 int retval
= str_fileread(&the_session
.banned_email_str
,
187 tunable_banned_email_file
, VSFTP_CONF_FILE_MAX
);
188 if (vsf_sysutil_retval_is_error(retval
))
190 die2("cannot open anon e-mail list file:", tunable_banned_email_file
);
193 if (tunable_banner_file
)
195 int retval
= str_fileread(&the_session
.banner_str
, tunable_banner_file
,
196 VSFTP_CONF_FILE_MAX
);
197 if (vsf_sysutil_retval_is_error(retval
))
199 die2("cannot open banner file:", tunable_banner_file
);
202 if (tunable_secure_email_list_enable
)
204 int retval
= str_fileread(&the_session
.email_passwords_str
,
205 tunable_email_password_file
,
206 VSFTP_CONF_FILE_MAX
);
207 if (vsf_sysutil_retval_is_error(retval
))
209 die2("cannot open email passwords file:", tunable_email_password_file
);
212 /* Special case - can force one process model if we've got a setup
215 if (!tunable_local_enable
&& !tunable_connect_from_port_20
&&
216 !tunable_chown_uploads
)
218 tunable_one_process_model
= 1;
220 if (tunable_run_as_launching_user
)
222 tunable_one_process_model
= 1;
223 if (!vsf_sysutil_running_as_root())
225 tunable_connect_from_port_20
= 0;
226 tunable_chown_uploads
= 0;
229 if (tunable_one_process_model
)
231 vsf_one_process_start(&the_session
);
235 vsf_two_process_start(&the_session
);
238 bug("should not get here: main");
243 die_unless_privileged(void)
245 if (!vsf_sysutil_running_as_root())
247 die("vsftpd: must be started as root (see run_as_launching_user option)");
252 do_sanity_checks(void)
255 struct vsf_sysutil_statbuf
* p_statbuf
= 0;
256 vsf_sysutil_fstat(VSFTP_COMMAND_FD
, &p_statbuf
);
257 if (!vsf_sysutil_statbuf_is_socket(p_statbuf
))
259 die("vsftpd: not configured for standalone, must be started from inetd");
261 vsf_sysutil_free(p_statbuf
);
263 if (tunable_one_process_model
)
265 if (tunable_local_enable
)
267 die("vsftpd: security: 'one_process_model' is anonymous only");
269 if (!vsf_sysdep_has_capabilities_as_non_root())
271 die("vsftpd: security: 'one_process_model' needs a better OS");
273 if (tunable_ssl_enable
)
275 die("vsftpd: SSL mode not compatible with 'one_process_model'");
278 if (!tunable_local_enable
&& !tunable_anonymous_enable
)
280 die("vsftpd: both local and anonymous access disabled!");
287 vsf_sysutil_make_session_leader();
288 /* Set up a secure umask - we'll set the proper one after login */
289 vsf_sysutil_set_umask(VSFTP_SECURE_UMASK
);
290 /* Fire up libc's timezone initialisation, before we chroot()! */
292 /* Signals. We'll always take -EPIPE rather than a rude signal, thanks */
293 vsf_sysutil_install_null_sighandler(kVSFSysUtilSigPIPE
);
297 session_init(struct vsf_session
* p_sess
)
299 /* Get the addresses of the control connection */
300 vsf_sysutil_getpeername(VSFTP_COMMAND_FD
, &p_sess
->p_remote_addr
);
301 vsf_sysutil_getsockname(VSFTP_COMMAND_FD
, &p_sess
->p_local_addr
);
302 /* If anonymous mode is active, fetch the uid of the anonymous user */
303 if (tunable_anonymous_enable
)
305 const struct vsf_sysutil_user
* p_user
=
306 vsf_sysutil_getpwnam(tunable_ftp_username
);
309 die2("vsftpd: cannot locate user specified in 'ftp_username':",
310 tunable_ftp_username
);
312 p_sess
->anon_ftp_uid
= vsf_sysutil_user_getuid(p_user
);
314 if (tunable_guest_enable
)
316 const struct vsf_sysutil_user
* p_user
=
317 vsf_sysutil_getpwnam(tunable_guest_username
);
320 die2("vsftpd: cannot locate user specified in 'guest_username':",
321 tunable_guest_username
);
323 p_sess
->guest_user_uid
= vsf_sysutil_user_getuid(p_user
);
325 if (tunable_chown_uploads
)
327 const struct vsf_sysutil_user
* p_user
=
328 vsf_sysutil_getpwnam(tunable_chown_username
);
331 die2("vsftpd: cannot locate user specified in 'chown_username':",
332 tunable_chown_username
);
334 p_sess
->anon_upload_chown_uid
= vsf_sysutil_user_getuid(p_user
);