aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2012-07-18 17:32:32 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2012-07-18 17:32:32 +0200
commitdbed6c4b46f3c8dc74d50e4cf35b1cb8b8c4ff2d (patch)
tree70daedb8c72e42362807bb0ff6dfa8953b3f130c
parentdf8066a78ccd9b899244145f6be0171957a41a1e (diff)
downloadbusybox-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.c64
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 {
116struct globals { 116struct 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 {
130struct BUG_G_too_big { 130struct 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
142static void tftp_progress_update(void) 139static 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