new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / remoted / syslogtcp.c
1 /* Copyright (C) 2009 Trend Micro Inc.
2  * All right reserved.
3  *
4  * This program is a free software; you can redistribute it
5  * and/or modify it under the terms of the GNU General Public
6  * License (version 2) as published by the FSF - Free Software
7  * Foundation
8  */
9
10 #include "shared.h"
11 #include "os_net/os_net.h"
12 #include "remoted.h"
13
14
15 /* Checks if an IP is not allowed */
16 static int OS_IPNotAllowed(char *srcip)
17 {
18     if (logr.denyips != NULL) {
19         if (OS_IPFoundList(srcip, logr.denyips)) {
20             return (1);
21         }
22     }
23     if (logr.allowips != NULL) {
24         if (OS_IPFoundList(srcip, logr.allowips)) {
25             return (0);
26         }
27     }
28
29     /* If the IP is not allowed, it will be denied */
30     return (1);
31 }
32
33 /* Handle each client */
34 static void HandleClient(int client_socket, char *srcip)
35 {
36     int sb_size = OS_MAXSTR;
37     int r_sz = 0;
38
39     char buffer[OS_MAXSTR + 2];
40     char storage_buffer[OS_MAXSTR + 2];
41     char tmp_buffer[OS_MAXSTR + 2];
42
43     char *buffer_pt = NULL;
44
45     /* Create PID file */
46     if (CreatePID(ARGV0, getpid()) < 0) {
47         ErrorExit(PID_ERROR, ARGV0);
48     }
49
50     /* Initialize some variables */
51     memset(buffer, '\0', OS_MAXSTR + 2);
52     memset(storage_buffer, '\0', OS_MAXSTR + 2);
53     memset(tmp_buffer, '\0', OS_MAXSTR + 2);
54
55
56     while (1) {
57         /* If we fail, we need to return and close the socket */
58         if ((r_sz = OS_RecvTCPBuffer(client_socket, buffer, OS_MAXSTR - 2)) < 0) {
59             close(client_socket);
60             DeletePID(ARGV0);
61             return;
62         }
63
64         /* We must have a new line at the end */
65         buffer_pt = strchr(buffer, '\n');
66         if (!buffer_pt) {
67             /* Buffer is full */
68             if ((sb_size - r_sz) <= 2) {
69                 merror("%s: Full buffer receiving from: '%s'", ARGV0, srcip);
70                 sb_size = OS_MAXSTR;
71                 storage_buffer[0] = '\0';
72                 continue;
73             }
74
75             strncat(storage_buffer, buffer, sb_size);
76             sb_size -= r_sz;
77             continue;
78         }
79
80         /* See if we received more than just one message */
81         if (*(buffer_pt + 1) != '\0') {
82             *buffer_pt = '\0';
83             buffer_pt++;
84             strncpy(tmp_buffer, buffer_pt, OS_MAXSTR);
85         }
86
87         /* Store everything in the storage_buffer
88          * Check if buffer will be full
89          */
90         if ((sb_size - r_sz) <= 2) {
91             merror("%s: Full buffer receiving from: '%s'.", ARGV0, srcip);
92             sb_size = OS_MAXSTR;
93             storage_buffer[0] = '\0';
94             tmp_buffer[0] = '\0';
95             continue;
96         }
97
98         strncat(storage_buffer, buffer, sb_size);
99
100         /* Remove carriage returns too */
101         buffer_pt = strchr(storage_buffer, '\r');
102         if (buffer_pt) {
103             *buffer_pt = '\0';
104         }
105
106         /* Remove syslog header */
107         if (storage_buffer[0] == '<') {
108             buffer_pt = strchr(storage_buffer + 1, '>');
109             if (buffer_pt) {
110                 buffer_pt++;
111             } else {
112                 buffer_pt = storage_buffer;
113             }
114         } else {
115             buffer_pt = storage_buffer;
116         }
117
118         /* Send to the queue */
119         if (SendMSG(logr.m_queue, buffer_pt, srcip, SYSLOG_MQ) < 0) {
120             merror(QUEUE_ERROR, ARGV0, DEFAULTQUEUE, strerror(errno));
121
122             if ((logr.m_queue = StartMQ(DEFAULTQUEUE, WRITE)) < 0) {
123                 ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQUEUE);
124             }
125         }
126
127         /* Clean up the buffers */
128         if (tmp_buffer[0] != '\0') {
129             strncpy(storage_buffer, tmp_buffer, OS_MAXSTR);
130             sb_size = OS_MAXSTR - (strlen(storage_buffer) + 1);
131             tmp_buffer[0] = '\0';
132         } else {
133             storage_buffer[0] = '\0';
134             sb_size = OS_MAXSTR;
135         }
136     }
137 }
138
139 /* Handle syslog TCP connections */
140 void HandleSyslogTCP()
141 {
142     int childcount = 0;
143     char srcip[IPSIZE + 1];
144     fd_set fdsave, fdwork;                      /* select() work areas */
145     int fdmax;                                  /* max socket number + 1 */
146     int sock;                                   /* active socket */
147
148     /* Initialize some variables */
149     memset(srcip, '\0', IPSIZE + 1);
150
151     /* initialize select() save area */
152     fdsave = logr.netinfo->fdset;
153     fdmax  = logr.netinfo->fdmax;               /* value preset to max fd + 1 */
154
155     /* Connecting to the message queue
156      * Exit if it fails.
157      */
158     if ((logr.m_queue = StartMQ(DEFAULTQUEUE, WRITE)) < 0) {
159         ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQUEUE);
160     }
161
162     while (1) {
163         /* Wait for the children */
164         while (childcount) {
165             int wp;
166             wp = waitpid((pid_t) - 1, NULL, WNOHANG);
167             if (wp < 0) {
168                 merror(WAITPID_ERROR, ARGV0, errno, strerror(errno));
169             }
170
171             /* if = 0, we still need to wait for the child process */
172             else if (wp == 0) {
173                 break;
174             } else {
175                 childcount--;
176             }
177         }
178
179         /* process connections through select() for multiple sockets */
180         fdwork = fdsave;
181         if (select (fdmax, &fdwork, NULL, NULL, NULL) < 0) {
182             ErrorExit("ERROR: Call to syslogtcp select() failed, errno %d - %s",
183                       errno, strerror (errno));
184         }
185
186         /* read through socket list for active socket */
187         for (sock = 0; sock <= fdmax; sock++) {
188             if (FD_ISSET (sock, &fdwork)) {
189
190                 /* Accept new connections */
191                 int client_socket = OS_AcceptTCP(sock, srcip, IPSIZE);
192                 if (client_socket < 0) {
193                     merror("%s: WARN: Accepting tcp connection from client failed.", ARGV0);
194                     continue;
195                 }
196
197                 /* Check if IP is allowed here */
198                 if (OS_IPNotAllowed(srcip)) {
199                     merror(DENYIP_WARN, ARGV0, srcip);
200                     close(client_socket);
201                     continue;
202                 }
203
204                 /* Fork to deal with new client */
205                 if (fork() == 0) {
206                     HandleClient(client_socket, srcip);
207                     exit(0);
208                 } else {
209                     childcount++;
210
211                     /* Close client socket, since the child is handling it */
212                     close(client_socket);
213                     continue;
214                 }
215             } /* if socket active */
216         } /* for() loop on available sockets */
217     } /* while(1) loop for messages */
218 }
219