new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / client-agent / receiver.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 #ifdef WIN32
12 #include "os_execd/execd.h"
13 #endif
14 #include "os_crypto/md5/md5_op.h"
15 #include "os_net/os_net.h"
16 #include "agentd.h"
17
18 /* Global variables */
19 static FILE *fp = NULL;
20 static char file_sum[34] = "";
21 static char file[OS_SIZE_1024 + 1] = "";
22
23
24 /* Receive events from the server */
25 void *receive_msg()
26 {
27     ssize_t recv_b;
28     char buffer[OS_MAXSTR + 1];
29     char cleartext[OS_MAXSTR + 1];
30     char *tmp_msg;
31
32     memset(cleartext, '\0', OS_MAXSTR + 1);
33     memset(buffer, '\0', OS_MAXSTR + 1);
34
35     /* Read until no more messages are available */
36     while ((recv_b = recv(agt->sock, buffer, OS_SIZE_1024, MSG_DONTWAIT)) > 0) {
37         buffer[recv_b] = '\0';
38
39         tmp_msg = ReadSecMSG(&keys, buffer, cleartext, 0, recv_b - 1);
40         if (tmp_msg == NULL) {
41             merror(MSG_ERROR, ARGV0, agt->rip[agt->rip_id]);
42             continue;
43         }
44
45         /* Check for commands */
46         if (IsValidHeader(tmp_msg)) {
47             available_server = (int)time(NULL);
48
49 #ifdef WIN32
50             /* Run timeout commands */
51             if (agt->execdq >= 0) {
52                 WinTimeoutRun(available_server);
53             }
54 #endif
55
56             /* If it is an active response message */
57             if (strncmp(tmp_msg, EXECD_HEADER, strlen(EXECD_HEADER)) == 0) {
58                 tmp_msg += strlen(EXECD_HEADER);
59 #ifndef WIN32
60                 if (agt->execdq >= 0) {
61                     if (OS_SendUnix(agt->execdq, tmp_msg, 0) < 0) {
62                         merror("%s: Error communicating with execd",
63                                ARGV0);
64                     }
65                 }
66 #else
67                 /* Run on Windows */
68                 if (agt->execdq >= 0) {
69                     WinExecdRun(tmp_msg);
70                 }
71 #endif
72
73                 continue;
74             }
75
76             /* Restart syscheck */
77             else if (strcmp(tmp_msg, HC_SK_RESTART) == 0) {
78                 os_set_restart_syscheck();
79                 continue;
80             }
81
82             /* Ack from server */
83             else if (strcmp(tmp_msg, HC_ACK) == 0) {
84                 continue;
85             }
86
87             /* Close any open file pointer if it was being written to */
88             if (fp) {
89                 fclose(fp);
90                 fp = NULL;
91             }
92
93             /* File update message */
94             if (strncmp(tmp_msg, FILE_UPDATE_HEADER,
95                         strlen(FILE_UPDATE_HEADER)) == 0) {
96                 char *validate_file;
97
98                 tmp_msg += strlen(FILE_UPDATE_HEADER);
99
100                 /* Going to after the file sum */
101                 validate_file = strchr(tmp_msg, ' ');
102                 if (!validate_file) {
103                     continue;
104                 }
105
106                 *validate_file = '\0';
107
108                 /* Copy the file sum */
109                 strncpy(file_sum, tmp_msg, 33);
110
111                 /* Set tmp_msg to the beginning of the file name */
112                 validate_file++;
113                 tmp_msg = validate_file;
114
115                 if ((validate_file = strchr(tmp_msg, '\n')) != NULL) {
116                     *validate_file = '\0';
117                 }
118
119                 while ((validate_file = strchr(tmp_msg, '/')) != NULL) {
120                     *validate_file = '-';
121                 }
122
123                 if (tmp_msg[0] == '.') {
124                     tmp_msg[0] = '-';
125                 }
126
127                 snprintf(file, OS_SIZE_1024, "%s/%s",
128                          SHAREDCFG_DIR,
129                          tmp_msg);
130
131                 fp = fopen(file, "w");
132                 if (!fp) {
133                     merror(FOPEN_ERROR, ARGV0, file, errno, strerror(errno));
134                 }
135             }
136
137             else if (strncmp(tmp_msg, FILE_CLOSE_HEADER,
138                              strlen(FILE_CLOSE_HEADER)) == 0) {
139                 /* No error */
140                 os_md5 currently_md5;
141
142                 /* Close for the rename to work */
143                 if (fp) {
144                     fclose(fp);
145                     fp = NULL;
146                 }
147
148                 if (file[0] == '\0') {
149                     /* Nothing to be done */
150                 }
151
152                 else if (OS_MD5_File(file, currently_md5, OS_TEXT) < 0) {
153                     /* Remove file */
154                     unlink(file);
155                     file[0] = '\0';
156                 } else {
157                     if (strcmp(currently_md5, file_sum) != 0) {
158                         debug1("%s: ERROR: Failed md5 for: %s -- deleting.",
159                                ARGV0, file);
160                         unlink(file);
161                     } else {
162                         char *final_file;
163
164                         /* Rename the file to its original name */
165                         final_file = strrchr(file, '/');
166                         if (final_file) {
167                             if (strcmp(final_file + 1, SHAREDCFG_FILENAME) == 0) {
168                                 UnmergeFiles(file, SHAREDCFG_DIR);
169                             }
170                         } else {
171                             /* Remove file */
172                             unlink(file);
173                         }
174                     }
175
176                     file[0] = '\0';
177                 }
178             }
179
180             else {
181                 merror("%s: WARN: Unknown message received from server.", ARGV0);
182             }
183         }
184
185         else if (fp) {
186             available_server = (int)time(NULL);
187             fprintf(fp, "%s", tmp_msg);
188         }
189
190         else {
191             merror("%s: WARN: Unknown message received. No action defined.",
192                    ARGV0);
193         }
194     }
195
196     return (NULL);
197 }
198