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 | ||