890407cb0ce2a9fbff6313a56e4e6d71f594582e
[ossec-hids.git] / src / rootcheck / check_rc_ports.c
1 /* @(#) $Id$ */
2
3 /* Copyright (C) 2009 Trend Micro Inc.
4  * All right reserved.
5  *
6  * This program is a free software; you can redistribute it
7  * and/or modify it under the terms of the GNU General Public
8  * License (version 2) as published by the FSF - Free Software
9  * Foundation
10  */
11
12  
13 #ifndef WIN32
14  
15 #include "shared.h"
16 #include "rootcheck.h"
17
18 /* SunOS netstat */
19 #if defined(sun) || defined(__sun__)
20 #define NETSTAT "netstat -an -P %s | "\
21                 "grep \"[^0-9]%d \" > /dev/null 2>&1"
22
23 /*
24 #elif WIN32
25 #define NETSTAT "netstat -an -p %s | "\
26                 "find \":%d\""
27 */
28
29 #elif defined(Linux)
30 #define NETSTAT_LIST "netstat -an | grep \"^%s\" | "\
31                      "cut -d ':' -f 2 | cut -d ' ' -f 1"
32 #define NETSTAT "netstat -an | grep \"^%s\" | " \
33                 "grep \"[^0-9]%d \" > /dev/null 2>&1"                          
34 #endif
35
36 #ifndef NETSTAT
37 #define NETSTAT "netstat -an | grep \"^%s\" | " \
38                 "grep \"[^0-9]%d \" > /dev/null 2>&1"
39 #endif
40
41
42 int run_netstat(int proto, int port)
43 {
44     char nt[OS_SIZE_1024 +1];
45
46     if(proto == IPPROTO_TCP)
47         snprintf(nt, OS_SIZE_1024, NETSTAT, "tcp", port);
48     else if(proto == IPPROTO_UDP)
49         snprintf(nt, OS_SIZE_1024, NETSTAT, "udp", port);
50     else
51     {
52         merror("%s: Netstat error (wrong protocol)", ARGV0);
53         return(0);
54     }
55
56     if(system(nt) == 0)    
57         return(1);
58     
59     return(0);    
60 }
61
62
63 int conn_port(int proto, int port)
64 {
65     int rc = 0;
66     int ossock;
67     struct sockaddr_in server;
68
69     if(proto == IPPROTO_UDP)
70     {
71         if((ossock = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0)
72             return(0);
73     }
74     else if(proto == IPPROTO_TCP)
75     {
76         if((ossock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0)
77             return(0);
78     }
79
80
81     memset(&server, 0, sizeof(server));
82     server.sin_family = AF_INET;
83     server.sin_port = htons( port );
84     server.sin_addr.s_addr = htonl(INADDR_ANY);
85
86     
87     /* If we can't bind, it means the port is open */
88     if(bind(ossock, (struct sockaddr *) &server, sizeof(server)) < 0)
89     {
90         rc = 1;
91     }
92
93     /* Setting if port is open or closed */
94     if(proto == IPPROTO_TCP)
95     {
96         total_ports_tcp[port] = rc;
97     }
98     else
99     {
100         total_ports_udp[port] = rc;
101     }
102     
103     close(ossock);  
104
105     return(rc);  
106 }
107
108
109 void test_ports(int proto, int *_errors, int *_total)
110 {
111     int i;
112
113     for(i = 0; i<= 65535; i++)
114     {
115         (*_total)++;
116         if(conn_port(proto, i))
117         {
118             /* Checking if we can find it using netstat, if not,
119              * check again to see if the port is still being used.
120              */
121             if(run_netstat(proto, i))
122             {
123                 continue;
124                 
125                 #ifdef OSSECHIDS
126                 sleep(2);
127                 #endif
128             }
129
130             /* If we are being run by the ossec hids, sleep here (no rush) */
131             #ifdef OSSECHIDS
132             sleep(2);
133             #endif
134
135             if(!run_netstat(proto, i) && conn_port(proto, i))
136             {
137                 char op_msg[OS_SIZE_1024 +1];
138
139                 (*_errors)++;
140
141                 snprintf(op_msg, OS_SIZE_1024, "Port '%d'(%s) hidden. "
142                         "Kernel-level rootkit or trojaned "
143                         "version of netstat.", i, 
144                         (proto == IPPROTO_UDP)? "udp" : "tcp");
145
146                 notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
147             }
148         }
149
150         if((*_errors) > 20)
151         {
152             char op_msg[OS_SIZE_1024 +1];
153             snprintf(op_msg, OS_SIZE_1024, "Excessive number of '%s' ports "
154                              "hidden. It maybe a false-positive or "
155                              "something really bad is going on.",
156                              (proto == IPPROTO_UDP)? "udp" : "tcp" );
157             notify_rk(ALERT_SYSTEM_CRIT, op_msg);
158             return;
159         }
160     }
161
162 }
163
164
165 /*  check_rc_ports: v0.1
166  *  Check all ports
167  */
168 void check_rc_ports()
169 {
170     int _errors = 0;
171     int _total = 0;
172
173     int i = 0;
174
175     while(i<=65535)
176     {
177         total_ports_tcp[i] = 0;
178         total_ports_udp[i] = 0;
179         i++;
180     }
181     
182     /* Trsting TCP ports */ 
183     test_ports(IPPROTO_TCP, &_errors, &_total);
184
185     /* Testing UDP ports */
186     test_ports(IPPROTO_UDP, &_errors, &_total);
187
188     if(_errors == 0)
189     {
190         char op_msg[OS_SIZE_1024 +1];
191         snprintf(op_msg,OS_SIZE_1024,"No kernel-level rootkit hiding any port."
192                                    "\n      Netstat is acting correctly."
193                                     " Analyzed %d ports.", _total);
194         notify_rk(ALERT_OK, op_msg);
195     }
196     
197     return;
198 }
199
200
201 #else
202 void check_rc_ports()
203 {
204     return;
205 }
206 #endif
207
208
209 /* EOF */