mirror of https://github.com/mirror/busybox.git
tftpd: fix -u USER to work with chroot. Closes 5348
function old new delta tftpd_main 546 568 +22 tftp_protocol 1844 1839 -5 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>1_21_stable
parent
df8066a78c
commit
dbed6c4b46
|
@ -116,7 +116,7 @@ enum {
|
||||||
struct globals {
|
struct globals {
|
||||||
/* u16 TFTP_ERROR; u16 reason; both network-endian, then error text: */
|
/* u16 TFTP_ERROR; u16 reason; both network-endian, then error text: */
|
||||||
uint8_t error_pkt[4 + 32];
|
uint8_t error_pkt[4 + 32];
|
||||||
char *user_opt;
|
struct passwd *pw;
|
||||||
/* used in tftpd_main(), a bit big for stack: */
|
/* used in tftpd_main(), a bit big for stack: */
|
||||||
char block_buf[TFTP_BLKSIZE_DEFAULT];
|
char block_buf[TFTP_BLKSIZE_DEFAULT];
|
||||||
#if ENABLE_FEATURE_TFTP_PROGRESS_BAR
|
#if ENABLE_FEATURE_TFTP_PROGRESS_BAR
|
||||||
|
@ -130,13 +130,10 @@ struct globals {
|
||||||
struct BUG_G_too_big {
|
struct BUG_G_too_big {
|
||||||
char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
|
char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
|
||||||
};
|
};
|
||||||
#define block_buf (G.block_buf )
|
|
||||||
#define user_opt (G.user_opt )
|
|
||||||
#define error_pkt (G.error_pkt )
|
|
||||||
#define INIT_G() do { } while (0)
|
#define INIT_G() do { } while (0)
|
||||||
|
|
||||||
#define error_pkt_reason (error_pkt[3])
|
#define G_error_pkt_reason (G.error_pkt[3])
|
||||||
#define error_pkt_str (error_pkt + 4)
|
#define G_error_pkt_str ((char*)(G.error_pkt + 4))
|
||||||
|
|
||||||
#if ENABLE_FEATURE_TFTP_PROGRESS_BAR
|
#if ENABLE_FEATURE_TFTP_PROGRESS_BAR
|
||||||
static void tftp_progress_update(void)
|
static void tftp_progress_update(void)
|
||||||
|
@ -272,12 +269,11 @@ static int tftp_protocol(
|
||||||
xconnect(socket_fd, &peer_lsa->u.sa, peer_lsa->len);
|
xconnect(socket_fd, &peer_lsa->u.sa, peer_lsa->len);
|
||||||
|
|
||||||
/* Is there an error already? Send pkt and bail out */
|
/* Is there an error already? Send pkt and bail out */
|
||||||
if (error_pkt_reason || error_pkt_str[0])
|
if (G_error_pkt_reason || G_error_pkt_str[0])
|
||||||
goto send_err_pkt;
|
goto send_err_pkt;
|
||||||
|
|
||||||
if (user_opt) {
|
if (G.pw) {
|
||||||
struct passwd *pw = xgetpwnam(user_opt);
|
change_identity(G.pw); /* initgroups, setgid, setuid */
|
||||||
change_identity(pw); /* initgroups, setgid, setuid */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,8 +325,8 @@ static int tftp_protocol(
|
||||||
/* Open file (must be after changing user) */
|
/* Open file (must be after changing user) */
|
||||||
local_fd = open(local_file, open_mode, 0666);
|
local_fd = open(local_file, open_mode, 0666);
|
||||||
if (local_fd < 0) {
|
if (local_fd < 0) {
|
||||||
error_pkt_reason = ERR_NOFILE;
|
G_error_pkt_reason = ERR_NOFILE;
|
||||||
strcpy((char*)error_pkt_str, "can't open file");
|
strcpy(G_error_pkt_str, "can't open file");
|
||||||
goto send_err_pkt;
|
goto send_err_pkt;
|
||||||
}
|
}
|
||||||
/* gcc 4.3.1 would NOT optimize it out as it should! */
|
/* gcc 4.3.1 would NOT optimize it out as it should! */
|
||||||
|
@ -575,7 +571,7 @@ static int tftp_protocol(
|
||||||
if (res) {
|
if (res) {
|
||||||
blksize = tftp_blksize_check(res, blksize);
|
blksize = tftp_blksize_check(res, blksize);
|
||||||
if (blksize < 0) {
|
if (blksize < 0) {
|
||||||
error_pkt_reason = ERR_BAD_OPT;
|
G_error_pkt_reason = ERR_BAD_OPT;
|
||||||
goto send_err_pkt;
|
goto send_err_pkt;
|
||||||
}
|
}
|
||||||
io_bufsize = blksize + 4;
|
io_bufsize = blksize + 4;
|
||||||
|
@ -614,8 +610,8 @@ static int tftp_protocol(
|
||||||
if (recv_blk == block_nr) {
|
if (recv_blk == block_nr) {
|
||||||
int sz = full_write(local_fd, &rbuf[4], len - 4);
|
int sz = full_write(local_fd, &rbuf[4], len - 4);
|
||||||
if (sz != len - 4) {
|
if (sz != len - 4) {
|
||||||
strcpy((char*)error_pkt_str, bb_msg_write_error);
|
strcpy(G_error_pkt_str, bb_msg_write_error);
|
||||||
error_pkt_reason = ERR_WRITE;
|
G_error_pkt_reason = ERR_WRITE;
|
||||||
goto send_err_pkt;
|
goto send_err_pkt;
|
||||||
}
|
}
|
||||||
if (sz != blksize) {
|
if (sz != blksize) {
|
||||||
|
@ -664,12 +660,12 @@ static int tftp_protocol(
|
||||||
return finished == 0; /* returns 1 on failure */
|
return finished == 0; /* returns 1 on failure */
|
||||||
|
|
||||||
send_read_err_pkt:
|
send_read_err_pkt:
|
||||||
strcpy((char*)error_pkt_str, bb_msg_read_error);
|
strcpy(G_error_pkt_str, bb_msg_read_error);
|
||||||
send_err_pkt:
|
send_err_pkt:
|
||||||
if (error_pkt_str[0])
|
if (G_error_pkt_str[0])
|
||||||
bb_error_msg("%s", (char*)error_pkt_str);
|
bb_error_msg("%s", G_error_pkt_str);
|
||||||
error_pkt[1] = TFTP_ERROR;
|
G.error_pkt[1] = TFTP_ERROR;
|
||||||
xsendto(socket_fd, error_pkt, 4 + 1 + strlen((char*)error_pkt_str),
|
xsendto(socket_fd, G.error_pkt, 4 + 1 + strlen(G_error_pkt_str),
|
||||||
&peer_lsa->u.sa, peer_lsa->len);
|
&peer_lsa->u.sa, peer_lsa->len);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
#undef remote_file
|
#undef remote_file
|
||||||
|
@ -761,7 +757,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
|
||||||
{
|
{
|
||||||
len_and_sockaddr *our_lsa;
|
len_and_sockaddr *our_lsa;
|
||||||
len_and_sockaddr *peer_lsa;
|
len_and_sockaddr *peer_lsa;
|
||||||
char *local_file, *mode;
|
char *local_file, *mode, *user_opt;
|
||||||
const char *error_msg;
|
const char *error_msg;
|
||||||
int opt, result, opcode;
|
int opt, result, opcode;
|
||||||
IF_FEATURE_TFTP_BLOCKSIZE(int blksize = TFTP_BLKSIZE_DEFAULT;)
|
IF_FEATURE_TFTP_BLOCKSIZE(int blksize = TFTP_BLKSIZE_DEFAULT;)
|
||||||
|
@ -789,18 +785,22 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
|
||||||
openlog(applet_name, LOG_PID, LOG_DAEMON);
|
openlog(applet_name, LOG_PID, LOG_DAEMON);
|
||||||
logmode = LOGMODE_SYSLOG;
|
logmode = LOGMODE_SYSLOG;
|
||||||
}
|
}
|
||||||
|
if (opt & TFTPD_OPT_u) {
|
||||||
|
/* Must be before xchroot */
|
||||||
|
G.pw = xgetpwnam(user_opt);
|
||||||
|
}
|
||||||
if (argv[0]) {
|
if (argv[0]) {
|
||||||
xchroot(argv[0]);
|
xchroot(argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = recv_from_to(STDIN_FILENO, block_buf, sizeof(block_buf),
|
result = recv_from_to(STDIN_FILENO, G.block_buf, sizeof(G.block_buf),
|
||||||
0 /* flags */,
|
0 /* flags */,
|
||||||
&peer_lsa->u.sa, &our_lsa->u.sa, our_lsa->len);
|
&peer_lsa->u.sa, &our_lsa->u.sa, our_lsa->len);
|
||||||
|
|
||||||
error_msg = "malformed packet";
|
error_msg = "malformed packet";
|
||||||
opcode = ntohs(*(uint16_t*)block_buf);
|
opcode = ntohs(*(uint16_t*)G.block_buf);
|
||||||
if (result < 4 || result >= sizeof(block_buf)
|
if (result < 4 || result >= sizeof(G.block_buf)
|
||||||
|| block_buf[result-1] != '\0'
|
|| G.block_buf[result-1] != '\0'
|
||||||
|| (IF_FEATURE_TFTP_PUT(opcode != TFTP_RRQ) /* not download */
|
|| (IF_FEATURE_TFTP_PUT(opcode != TFTP_RRQ) /* not download */
|
||||||
IF_GETPUT(&&)
|
IF_GETPUT(&&)
|
||||||
IF_FEATURE_TFTP_GET(opcode != TFTP_WRQ) /* not upload */
|
IF_FEATURE_TFTP_GET(opcode != TFTP_WRQ) /* not upload */
|
||||||
|
@ -808,27 +808,27 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
|
||||||
) {
|
) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
local_file = block_buf + 2;
|
local_file = G.block_buf + 2;
|
||||||
if (local_file[0] == '.' || strstr(local_file, "/.")) {
|
if (local_file[0] == '.' || strstr(local_file, "/.")) {
|
||||||
error_msg = "dot in file name";
|
error_msg = "dot in file name";
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
mode = local_file + strlen(local_file) + 1;
|
mode = local_file + strlen(local_file) + 1;
|
||||||
/* RFC 1350 says mode string is case independent */
|
/* RFC 1350 says mode string is case independent */
|
||||||
if (mode >= block_buf + result || strcasecmp(mode, "octet") != 0) {
|
if (mode >= G.block_buf + result || strcasecmp(mode, "octet") != 0) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
# if ENABLE_FEATURE_TFTP_BLOCKSIZE
|
# if ENABLE_FEATURE_TFTP_BLOCKSIZE
|
||||||
{
|
{
|
||||||
char *res;
|
char *res;
|
||||||
char *opt_str = mode + sizeof("octet");
|
char *opt_str = mode + sizeof("octet");
|
||||||
int opt_len = block_buf + result - opt_str;
|
int opt_len = G.block_buf + result - opt_str;
|
||||||
if (opt_len > 0) {
|
if (opt_len > 0) {
|
||||||
res = tftp_get_option("blksize", opt_str, opt_len);
|
res = tftp_get_option("blksize", opt_str, opt_len);
|
||||||
if (res) {
|
if (res) {
|
||||||
blksize = tftp_blksize_check(res, 65564);
|
blksize = tftp_blksize_check(res, 65564);
|
||||||
if (blksize < 0) {
|
if (blksize < 0) {
|
||||||
error_pkt_reason = ERR_BAD_OPT;
|
G_error_pkt_reason = ERR_BAD_OPT;
|
||||||
/* will just send error pkt */
|
/* will just send error pkt */
|
||||||
goto do_proto;
|
goto do_proto;
|
||||||
}
|
}
|
||||||
|
@ -846,7 +846,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
|
||||||
if (!ENABLE_FEATURE_TFTP_PUT || opcode == TFTP_WRQ) {
|
if (!ENABLE_FEATURE_TFTP_PUT || opcode == TFTP_WRQ) {
|
||||||
if (opt & TFTPD_OPT_r) {
|
if (opt & TFTPD_OPT_r) {
|
||||||
/* This would mean "disk full" - not true */
|
/* This would mean "disk full" - not true */
|
||||||
/*error_pkt_reason = ERR_WRITE;*/
|
/*G_error_pkt_reason = ERR_WRITE;*/
|
||||||
error_msg = bb_msg_write_error;
|
error_msg = bb_msg_write_error;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -855,7 +855,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
|
||||||
IF_GETPUT(option_mask32 |= TFTP_OPT_PUT;) /* will send file's data */
|
IF_GETPUT(option_mask32 |= TFTP_OPT_PUT;) /* will send file's data */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NB: if error_pkt_str or error_pkt_reason is set up,
|
/* NB: if G_error_pkt_str or G_error_pkt_reason is set up,
|
||||||
* tftp_protocol() just sends one error pkt and returns */
|
* tftp_protocol() just sends one error pkt and returns */
|
||||||
|
|
||||||
do_proto:
|
do_proto:
|
||||||
|
@ -870,7 +870,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
err:
|
err:
|
||||||
strcpy((char*)error_pkt_str, error_msg);
|
strcpy(G_error_pkt_str, error_msg);
|
||||||
goto do_proto;
|
goto do_proto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue