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