novi upstream verzije 2.8.3
[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     else
89     {
90         return (0);
91     }
92
93     memset(&server, 0, sizeof(server));
94     server.sin_family = AF_INET;
95     server.sin_port = htons( port );
96     server.sin_addr.s_addr = htonl(INADDR_ANY);
97
98
99     /* If we can't bind, it means the port is open */
100     if(bind(ossock, (struct sockaddr *) &server, sizeof(server)) < 0)
101     {
102         rc = 1;
103     }
104
105     /* Setting if port is open or closed */
106     if(proto == IPPROTO_TCP)
107     {
108         total_ports_tcp[port] = rc;
109     }
110     else
111     {
112         total_ports_udp[port] = rc;
113     }
114
115     close(ossock);
116
117     return(rc);
118 }
119
120
121 void test_ports(int proto, int *_errors, int *_total)
122 {
123     int i;
124
125     for(i = 0; i<= 65535; i++)
126     {
127         (*_total)++;
128         if(conn_port(proto, i))
129         {
130             /* Checking if we can find it using netstat, if not,
131              * check again to see if the port is still being used.
132              */
133             if(run_netstat(proto, i))
134             {
135                 continue;
136
137                 #ifdef OSSECHIDS
138                 sleep(2);
139                 #endif
140             }
141
142             /* If we are being run by the ossec hids, sleep here (no rush) */
143             #ifdef OSSECHIDS
144             sleep(2);
145             #endif
146
147             if(!run_netstat(proto, i) && conn_port(proto, i))
148             {
149                 char op_msg[OS_SIZE_1024 +1];
150
151                 (*_errors)++;
152
153                 snprintf(op_msg, OS_SIZE_1024, "Port '%d'(%s) hidden. "
154                         "Kernel-level rootkit or trojaned "
155                         "version of netstat.", i,
156                         (proto == IPPROTO_UDP)? "udp" : "tcp");
157
158                 notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
159             }
160         }
161
162         if((*_errors) > 20)
163         {
164             char op_msg[OS_SIZE_1024 +1];
165             snprintf(op_msg, OS_SIZE_1024, "Excessive number of '%s' ports "
166                              "hidden. It maybe a false-positive or "
167                              "something really bad is going on.",
168                              (proto == IPPROTO_UDP)? "udp" : "tcp" );
169             notify_rk(ALERT_SYSTEM_CRIT, op_msg);
170             return;
171         }
172     }
173
174 }
175
176
177 /*  check_rc_ports: v0.1
178  *  Check all ports
179  */
180 void check_rc_ports()
181 {
182     int _errors = 0;
183     int _total = 0;
184
185     int i = 0;
186
187     while(i<=65535)
188     {
189         total_ports_tcp[i] = 0;
190         total_ports_udp[i] = 0;
191         i++;
192     }
193
194     /* Trsting TCP ports */
195     test_ports(IPPROTO_TCP, &_errors, &_total);
196
197     /* Testing UDP ports */
198     test_ports(IPPROTO_UDP, &_errors, &_total);
199
200     if(_errors == 0)
201     {
202         char op_msg[OS_SIZE_1024 +1];
203         snprintf(op_msg,OS_SIZE_1024,"No kernel-level rootkit hiding any port."
204                                    "\n      Netstat is acting correctly."
205                                     " Analyzed %d ports.", _total);
206         notify_rk(ALERT_OK, op_msg);
207     }
208
209     return;
210 }
211
212
213 #else
214 void check_rc_ports()
215 {
216     return;
217 }
218 #endif
219
220
221 /* EOF */