new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / os_execd / exec.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_regex/os_regex.h"
12 #include "execd.h"
13
14 static char exec_names[MAX_AR + 1][OS_FLSIZE + 1];
15 static char exec_cmd[MAX_AR + 1][OS_FLSIZE + 1];
16 static int  exec_timeout[MAX_AR + 1];
17 static int  exec_size = 0;
18 static int  f_time_reading = 1;
19
20
21 /* Read the shared exec config
22  * Returns 1 on success or 0 on failure
23  * Format of the file is 'name - command - timeout'
24  */
25 int ReadExecConfig()
26 {
27     int i = 0, j = 0, dup_entry = 0;
28     FILE *fp;
29     FILE *process_file;
30     char buffer[OS_MAXSTR + 1];
31
32     /* Clean up */
33     for (i = 0; i <= exec_size + 1; i++) {
34         memset(exec_names[i], '\0', OS_FLSIZE + 1);
35         memset(exec_cmd[i], '\0', OS_FLSIZE + 1);
36         exec_timeout[i] = 0;
37     }
38     exec_size = 0;
39
40     /* Open file */
41     fp = fopen(DEFAULTARPATH, "r");
42     if (!fp) {
43         merror(FOPEN_ERROR, ARGV0, DEFAULTARPATH, errno, strerror(errno));
44         return (0);
45     }
46
47     /* Read config */
48     while (fgets(buffer, OS_MAXSTR, fp) != NULL) {
49         char *str_pt;
50         char *tmp_str;
51
52         str_pt = buffer;
53
54         /* Clean up the buffer */
55         tmp_str = strstr(buffer, " - ");
56         if (!tmp_str) {
57             merror(EXEC_INV_CONF, ARGV0, DEFAULTARPATH);
58             continue;
59         }
60         *tmp_str = '\0';
61         tmp_str += 3;
62
63         /* Set the name */
64         strncpy(exec_names[exec_size], str_pt, OS_FLSIZE);
65         exec_names[exec_size][OS_FLSIZE] = '\0';
66
67         str_pt = tmp_str;
68
69         /* Search for ' ' and - */
70         tmp_str = strstr(tmp_str, " - ");
71         if (!tmp_str) {
72             merror(EXEC_INV_CONF, ARGV0, DEFAULTARPATH);
73             continue;
74         }
75         *tmp_str = '\0';
76         tmp_str += 3;
77
78         // Directory traversal test
79
80         if (w_ref_parent_folder(str_pt)) {
81             merror("Active response command '%s' vulnerable to directory transversal attack. Ignoring.", str_pt);
82              exec_cmd[exec_size][0] = '\0';
83          } else {
84             /* Write the full command path */
85             snprintf(exec_cmd[exec_size], OS_FLSIZE,
86                      "%s/%s",
87                      AR_BINDIRPATH,
88                      str_pt);
89             process_file = fopen(exec_cmd[exec_size], "r");
90             if (!process_file) {
91                 if (f_time_reading) {
92                     verbose("%s: INFO: Active response command not present: '%s'. "
93                             "Not using it on this system.",
94                             ARGV0, exec_cmd[exec_size]);
95                 }
96
97                 exec_cmd[exec_size][0] = '\0';
98             } else {
99                 fclose(process_file);
100             }
101         }
102
103         str_pt = tmp_str;
104         tmp_str = strchr(tmp_str, '\n');
105         if (tmp_str) {
106             *tmp_str = '\0';
107         }
108
109         /* Get the exec timeout */
110         exec_timeout[exec_size] = atoi(str_pt);
111
112         /* Check if name is duplicated */
113         dup_entry = 0;
114         for (j = 0; j < exec_size; j++) {
115             if (strcmp(exec_names[j], exec_names[exec_size]) == 0) {
116                 if (exec_cmd[j][0] == '\0') {
117                     strncpy(exec_cmd[j], exec_cmd[exec_size], OS_FLSIZE);
118                     exec_cmd[j][OS_FLSIZE] = '\0';
119                     dup_entry = 1;
120                     break;
121                 } else if (exec_cmd[exec_size][0] == '\0') {
122                     dup_entry = 1;
123                 }
124             }
125         }
126
127         if (dup_entry) {
128             exec_cmd[exec_size][0] = '\0';
129             exec_names[exec_size][0] = '\0';
130             exec_timeout[exec_size] = 0;
131         } else {
132             exec_size++;
133         }
134     }
135
136     fclose(fp);
137     f_time_reading = 0;
138
139     return (1);
140 }
141
142 /* Returns a pointer to the command name (full path)
143  * Returns NULL if name cannot be found
144  * If timeout is not NULL, write the timeout for that
145  * command to it
146  */
147 char *GetCommandbyName(const char *name, int *timeout)
148 {
149     int i = 0;
150
151     for (; i < exec_size; i++) {
152         if (strcmp(name, exec_names[i]) == 0) {
153             *timeout = exec_timeout[i];
154             return (exec_cmd[i]);
155         }
156     }
157
158     return (NULL);
159 }
160
161 #ifndef WIN32
162
163 /* Execute command given. Must be a argv** NULL terminated.
164  * Prints error to log message in case of problems
165  */
166 void ExecCmd(char *const *cmd)
167 {
168     pid_t pid;
169
170     /* Fork and leave it running */
171     pid = fork();
172     if (pid == 0) {
173         if (execv(*cmd, cmd) < 0) {
174             merror(EXEC_CMDERROR, ARGV0, *cmd, strerror(errno));
175             exit(1);
176         }
177
178         exit(0);
179     }
180
181     return;
182 }
183
184 #else
185
186 void ExecCmd_Win32(char *cmd)
187 {
188     STARTUPINFO si;
189     PROCESS_INFORMATION pi;
190
191     ZeroMemory( &si, sizeof(si) );
192     si.cb = sizeof(si);
193     ZeroMemory( &pi, sizeof(pi) );
194
195     if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL,
196                        &si, &pi)) {
197         merror("%s: ERROR: Unable to create active response process. ", ARGV0);
198         return;
199     }
200
201     /* Wait until process exits */
202     WaitForSingleObject(pi.hProcess, INFINITE );
203
204     /* Close process and thread */
205     CloseHandle( pi.hProcess );
206     CloseHandle( pi.hThread );
207
208     return;
209 }
210 #endif
211