summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLorenz <12514511+RincewindsHat@users.noreply.github.com>2022-03-15 21:00:55 (GMT)
committerGitHub <noreply@github.com>2022-03-15 21:00:55 (GMT)
commit605405557102c04e740fc3249675cc5154436d11 (patch)
tree5c4ff8a018d3ccc1bc784a6ea0bbf6514f91ff85
parent6c8b45a1691f4ce98f1c559a1e9cd1fef68c0fe2 (diff)
downloadmonitoring-plugins-6054055.tar.gz
check_icmp: buffer offerflow (#1733)
* Fix different overflows * Less includes * Add testcases * Remove unused variable * Remove unused and commented includes
-rw-r--r--plugins-root/check_icmp.c66
-rw-r--r--plugins-root/t/check_icmp.t7
2 files changed, 43 insertions, 30 deletions
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c
index f97b0ed..6119823 100644
--- a/plugins-root/check_icmp.c
+++ b/plugins-root/check_icmp.c
@@ -50,19 +50,11 @@ const char *email = "devel@monitoring-plugins.org";
50#if HAVE_SYS_SOCKIO_H 50#if HAVE_SYS_SOCKIO_H
51#include <sys/sockio.h> 51#include <sys/sockio.h>
52#endif 52#endif
53#include <sys/ioctl.h> 53
54#include <sys/time.h> 54#include <sys/time.h>
55#include <sys/types.h>
56#include <stdio.h>
57#include <stdlib.h>
58#include <stdarg.h>
59#include <unistd.h>
60#include <stddef.h>
61#include <errno.h> 55#include <errno.h>
62#include <string.h> 56#include <signal.h>
63#include <ctype.h> 57#include <ctype.h>
64#include <netdb.h>
65#include <sys/socket.h>
66#include <net/if.h> 58#include <net/if.h>
67#include <netinet/in_systm.h> 59#include <netinet/in_systm.h>
68#include <netinet/in.h> 60#include <netinet/in.h>
@@ -71,8 +63,6 @@ const char *email = "devel@monitoring-plugins.org";
71#include <netinet/ip_icmp.h> 63#include <netinet/ip_icmp.h>
72#include <netinet/icmp6.h> 64#include <netinet/icmp6.h>
73#include <arpa/inet.h> 65#include <arpa/inet.h>
74#include <signal.h>
75#include <float.h>
76 66
77 67
78/** sometimes undefined system macros (quite a few, actually) **/ 68/** sometimes undefined system macros (quite a few, actually) **/
@@ -207,7 +197,7 @@ static int add_target(char *);
207static int add_target_ip(char *, struct sockaddr_storage *); 197static int add_target_ip(char *, struct sockaddr_storage *);
208static int handle_random_icmp(unsigned char *, struct sockaddr_storage *); 198static int handle_random_icmp(unsigned char *, struct sockaddr_storage *);
209static void parse_address(struct sockaddr_storage *, char *, int); 199static void parse_address(struct sockaddr_storage *, char *, int);
210static unsigned short icmp_checksum(unsigned short *, int); 200static unsigned short icmp_checksum(uint16_t *, size_t);
211static void finish(int); 201static void finish(int);
212static void crash(const char *, ...); 202static void crash(const char *, ...);
213 203
@@ -465,7 +455,6 @@ main(int argc, char **argv)
465 /* Parse protocol arguments first */ 455 /* Parse protocol arguments first */
466 for(i = 1; i < argc; i++) { 456 for(i = 1; i < argc; i++) {
467 while((arg = getopt(argc, argv, opts_str)) != EOF) { 457 while((arg = getopt(argc, argv, opts_str)) != EOF) {
468 unsigned short size;
469 switch(arg) { 458 switch(arg) {
470 case '4': 459 case '4':
471 if (address_family != -1) 460 if (address_family != -1)
@@ -488,10 +477,10 @@ main(int argc, char **argv)
488 /* Reset argument scanning */ 477 /* Reset argument scanning */
489 optind = 1; 478 optind = 1;
490 479
480 unsigned short size;
491 /* parse the arguments */ 481 /* parse the arguments */
492 for(i = 1; i < argc; i++) { 482 for(i = 1; i < argc; i++) {
493 while((arg = getopt(argc, argv, opts_str)) != EOF) { 483 while((arg = getopt(argc, argv, opts_str)) != EOF) {
494 unsigned short size;
495 switch(arg) { 484 switch(arg) {
496 case 'v': 485 case 'v':
497 debug++; 486 debug++;
@@ -720,7 +709,7 @@ main(int argc, char **argv)
720static void 709static void
721run_checks() 710run_checks()
722{ 711{
723 u_int i, t, result; 712 u_int i, t;
724 u_int final_wait, time_passed; 713 u_int final_wait, time_passed;
725 714
726 /* this loop might actually violate the pkt_interval or target_interval 715 /* this loop might actually violate the pkt_interval or target_interval
@@ -738,9 +727,9 @@ run_checks()
738 727
739 /* we're still in the game, so send next packet */ 728 /* we're still in the game, so send next packet */
740 (void)send_icmp_ping(icmp_sock, table[t]); 729 (void)send_icmp_ping(icmp_sock, table[t]);
741 result = wait_for_reply(icmp_sock, target_interval); 730 wait_for_reply(icmp_sock, target_interval);
742 } 731 }
743 result = wait_for_reply(icmp_sock, pkt_interval * targets); 732 wait_for_reply(icmp_sock, pkt_interval * targets);
744 } 733 }
745 734
746 if(icmp_pkts_en_route && targets_alive) { 735 if(icmp_pkts_en_route && targets_alive) {
@@ -760,7 +749,7 @@ run_checks()
760 * haven't yet */ 749 * haven't yet */
761 if(debug) printf("Waiting for %u micro-seconds (%0.3f msecs)\n", 750 if(debug) printf("Waiting for %u micro-seconds (%0.3f msecs)\n",
762 final_wait, (float)final_wait / 1000); 751 final_wait, (float)final_wait / 1000);
763 result = wait_for_reply(icmp_sock, final_wait); 752 wait_for_reply(icmp_sock, final_wait);
764 } 753 }
765} 754}
766 755
@@ -779,7 +768,7 @@ static int
779wait_for_reply(int sock, u_int t) 768wait_for_reply(int sock, u_int t)
780{ 769{
781 int n, hlen; 770 int n, hlen;
782 static unsigned char buf[4096]; 771 static unsigned char buf[65536];
783 struct sockaddr_storage resp_addr; 772 struct sockaddr_storage resp_addr;
784 union ip_hdr *ip; 773 union ip_hdr *ip;
785 union icmp_packet packet; 774 union icmp_packet packet;
@@ -916,9 +905,27 @@ wait_for_reply(int sock, u_int t)
916 if(debug) { 905 if(debug) {
917 char address[INET6_ADDRSTRLEN]; 906 char address[INET6_ADDRSTRLEN];
918 parse_address(&resp_addr, address, sizeof(address)); 907 parse_address(&resp_addr, address, sizeof(address));
919 printf("%0.3f ms rtt from %s, outgoing ttl: %u, incoming ttl: %u, max: %0.3f, min: %0.3f\n", 908
920 (float)tdiff / 1000, address, 909 switch(address_family) {
921 ttl, ip->ip.ip_ttl, (float)host->rtmax / 1000, (float)host->rtmin / 1000); 910 case AF_INET: {
911 printf("%0.3f ms rtt from %s, outgoing ttl: %u, incoming ttl: %u, max: %0.3f, min: %0.3f\n",
912 (float)tdiff / 1000,
913 address,
914 ttl,
915 ip->ip.ip_ttl,
916 (float)host->rtmax / 1000,
917 (float)host->rtmin / 1000);
918 break;
919 };
920 case AF_INET6: {
921 printf("%0.3f ms rtt from %s, outgoing ttl: %u, max: %0.3f, min: %0.3f\n",
922 (float)tdiff / 1000,
923 address,
924 ttl,
925 (float)host->rtmax / 1000,
926 (float)host->rtmin / 1000);
927 };
928 }
922 } 929 }
923 930
924 /* if we're in hostcheck mode, exit with limited printouts */ 931 /* if we're in hostcheck mode, exit with limited printouts */
@@ -980,7 +987,7 @@ send_icmp_ping(int sock, struct rta_host *host)
980 icp->icmp_cksum = 0; 987 icp->icmp_cksum = 0;
981 icp->icmp_id = htons(pid); 988 icp->icmp_id = htons(pid);
982 icp->icmp_seq = htons(host->id++); 989 icp->icmp_seq = htons(host->id++);
983 icp->icmp_cksum = icmp_checksum((unsigned short*)buf, icmp_pkt_size); 990 icp->icmp_cksum = icmp_checksum((uint16_t*)buf, (size_t)icmp_pkt_size);
984 991
985 if (debug > 2) 992 if (debug > 2)
986 printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", 993 printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n",
@@ -1517,18 +1524,19 @@ get_threshold(char *str, threshold *th)
1517} 1524}
1518 1525
1519unsigned short 1526unsigned short
1520icmp_checksum(unsigned short *p, int n) 1527icmp_checksum(uint16_t *p, size_t n)
1521{ 1528{
1522 unsigned short cksum; 1529 unsigned short cksum;
1523 long sum = 0; 1530 long sum = 0;
1524 1531
1525 while(n > 2) { 1532 /* sizeof(uint16_t) == 2 */
1526 sum += *p++; 1533 while(n >= 2) {
1527 n -= sizeof(unsigned short); 1534 sum += *(p++);
1535 n -= 2;
1528 } 1536 }
1529 1537
1530 /* mop up the occasional odd byte */ 1538 /* mop up the occasional odd byte */
1531 if(n == 1) sum += (unsigned char)*p; 1539 if(n == 1) sum += *((uint8_t *)p -1);
1532 1540
1533 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 1541 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
1534 sum += (sum >> 16); /* add carry */ 1542 sum += (sum >> 16); /* add carry */
diff --git a/plugins-root/t/check_icmp.t b/plugins-root/t/check_icmp.t
index 55edc31..f6aa681 100644
--- a/plugins-root/t/check_icmp.t
+++ b/plugins-root/t/check_icmp.t
@@ -12,7 +12,7 @@ my $allow_sudo = getTestParameter( "NP_ALLOW_SUDO",
12 "no" ); 12 "no" );
13 13
14if ($allow_sudo eq "yes" or $> == 0) { 14if ($allow_sudo eq "yes" or $> == 0) {
15 plan tests => 18; 15 plan tests => 20;
16} else { 16} else {
17 plan skip_all => "Need sudo to test check_icmp"; 17 plan skip_all => "Need sudo to test check_icmp";
18} 18}
@@ -89,3 +89,8 @@ $res = NPTest->testCmd(
89is( $res->return_code, 0, "IPv4 source_ip accepted" ); 89is( $res->return_code, 0, "IPv4 source_ip accepted" );
90like( $res->output, $successOutput, "Output OK" ); 90like( $res->output, $successOutput, "Output OK" );
91 91
92$res = NPTest->testCmd(
93 "$sudo ./check_icmp -H $host_responsive -b 65507"
94 );
95is( $res->return_code, 0, "Try max paket size" );
96like( $res->output, $successOutput, "Output OK - Didn't overflow" );