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