diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-03-18 01:13:11 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-03-18 01:13:11 +0000 |
commit | d7e6af2dda0abdd7a0411af46314724bd5f88549 (patch) | |
tree | e77291fb6fcb2d93c9c6ec60e21ddfe8bea5dc64 /networking/tftp.c | |
parent | 78c565653005192c4587fce1ccac6c441cea7ca6 (diff) | |
download | busybox-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.c | 48 |
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 | ||
535 | int tftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 537 | int tftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
536 | int tftpd_main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) | 538 | int 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 */ |