tftpd: make open() check r/w permissions instead of doing it ourself.
Add -r "prohibit upload" opt for those lazy people who run tftpd as root. -40 bytes.
This commit is contained in:
parent
78c5656530
commit
d7e6af2dda
@ -3977,9 +3977,11 @@
|
|||||||
)
|
)
|
||||||
|
|
||||||
#define tftpd_trivial_usage \
|
#define tftpd_trivial_usage \
|
||||||
"[DIR]"
|
"[-r] [DIR]"
|
||||||
#define tftpd_full_usage \
|
#define tftpd_full_usage \
|
||||||
"Transfer a file on request from a tftp client" \
|
"Transfer a file on request from a tftp client.\n" \
|
||||||
|
"\nOptions:" \
|
||||||
|
"\n -r Prohibit upload" \
|
||||||
|
|
||||||
#define time_trivial_usage \
|
#define time_trivial_usage \
|
||||||
"[OPTION]... COMMAND [ARGS...]"
|
"[OPTION]... COMMAND [ARGS...]"
|
||||||
|
@ -56,6 +56,8 @@
|
|||||||
* CMD_GET(cmd) and CMD_PUT(cmd) are mutually exclusive
|
* CMD_GET(cmd) and CMD_PUT(cmd) are mutually exclusive
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// TODO: emit error packets before dying
|
||||||
|
|
||||||
|
|
||||||
#if ENABLE_FEATURE_TFTP_BLOCKSIZE
|
#if ENABLE_FEATURE_TFTP_BLOCKSIZE
|
||||||
|
|
||||||
@ -340,7 +342,7 @@ static int tftp_protocol(
|
|||||||
|
|
||||||
const char *msg = "";
|
const char *msg = "";
|
||||||
|
|
||||||
if (rbuf[4] != '\0') {
|
if (len > 4 && rbuf[4] != '\0') {
|
||||||
msg = &rbuf[4];
|
msg = &rbuf[4];
|
||||||
rbuf[tftp_bufsize - 1] = '\0';
|
rbuf[tftp_bufsize - 1] = '\0';
|
||||||
} else if (recv_blk < ARRAY_SIZE(errcode_str)) {
|
} else if (recv_blk < ARRAY_SIZE(errcode_str)) {
|
||||||
@ -533,14 +535,14 @@ static len_and_sockaddr *get_sock_lsa(int s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int tftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
int tftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||||
int tftpd_main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
|
int tftpd_main(int argc ATTRIBUTE_UNUSED, char **argv)
|
||||||
{
|
{
|
||||||
struct stat statbuf;
|
|
||||||
char block_buf[TFTP_BLOCKSIZE_DEFAULT];
|
char block_buf[TFTP_BLOCKSIZE_DEFAULT];
|
||||||
len_and_sockaddr *our_lsa;
|
len_and_sockaddr *our_lsa;
|
||||||
len_and_sockaddr *peer_lsa;
|
len_and_sockaddr *peer_lsa;
|
||||||
char *filename, *mode, *opt_str;
|
char *filename, *mode, *opt_str;
|
||||||
int result, opcode, cmd, req_modebits, open_mode, local_fd, blksize;
|
int opt_r, result, opcode, open_mode, local_fd, blksize;
|
||||||
|
USE_GETPUT(int cmd;)
|
||||||
|
|
||||||
our_lsa = get_sock_lsa(STDIN_FILENO);
|
our_lsa = get_sock_lsa(STDIN_FILENO);
|
||||||
if (!our_lsa)
|
if (!our_lsa)
|
||||||
@ -548,8 +550,10 @@ int tftpd_main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
|
|||||||
peer_lsa = xzalloc(LSA_LEN_SIZE + our_lsa->len);
|
peer_lsa = xzalloc(LSA_LEN_SIZE + our_lsa->len);
|
||||||
peer_lsa->len = our_lsa->len;
|
peer_lsa->len = our_lsa->len;
|
||||||
|
|
||||||
if (argv[1])
|
opt_r = getopt32(argv, "r");
|
||||||
xchdir(argv[1]);
|
argv += optind;
|
||||||
|
if (argv[0])
|
||||||
|
xchdir(argv[0]);
|
||||||
|
|
||||||
result = recv_from_to(STDIN_FILENO, block_buf, sizeof(block_buf),
|
result = recv_from_to(STDIN_FILENO, block_buf, sizeof(block_buf),
|
||||||
0 /* flags */,
|
0 /* flags */,
|
||||||
@ -558,7 +562,10 @@ int tftpd_main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
|
|||||||
opcode = ntohs(*(uint16_t*)block_buf);
|
opcode = ntohs(*(uint16_t*)block_buf);
|
||||||
if (result < 4 || result >= sizeof(block_buf)
|
if (result < 4 || result >= sizeof(block_buf)
|
||||||
|| block_buf[result-1] != '\0'
|
|| block_buf[result-1] != '\0'
|
||||||
|| (opcode != TFTP_RRQ && opcode != TFTP_WRQ)
|
|| (USE_FEATURE_TFTP_GET(opcode != TFTP_RRQ) /* not download */
|
||||||
|
USE_GETPUT(&&)
|
||||||
|
USE_FEATURE_TFTP_GET(opcode != TFTP_WRQ) /* not upload */
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
bb_error_msg_and_die("malformed packet");
|
bb_error_msg_and_die("malformed packet");
|
||||||
}
|
}
|
||||||
@ -584,21 +591,20 @@ int tftpd_main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
xstat(filename, &statbuf);
|
|
||||||
/* if opcode == TFTP_WRQ: */
|
#if ENABLE_FEATURE_TFTP_PUT
|
||||||
cmd = 1; /* CMD_GET: we will receive file's data */
|
/* in case opcode is TFTP_RRQ: */
|
||||||
req_modebits = 0222; /* writable by anyone */
|
USE_GETPUT(cmd = 2;) /* CMD_PUT: we will send file's data */
|
||||||
open_mode = O_WRONLY | O_TRUNC;
|
open_mode = O_RDONLY;
|
||||||
if (opcode == TFTP_RRQ) {
|
#endif
|
||||||
cmd = 2; /* CMD_PUT */
|
#if ENABLE_FEATURE_TFTP_GET
|
||||||
req_modebits = 0444; /* readable by anyone */
|
if (!ENABLE_FEATURE_TFTP_PUT || opcode == TFTP_WRQ) {
|
||||||
open_mode = O_RDONLY;
|
if (opt_r)
|
||||||
}
|
bb_error_msg_and_die("upload is prohibited");
|
||||||
if (!S_ISREG(statbuf.st_mode)
|
USE_GETPUT(cmd = 1;) /* CMD_GET: we will receive file's data */
|
||||||
|| (statbuf.st_mode & req_modebits) != req_modebits
|
open_mode = O_WRONLY | O_TRUNC;
|
||||||
) {
|
|
||||||
bb_error_msg_and_die("access to '%s' is denied", filename);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
local_fd = xopen(filename, open_mode);
|
local_fd = xopen(filename, open_mode);
|
||||||
|
|
||||||
close(STDIN_FILENO); /* close old, possibly wildcard socket */
|
close(STDIN_FILENO); /* close old, possibly wildcard socket */
|
||||||
|
Loading…
Reference in New Issue
Block a user