aboutsummaryrefslogtreecommitdiff
path: root/networking/tftp.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-03-18 01:13:11 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-03-18 01:13:11 +0000
commitd7e6af2dda0abdd7a0411af46314724bd5f88549 (patch)
treee77291fb6fcb2d93c9c6ec60e21ddfe8bea5dc64 /networking/tftp.c
parent78c565653005192c4587fce1ccac6c441cea7ca6 (diff)
downloadbusybox-w32-d7e6af2dda0abdd7a0411af46314724bd5f88549.tar.gz
busybox-w32-d7e6af2dda0abdd7a0411af46314724bd5f88549.tar.bz2
busybox-w32-d7e6af2dda0abdd7a0411af46314724bd5f88549.zip
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.
Diffstat (limited to 'networking/tftp.c')
-rw-r--r--networking/tftp.c48
1 files changed, 27 insertions, 21 deletions
diff --git a/networking/tftp.c b/networking/tftp.c
index 25001c22c..3075ab04b 100644
--- a/networking/tftp.c
+++ b/networking/tftp.c
@@ -56,6 +56,8 @@
56 * CMD_GET(cmd) and CMD_PUT(cmd) are mutually exclusive 56 * CMD_GET(cmd) and CMD_PUT(cmd) are mutually exclusive
57 */ 57 */
58 58
59// TODO: emit error packets before dying
60
59 61
60#if ENABLE_FEATURE_TFTP_BLOCKSIZE 62#if ENABLE_FEATURE_TFTP_BLOCKSIZE
61 63
@@ -340,7 +342,7 @@ static int tftp_protocol(
340 342
341 const char *msg = ""; 343 const char *msg = "";
342 344
343 if (rbuf[4] != '\0') { 345 if (len > 4 && rbuf[4] != '\0') {
344 msg = &rbuf[4]; 346 msg = &rbuf[4];
345 rbuf[tftp_bufsize - 1] = '\0'; 347 rbuf[tftp_bufsize - 1] = '\0';
346 } else if (recv_blk < ARRAY_SIZE(errcode_str)) { 348 } else if (recv_blk < ARRAY_SIZE(errcode_str)) {
@@ -533,14 +535,14 @@ static len_and_sockaddr *get_sock_lsa(int s)
533} 535}
534 536
535int tftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 537int tftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
536int tftpd_main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) 538int tftpd_main(int argc ATTRIBUTE_UNUSED, char **argv)
537{ 539{
538 struct stat statbuf;
539 char block_buf[TFTP_BLOCKSIZE_DEFAULT]; 540 char block_buf[TFTP_BLOCKSIZE_DEFAULT];
540 len_and_sockaddr *our_lsa; 541 len_and_sockaddr *our_lsa;
541 len_and_sockaddr *peer_lsa; 542 len_and_sockaddr *peer_lsa;
542 char *filename, *mode, *opt_str; 543 char *filename, *mode, *opt_str;
543 int result, opcode, cmd, req_modebits, open_mode, local_fd, blksize; 544 int opt_r, result, opcode, open_mode, local_fd, blksize;
545 USE_GETPUT(int cmd;)
544 546
545 our_lsa = get_sock_lsa(STDIN_FILENO); 547 our_lsa = get_sock_lsa(STDIN_FILENO);
546 if (!our_lsa) 548 if (!our_lsa)
@@ -548,8 +550,10 @@ int tftpd_main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
548 peer_lsa = xzalloc(LSA_LEN_SIZE + our_lsa->len); 550 peer_lsa = xzalloc(LSA_LEN_SIZE + our_lsa->len);
549 peer_lsa->len = our_lsa->len; 551 peer_lsa->len = our_lsa->len;
550 552
551 if (argv[1]) 553 opt_r = getopt32(argv, "r");
552 xchdir(argv[1]); 554 argv += optind;
555 if (argv[0])
556 xchdir(argv[0]);
553 557
554 result = recv_from_to(STDIN_FILENO, block_buf, sizeof(block_buf), 558 result = recv_from_to(STDIN_FILENO, block_buf, sizeof(block_buf),
555 0 /* flags */, 559 0 /* flags */,
@@ -558,7 +562,10 @@ int tftpd_main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
558 opcode = ntohs(*(uint16_t*)block_buf); 562 opcode = ntohs(*(uint16_t*)block_buf);
559 if (result < 4 || result >= sizeof(block_buf) 563 if (result < 4 || result >= sizeof(block_buf)
560 || block_buf[result-1] != '\0' 564 || block_buf[result-1] != '\0'
561 || (opcode != TFTP_RRQ && opcode != TFTP_WRQ) 565 || (USE_FEATURE_TFTP_GET(opcode != TFTP_RRQ) /* not download */
566 USE_GETPUT(&&)
567 USE_FEATURE_TFTP_GET(opcode != TFTP_WRQ) /* not upload */
568 )
562 ) { 569 ) {
563 bb_error_msg_and_die("malformed packet"); 570 bb_error_msg_and_die("malformed packet");
564 } 571 }
@@ -584,21 +591,20 @@ int tftpd_main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
584 } 591 }
585 } 592 }
586#endif 593#endif
587 xstat(filename, &statbuf); 594
588 /* if opcode == TFTP_WRQ: */ 595#if ENABLE_FEATURE_TFTP_PUT
589 cmd = 1; /* CMD_GET: we will receive file's data */ 596 /* in case opcode is TFTP_RRQ: */
590 req_modebits = 0222; /* writable by anyone */ 597 USE_GETPUT(cmd = 2;) /* CMD_PUT: we will send file's data */
591 open_mode = O_WRONLY | O_TRUNC; 598 open_mode = O_RDONLY;
592 if (opcode == TFTP_RRQ) { 599#endif
593 cmd = 2; /* CMD_PUT */ 600#if ENABLE_FEATURE_TFTP_GET
594 req_modebits = 0444; /* readable by anyone */ 601 if (!ENABLE_FEATURE_TFTP_PUT || opcode == TFTP_WRQ) {
595 open_mode = O_RDONLY; 602 if (opt_r)
596 } 603 bb_error_msg_and_die("upload is prohibited");
597 if (!S_ISREG(statbuf.st_mode) 604 USE_GETPUT(cmd = 1;) /* CMD_GET: we will receive file's data */
598 || (statbuf.st_mode & req_modebits) != req_modebits 605 open_mode = O_WRONLY | O_TRUNC;
599 ) {
600 bb_error_msg_and_die("access to '%s' is denied", filename);
601 } 606 }
607#endif
602 local_fd = xopen(filename, open_mode); 608 local_fd = xopen(filename, open_mode);
603 609
604 close(STDIN_FILENO); /* close old, possibly wildcard socket */ 610 close(STDIN_FILENO); /* close old, possibly wildcard socket */