diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2012-07-18 17:32:32 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2012-07-18 17:32:32 +0200 |
| commit | dbed6c4b46f3c8dc74d50e4cf35b1cb8b8c4ff2d (patch) | |
| tree | 70daedb8c72e42362807bb0ff6dfa8953b3f130c | |
| parent | df8066a78ccd9b899244145f6be0171957a41a1e (diff) | |
| download | busybox-w32-dbed6c4b46f3c8dc74d50e4cf35b1cb8b8c4ff2d.tar.gz busybox-w32-dbed6c4b46f3c8dc74d50e4cf35b1cb8b8c4ff2d.tar.bz2 busybox-w32-dbed6c4b46f3c8dc74d50e4cf35b1cb8b8c4ff2d.zip | |
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>
| -rw-r--r-- | networking/tftp.c | 64 |
1 files changed, 32 insertions, 32 deletions
diff --git a/networking/tftp.c b/networking/tftp.c index ce48a1edd..630fdaf9a 100644 --- a/networking/tftp.c +++ b/networking/tftp.c | |||
| @@ -116,7 +116,7 @@ enum { | |||
| 116 | struct globals { | 116 | struct globals { |
| 117 | /* u16 TFTP_ERROR; u16 reason; both network-endian, then error text: */ | 117 | /* u16 TFTP_ERROR; u16 reason; both network-endian, then error text: */ |
| 118 | uint8_t error_pkt[4 + 32]; | 118 | uint8_t error_pkt[4 + 32]; |
| 119 | char *user_opt; | 119 | struct passwd *pw; |
| 120 | /* used in tftpd_main(), a bit big for stack: */ | 120 | /* used in tftpd_main(), a bit big for stack: */ |
| 121 | char block_buf[TFTP_BLKSIZE_DEFAULT]; | 121 | char block_buf[TFTP_BLKSIZE_DEFAULT]; |
| 122 | #if ENABLE_FEATURE_TFTP_PROGRESS_BAR | 122 | #if ENABLE_FEATURE_TFTP_PROGRESS_BAR |
| @@ -130,13 +130,10 @@ struct globals { | |||
| 130 | struct BUG_G_too_big { | 130 | struct BUG_G_too_big { |
| 131 | char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; | 131 | char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; |
| 132 | }; | 132 | }; |
| 133 | #define block_buf (G.block_buf ) | ||
| 134 | #define user_opt (G.user_opt ) | ||
| 135 | #define error_pkt (G.error_pkt ) | ||
| 136 | #define INIT_G() do { } while (0) | 133 | #define INIT_G() do { } while (0) |
| 137 | 134 | ||
| 138 | #define error_pkt_reason (error_pkt[3]) | 135 | #define G_error_pkt_reason (G.error_pkt[3]) |
| 139 | #define error_pkt_str (error_pkt + 4) | 136 | #define G_error_pkt_str ((char*)(G.error_pkt + 4)) |
| 140 | 137 | ||
| 141 | #if ENABLE_FEATURE_TFTP_PROGRESS_BAR | 138 | #if ENABLE_FEATURE_TFTP_PROGRESS_BAR |
| 142 | static void tftp_progress_update(void) | 139 | static void tftp_progress_update(void) |
| @@ -272,12 +269,11 @@ static int tftp_protocol( | |||
| 272 | xconnect(socket_fd, &peer_lsa->u.sa, peer_lsa->len); | 269 | xconnect(socket_fd, &peer_lsa->u.sa, peer_lsa->len); |
| 273 | 270 | ||
| 274 | /* Is there an error already? Send pkt and bail out */ | 271 | /* Is there an error already? Send pkt and bail out */ |
| 275 | if (error_pkt_reason || error_pkt_str[0]) | 272 | if (G_error_pkt_reason || G_error_pkt_str[0]) |
| 276 | goto send_err_pkt; | 273 | goto send_err_pkt; |
| 277 | 274 | ||
| 278 | if (user_opt) { | 275 | if (G.pw) { |
| 279 | struct passwd *pw = xgetpwnam(user_opt); | 276 | change_identity(G.pw); /* initgroups, setgid, setuid */ |
| 280 | change_identity(pw); /* initgroups, setgid, setuid */ | ||
| 281 | } | 277 | } |
| 282 | } | 278 | } |
| 283 | 279 | ||
| @@ -329,8 +325,8 @@ static int tftp_protocol( | |||
| 329 | /* Open file (must be after changing user) */ | 325 | /* Open file (must be after changing user) */ |
| 330 | local_fd = open(local_file, open_mode, 0666); | 326 | local_fd = open(local_file, open_mode, 0666); |
| 331 | if (local_fd < 0) { | 327 | if (local_fd < 0) { |
| 332 | error_pkt_reason = ERR_NOFILE; | 328 | G_error_pkt_reason = ERR_NOFILE; |
| 333 | strcpy((char*)error_pkt_str, "can't open file"); | 329 | strcpy(G_error_pkt_str, "can't open file"); |
| 334 | goto send_err_pkt; | 330 | goto send_err_pkt; |
| 335 | } | 331 | } |
| 336 | /* gcc 4.3.1 would NOT optimize it out as it should! */ | 332 | /* gcc 4.3.1 would NOT optimize it out as it should! */ |
| @@ -575,7 +571,7 @@ static int tftp_protocol( | |||
| 575 | if (res) { | 571 | if (res) { |
| 576 | blksize = tftp_blksize_check(res, blksize); | 572 | blksize = tftp_blksize_check(res, blksize); |
| 577 | if (blksize < 0) { | 573 | if (blksize < 0) { |
| 578 | error_pkt_reason = ERR_BAD_OPT; | 574 | G_error_pkt_reason = ERR_BAD_OPT; |
| 579 | goto send_err_pkt; | 575 | goto send_err_pkt; |
| 580 | } | 576 | } |
| 581 | io_bufsize = blksize + 4; | 577 | io_bufsize = blksize + 4; |
| @@ -614,8 +610,8 @@ static int tftp_protocol( | |||
| 614 | if (recv_blk == block_nr) { | 610 | if (recv_blk == block_nr) { |
| 615 | int sz = full_write(local_fd, &rbuf[4], len - 4); | 611 | int sz = full_write(local_fd, &rbuf[4], len - 4); |
| 616 | if (sz != len - 4) { | 612 | if (sz != len - 4) { |
| 617 | strcpy((char*)error_pkt_str, bb_msg_write_error); | 613 | strcpy(G_error_pkt_str, bb_msg_write_error); |
| 618 | error_pkt_reason = ERR_WRITE; | 614 | G_error_pkt_reason = ERR_WRITE; |
| 619 | goto send_err_pkt; | 615 | goto send_err_pkt; |
| 620 | } | 616 | } |
| 621 | if (sz != blksize) { | 617 | if (sz != blksize) { |
| @@ -664,12 +660,12 @@ static int tftp_protocol( | |||
| 664 | return finished == 0; /* returns 1 on failure */ | 660 | return finished == 0; /* returns 1 on failure */ |
| 665 | 661 | ||
| 666 | send_read_err_pkt: | 662 | send_read_err_pkt: |
| 667 | strcpy((char*)error_pkt_str, bb_msg_read_error); | 663 | strcpy(G_error_pkt_str, bb_msg_read_error); |
| 668 | send_err_pkt: | 664 | send_err_pkt: |
| 669 | if (error_pkt_str[0]) | 665 | if (G_error_pkt_str[0]) |
| 670 | bb_error_msg("%s", (char*)error_pkt_str); | 666 | bb_error_msg("%s", G_error_pkt_str); |
| 671 | error_pkt[1] = TFTP_ERROR; | 667 | G.error_pkt[1] = TFTP_ERROR; |
| 672 | xsendto(socket_fd, error_pkt, 4 + 1 + strlen((char*)error_pkt_str), | 668 | xsendto(socket_fd, G.error_pkt, 4 + 1 + strlen(G_error_pkt_str), |
| 673 | &peer_lsa->u.sa, peer_lsa->len); | 669 | &peer_lsa->u.sa, peer_lsa->len); |
| 674 | return EXIT_FAILURE; | 670 | return EXIT_FAILURE; |
| 675 | #undef remote_file | 671 | #undef remote_file |
| @@ -761,7 +757,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) | |||
| 761 | { | 757 | { |
| 762 | len_and_sockaddr *our_lsa; | 758 | len_and_sockaddr *our_lsa; |
| 763 | len_and_sockaddr *peer_lsa; | 759 | len_and_sockaddr *peer_lsa; |
| 764 | char *local_file, *mode; | 760 | char *local_file, *mode, *user_opt; |
| 765 | const char *error_msg; | 761 | const char *error_msg; |
| 766 | int opt, result, opcode; | 762 | int opt, result, opcode; |
| 767 | IF_FEATURE_TFTP_BLOCKSIZE(int blksize = TFTP_BLKSIZE_DEFAULT;) | 763 | IF_FEATURE_TFTP_BLOCKSIZE(int blksize = TFTP_BLKSIZE_DEFAULT;) |
| @@ -789,18 +785,22 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) | |||
| 789 | openlog(applet_name, LOG_PID, LOG_DAEMON); | 785 | openlog(applet_name, LOG_PID, LOG_DAEMON); |
| 790 | logmode = LOGMODE_SYSLOG; | 786 | logmode = LOGMODE_SYSLOG; |
| 791 | } | 787 | } |
| 788 | if (opt & TFTPD_OPT_u) { | ||
| 789 | /* Must be before xchroot */ | ||
| 790 | G.pw = xgetpwnam(user_opt); | ||
| 791 | } | ||
| 792 | if (argv[0]) { | 792 | if (argv[0]) { |
| 793 | xchroot(argv[0]); | 793 | xchroot(argv[0]); |
| 794 | } | 794 | } |
| 795 | 795 | ||
| 796 | result = recv_from_to(STDIN_FILENO, block_buf, sizeof(block_buf), | 796 | result = recv_from_to(STDIN_FILENO, G.block_buf, sizeof(G.block_buf), |
| 797 | 0 /* flags */, | 797 | 0 /* flags */, |
| 798 | &peer_lsa->u.sa, &our_lsa->u.sa, our_lsa->len); | 798 | &peer_lsa->u.sa, &our_lsa->u.sa, our_lsa->len); |
| 799 | 799 | ||
| 800 | error_msg = "malformed packet"; | 800 | error_msg = "malformed packet"; |
| 801 | opcode = ntohs(*(uint16_t*)block_buf); | 801 | opcode = ntohs(*(uint16_t*)G.block_buf); |
| 802 | if (result < 4 || result >= sizeof(block_buf) | 802 | if (result < 4 || result >= sizeof(G.block_buf) |
| 803 | || block_buf[result-1] != '\0' | 803 | || G.block_buf[result-1] != '\0' |
| 804 | || (IF_FEATURE_TFTP_PUT(opcode != TFTP_RRQ) /* not download */ | 804 | || (IF_FEATURE_TFTP_PUT(opcode != TFTP_RRQ) /* not download */ |
| 805 | IF_GETPUT(&&) | 805 | IF_GETPUT(&&) |
| 806 | IF_FEATURE_TFTP_GET(opcode != TFTP_WRQ) /* not upload */ | 806 | IF_FEATURE_TFTP_GET(opcode != TFTP_WRQ) /* not upload */ |
| @@ -808,27 +808,27 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) | |||
| 808 | ) { | 808 | ) { |
| 809 | goto err; | 809 | goto err; |
| 810 | } | 810 | } |
| 811 | local_file = block_buf + 2; | 811 | local_file = G.block_buf + 2; |
| 812 | if (local_file[0] == '.' || strstr(local_file, "/.")) { | 812 | if (local_file[0] == '.' || strstr(local_file, "/.")) { |
| 813 | error_msg = "dot in file name"; | 813 | error_msg = "dot in file name"; |
| 814 | goto err; | 814 | goto err; |
| 815 | } | 815 | } |
| 816 | mode = local_file + strlen(local_file) + 1; | 816 | mode = local_file + strlen(local_file) + 1; |
| 817 | /* RFC 1350 says mode string is case independent */ | 817 | /* RFC 1350 says mode string is case independent */ |
| 818 | if (mode >= block_buf + result || strcasecmp(mode, "octet") != 0) { | 818 | if (mode >= G.block_buf + result || strcasecmp(mode, "octet") != 0) { |
| 819 | goto err; | 819 | goto err; |
| 820 | } | 820 | } |
| 821 | # if ENABLE_FEATURE_TFTP_BLOCKSIZE | 821 | # if ENABLE_FEATURE_TFTP_BLOCKSIZE |
| 822 | { | 822 | { |
| 823 | char *res; | 823 | char *res; |
| 824 | char *opt_str = mode + sizeof("octet"); | 824 | char *opt_str = mode + sizeof("octet"); |
| 825 | int opt_len = block_buf + result - opt_str; | 825 | int opt_len = G.block_buf + result - opt_str; |
| 826 | if (opt_len > 0) { | 826 | if (opt_len > 0) { |
| 827 | res = tftp_get_option("blksize", opt_str, opt_len); | 827 | res = tftp_get_option("blksize", opt_str, opt_len); |
| 828 | if (res) { | 828 | if (res) { |
| 829 | blksize = tftp_blksize_check(res, 65564); | 829 | blksize = tftp_blksize_check(res, 65564); |
| 830 | if (blksize < 0) { | 830 | if (blksize < 0) { |
| 831 | error_pkt_reason = ERR_BAD_OPT; | 831 | G_error_pkt_reason = ERR_BAD_OPT; |
| 832 | /* will just send error pkt */ | 832 | /* will just send error pkt */ |
| 833 | goto do_proto; | 833 | goto do_proto; |
| 834 | } | 834 | } |
| @@ -846,7 +846,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) | |||
| 846 | if (!ENABLE_FEATURE_TFTP_PUT || opcode == TFTP_WRQ) { | 846 | if (!ENABLE_FEATURE_TFTP_PUT || opcode == TFTP_WRQ) { |
| 847 | if (opt & TFTPD_OPT_r) { | 847 | if (opt & TFTPD_OPT_r) { |
| 848 | /* This would mean "disk full" - not true */ | 848 | /* This would mean "disk full" - not true */ |
| 849 | /*error_pkt_reason = ERR_WRITE;*/ | 849 | /*G_error_pkt_reason = ERR_WRITE;*/ |
| 850 | error_msg = bb_msg_write_error; | 850 | error_msg = bb_msg_write_error; |
| 851 | goto err; | 851 | goto err; |
| 852 | } | 852 | } |
| @@ -855,7 +855,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) | |||
| 855 | IF_GETPUT(option_mask32 |= TFTP_OPT_PUT;) /* will send file's data */ | 855 | IF_GETPUT(option_mask32 |= TFTP_OPT_PUT;) /* will send file's data */ |
| 856 | } | 856 | } |
| 857 | 857 | ||
| 858 | /* NB: if error_pkt_str or error_pkt_reason is set up, | 858 | /* NB: if G_error_pkt_str or G_error_pkt_reason is set up, |
| 859 | * tftp_protocol() just sends one error pkt and returns */ | 859 | * tftp_protocol() just sends one error pkt and returns */ |
| 860 | 860 | ||
| 861 | do_proto: | 861 | do_proto: |
| @@ -870,7 +870,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) | |||
| 870 | 870 | ||
| 871 | return result; | 871 | return result; |
| 872 | err: | 872 | err: |
| 873 | strcpy((char*)error_pkt_str, error_msg); | 873 | strcpy(G_error_pkt_str, error_msg); |
| 874 | goto do_proto; | 874 | goto do_proto; |
| 875 | } | 875 | } |
| 876 | 876 | ||
