new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / rootcheck / check_rc_ports.c
old mode 100755 (executable)
new mode 100644 (file)
index 94b1fae..de4f8ee
@@ -1,6 +1,3 @@
-/* @(#) $Id: ./src/rootcheck/check_rc_ports.c, 2011/09/08 dcid Exp $
- */
-
 /* Copyright (C) 2009 Trend Micro Inc.
  * All right reserved.
  *
  * Foundation
  */
 
-
 #ifndef WIN32
 
 #include "shared.h"
 #include "rootcheck.h"
 
-/* SunOS netstat */
 #if defined(sun) || defined(__sun__)
-#define NETSTAT "netstat -an -P %s | "\
-                "grep \"[^0-9]%d \" > /dev/null 2>&1"
-
-/*
-#elif WIN32
-#define NETSTAT "netstat -an -p %s | "\
-                "find \":%d\""
-*/
-
-#elif defined(Linux)
-#define NETSTAT_LIST "netstat -an | grep \"^%s\" | "\
-                     "cut -d ':' -f 2 | cut -d ' ' -f 1"
-#define NETSTAT "netstat -an | grep \"^%s\" | " \
-                "grep \"[^0-9]%d \" > /dev/null 2>&1"
+#define NETSTAT         "netstat -an -P %s | "\
+                        "grep \"[^0-9]%d \" > /dev/null 2>&1"
+#else
+#define NETSTAT         "netstat -an | grep \"^%s\" | " \
+                        "grep \"[^0-9]%d \" > /dev/null 2>&1"
 #endif
 
-#ifndef NETSTAT
-#define NETSTAT "netstat -an | grep \"^%s\" | " \
-                "grep \"[^0-9]%d \" > /dev/null 2>&1"
-#endif
+/* Prototypes */
+static int  run_netstat(int proto, int port);
+static int  conn_port(int proto, int port);
+static void test_ports(int proto, int *_errors, int *_total);
 
 
-int run_netstat(int proto, int port)
+static int run_netstat(int proto, int port)
 {
     int ret;
-    char nt[OS_SIZE_1024 +1];
+    char nt[OS_SIZE_1024 + 1];
 
-    if(proto == IPPROTO_TCP)
+    if (proto == IPPROTO_TCP) {
         snprintf(nt, OS_SIZE_1024, NETSTAT, "tcp", port);
-    else if(proto == IPPROTO_UDP)
+    } else if (proto == IPPROTO_UDP) {
         snprintf(nt, OS_SIZE_1024, NETSTAT, "udp", port);
-    else
-    {
+    } else {
         merror("%s: Netstat error (wrong protocol)", ARGV0);
-        return(0);
+        return (0);
     }
 
     ret = system(nt);
 
-    if(ret == 0)
-        return(1);
-
-    else if(ret == 1)
-    {
-        return(0);
+    if (ret == 0) {
+        return (1);
+    } else if (ret == 1) {
+        return (0);
     }
 
-    return(1);
+    return (1);
 }
 
-
-int conn_port(int proto, int port)
+static int conn_port(int proto, int port)
 {
     int rc = 0;
     int ossock;
     struct sockaddr_in server;
+    struct sockaddr_in6 server6;
 
-    if(proto == IPPROTO_UDP)
-    {
-        if((ossock = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0)
-            return(0);
-    }
-    else if(proto == IPPROTO_TCP)
-    {
-        if((ossock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0)
-            return(0);
-    }
-    else
-    {
-       return (0);
+    if (proto == IPPROTO_UDP) {
+        if ((ossock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+            return (0);
+        }
+    } else if (proto == IPPROTO_TCP) {
+        if ((ossock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+            return (0);
+        }
+    } else {
+        return (0);
     }
 
     memset(&server, 0, sizeof(server));
     server.sin_family = AF_INET;
-    server.sin_port = htons( port );
+    server.sin_port = htons(port);
     server.sin_addr.s_addr = htonl(INADDR_ANY);
 
+    /* If we can't bind, it means the port is open */
+    if (bind(ossock, (struct sockaddr *) &server, sizeof(server)) < 0) {
+        rc = 1;
+    }
+
+    /* Setting if port is open or closed */
+    if (proto == IPPROTO_TCP) {
+        total_ports_tcp[port] = (char) rc;
+    } else {
+        total_ports_udp[port] = (char) rc;
+    }
+
+    close(ossock);
+
+    /* repeat for IPv6 */
+    if (proto == IPPROTO_UDP) {
+        if ((ossock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+            return(0);
+        }
+    } else if (proto == IPPROTO_TCP) {
+        if ((ossock = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+            return(0);
+        }
+    }
+
+
+    memset(&server6, 0, sizeof(server6));
+    server6.sin6_family = AF_INET6;
+    server6.sin6_port = htons( port );
+    memcpy(&server6.sin6_addr.s6_addr, &in6addr_any, sizeof in6addr_any);
+
 
     /* If we can't bind, it means the port is open */
-    if(bind(ossock, (struct sockaddr *) &server, sizeof(server)) < 0)
-    {
+    if(bind(ossock, (struct sockaddr *) &server6, sizeof(server6)) < 0) {
         rc = 1;
     }
 
     /* Setting if port is open or closed */
-    if(proto == IPPROTO_TCP)
-    {
+    if(proto == IPPROTO_TCP) {
         total_ports_tcp[port] = rc;
-    }
-    else
-    {
+    } else {
         total_ports_udp[port] = rc;
     }
 
     close(ossock);
 
-    return(rc);
+    return (rc);
 }
 
-
-void test_ports(int proto, int *_errors, int *_total)
+static void test_ports(int proto, int *_errors, int *_total)
 {
     int i;
 
-    for(i = 0; i<= 65535; i++)
-    {
+    for (i = 0; i <= 65535; i++) {
         (*_total)++;
-        if(conn_port(proto, i))
-        {
-            /* Checking if we can find it using netstat, if not,
+        if (conn_port(proto, i)) {
+            /* Check if we can find it using netstat. If not,
              * check again to see if the port is still being used.
              */
-            if(run_netstat(proto, i))
-            {
+            if (run_netstat(proto, i)) {
                 continue;
-
-                #ifdef OSSECHIDS
-                sleep(2);
-                #endif
             }
 
-            /* If we are being run by the ossec hids, sleep here (no rush) */
-            #ifdef OSSECHIDS
-            sleep(2);
-            #endif
+#ifdef OSSECHIDS
+            /* If we are in the context of OSSEC-HIDS, sleep here (no rush) */
+            debug1("%s: DEBUG: pause for %u", ARGV0, rootcheck.tsleep);
+            sleep(rootcheck.tsleep);
+#endif
 
-            if(!run_netstat(proto, i) && conn_port(proto, i))
-            {
-                char op_msg[OS_SIZE_1024 +1];
+            if (!run_netstat(proto, i) && conn_port(proto, i)) {
+                char op_msg[OS_SIZE_1024 + 1];
 
                 (*_errors)++;
 
                 snprintf(op_msg, OS_SIZE_1024, "Port '%d'(%s) hidden. "
-                        "Kernel-level rootkit or trojaned "
-                        "version of netstat.", i,
-                        (proto == IPPROTO_UDP)? "udp" : "tcp");
+                         "Kernel-level rootkit or trojaned "
+                         "version of netstat.", i,
+                         (proto == IPPROTO_UDP) ? "udp" : "tcp");
 
                 notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
             }
         }
 
-        if((*_errors) > 20)
-        {
-            char op_msg[OS_SIZE_1024 +1];
+        if ((*_errors) > 20) {
+            char op_msg[OS_SIZE_1024 + 1];
+
             snprintf(op_msg, OS_SIZE_1024, "Excessive number of '%s' ports "
-                             "hidden. It maybe a false-positive or "
-                             "something really bad is going on.",
-                             (proto == IPPROTO_UDP)? "udp" : "tcp" );
+                     "hidden. It maybe a false-positive or "
+                     "something really bad is going on.",
+                     (proto == IPPROTO_UDP) ? "udp" : "tcp" );
             notify_rk(ALERT_SYSTEM_CRIT, op_msg);
             return;
         }
@@ -173,10 +172,6 @@ void test_ports(int proto, int *_errors, int *_total)
 
 }
 
-
-/*  check_rc_ports: v0.1
- *  Check all ports
- */
 void check_rc_ports()
 {
     int _errors = 0;
@@ -184,38 +179,35 @@ void check_rc_ports()
 
     int i = 0;
 
-    while(i<=65535)
-    {
+    while (i <= 65535) {
         total_ports_tcp[i] = 0;
         total_ports_udp[i] = 0;
         i++;
     }
 
-    /* Trsting TCP ports */
+    /* Test both TCP and UDP ports */
     test_ports(IPPROTO_TCP, &_errors, &_total);
-
-    /* Testing UDP ports */
     test_ports(IPPROTO_UDP, &_errors, &_total);
 
-    if(_errors == 0)
-    {
-        char op_msg[OS_SIZE_1024 +1];
-        snprintf(op_msg,OS_SIZE_1024,"No kernel-level rootkit hiding any port."
-                                   "\n      Netstat is acting correctly."
-                                    " Analyzed %d ports.", _total);
+    if (_errors == 0) {
+        char op_msg[OS_SIZE_1024 + 1];
+
+        snprintf(op_msg, OS_SIZE_1024, "No kernel-level rootkit hiding any port."
+                 "\n      Netstat is acting correctly."
+                 " Analyzed %d ports.", _total);
         notify_rk(ALERT_OK, op_msg);
     }
 
     return;
 }
 
+#else /* WIN32 */
 
-#else
+/* Not implemented on Windows */
 void check_rc_ports()
 {
     return;
 }
-#endif
 
+#endif /* WIN32 */
 
-/* EOF */