return remote_fd;
}
- setsockopt(remote_fd, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));
+ setsockopt_keepalive(remote_fd);
return remote_fd;
}
pid_t pid;
argv[0] = "ftpd";
- argv[1] = opt; /* "-l" or "-1" */
+ argv[1] = opt; /* "-lA" or "-1A" */
argv[2] = "--";
argv[3] = G.ftp_arg;
argv[4] = NULL;
if (!(opts & USE_CTRL_CONN) && !port_or_pasv_was_seen())
return; /* port_or_pasv_was_seen emitted error response */
- ls_fd = popen_ls((opts & LONG_LISTING) ? "-l" : "-1");
+ ls_fd = popen_ls((opts & LONG_LISTING) ? "-lA" : "-1A");
ls_fp = xfdopen_for_read(ls_fd);
/* FIXME: filenames with embedded newlines are mishandled */
#if !BB_MMU
OPT_l = (1 << 0),
OPT_1 = (1 << 1),
+ OPT_A = (1 << 2),
#endif
- OPT_v = (1 << ((!BB_MMU) * 2 + 0)),
- OPT_S = (1 << ((!BB_MMU) * 2 + 1)),
- OPT_w = (1 << ((!BB_MMU) * 2 + 2)) * ENABLE_FEATURE_FTP_WRITE,
+ OPT_v = (1 << ((!BB_MMU) * 3 + 0)),
+ OPT_S = (1 << ((!BB_MMU) * 3 + 1)),
+ OPT_w = (1 << ((!BB_MMU) * 3 + 2)) * ENABLE_FEATURE_FTP_WRITE,
};
int ftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int ftpd_main(int argc UNUSED_PARAM, char **argv)
#endif
{
+#if ENABLE_FEATURE_FTP_AUTHENTICATION
+ struct passwd *pw = NULL;
+#endif
unsigned abs_timeout;
unsigned verbose_S;
smallint opts;
G.timeout = 2 * 60;
opt_complementary = "t+:T+:vv:SS";
#if BB_MMU
- opts = getopt32(argv, "vS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S);
+ opts = getopt32(argv, "vS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S);
#else
- opts = getopt32(argv, "l1vS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S);
+ opts = getopt32(argv, "l1AvS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S);
if (opts & (OPT_l|OPT_1)) {
/* Our secret backdoor to ls */
-/* TODO: pass -A? It shows dot files */
/* TODO: pass --group-directories-first? would be nice, but ls doesn't do that yet */
if (fchdir(3) != 0)
_exit(127);
//umask(077); - admin can set umask before starting us
- /* Signals. We'll always take -EPIPE rather than a rude signal, thanks */
- signal(SIGPIPE, SIG_IGN);
+ /* Signals */
+ bb_signals(0
+ /* We'll always take EPIPE rather than a rude signal, thanks */
+ + (1 << SIGPIPE)
+ /* LIST command spawns chilren. Prevent zombies */
+ + (1 << SIGCHLD)
+ , SIG_IGN);
/* Set up options on the command socket (do we need these all? why?) */
- setsockopt(STDIN_FILENO, IPPROTO_TCP, TCP_NODELAY, &const_int_1, sizeof(const_int_1));
- setsockopt(STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));
+ setsockopt_1(STDIN_FILENO, IPPROTO_TCP, TCP_NODELAY);
+ setsockopt_keepalive(STDIN_FILENO);
/* Telnet protocol over command link may send "urgent" data,
* we prefer it to be received in the "normal" data stream: */
- setsockopt(STDIN_FILENO, SOL_SOCKET, SO_OOBINLINE, &const_int_1, sizeof(const_int_1));
+ setsockopt_1(STDIN_FILENO, SOL_SOCKET, SO_OOBINLINE);
WRITE_OK(FTP_GREET);
signal(SIGALRM, timeout_handler);
#if ENABLE_FEATURE_FTP_AUTHENTICATION
- {
- struct passwd *pw = NULL;
-
- while (1) {
- uint32_t cmdval = cmdio_get_cmd_and_arg();
-
+ while (1) {
+ uint32_t cmdval = cmdio_get_cmd_and_arg();
if (cmdval == const_USER) {
- pw = getpwnam(G.ftp_arg);
- cmdio_write_raw(STR(FTP_GIVEPWORD)" Please specify password\r\n");
- } else if (cmdval == const_PASS) {
- if (check_password(pw, G.ftp_arg) > 0) {
- break; /* login success */
- }
- cmdio_write_raw(STR(FTP_LOGINERR)" Login failed\r\n");
- pw = NULL;
- } else if (cmdval == const_QUIT) {
- WRITE_OK(FTP_GOODBYE);
- return 0;
- } else {
- cmdio_write_raw(STR(FTP_LOGINERR)" Login with USER and PASS\r\n");
+ pw = getpwnam(G.ftp_arg);
+ cmdio_write_raw(STR(FTP_GIVEPWORD)" Please specify password\r\n");
+ } else if (cmdval == const_PASS) {
+ if (check_password(pw, G.ftp_arg) > 0) {
+ break; /* login success */
}
+ cmdio_write_raw(STR(FTP_LOGINERR)" Login failed\r\n");
+ pw = NULL;
+ } else if (cmdval == const_QUIT) {
+ WRITE_OK(FTP_GOODBYE);
+ return 0;
+ } else {
+ cmdio_write_raw(STR(FTP_LOGINERR)" Login with USER and PASS\r\n");
}
- change_identity(pw);
}
WRITE_OK(FTP_LOGINOK);
#endif
#endif
argv += optind;
if (argv[0]) {
+ const char *basedir = argv[0];
#if !BB_MMU
G.root_fd = xopen("/", O_RDONLY | O_DIRECTORY);
close_on_exec_on(G.root_fd);
#endif
- xchroot(argv[0]);
+ if (chroot(basedir) == 0)
+ basedir = "/";
+#if !BB_MMU
+ else {
+ close(G.root_fd);
+ G.root_fd = -1;
+ }
+#endif
+ /*
+ * If chroot failed, assume that we aren't root,
+ * and at least chdir to the specified DIR
+ * (older versions were dying with error message).
+ * If chroot worked, move current dir to new "/":
+ */
+ xchdir(basedir);
}
+#if ENABLE_FEATURE_FTP_AUTHENTICATION
+ change_identity(pw);
+#endif
+
/* RFC-959 Section 5.1
* The following commands and options MUST be supported by every
* server-FTP and user-FTP, except in cases where the underlying