1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 **/
19 
20 #include "common.h"
21 #include "sysinfo.h"
22 
23 #include "log.h"
24 
25 #include "file.h"
26 #include "dir.h"
27 #include "net.h"
28 #include "dns.h"
29 #include "system.h"
30 #include "zabbix_stats.h"
31 #include "zbxexec.h"
32 
33 #if !defined(_WINDOWS)
34 #	define VFS_TEST_FILE "/etc/passwd"
35 #	define VFS_TEST_REGEXP "root"
36 #	define VFS_TEST_DIR  "/var/log"
37 #else
38 #	define VFS_TEST_FILE "c:\\windows\\win.ini"
39 #	define VFS_TEST_REGEXP "fonts"
40 #	define VFS_TEST_DIR  "c:\\windows"
41 #endif
42 
43 extern int	CONFIG_TIMEOUT;
44 
45 static int	ONLY_ACTIVE(AGENT_REQUEST *request, AGENT_RESULT *result);
46 static int	SYSTEM_RUN(AGENT_REQUEST *request, AGENT_RESULT *result);
47 static int	SYSTEM_RUN_LOCAL(AGENT_REQUEST *request, AGENT_RESULT *result);
48 
49 ZBX_METRIC	parameters_common_local[] =
50 /*	KEY			FLAG		FUNCTION		TEST PARAMETERS */
51 {
52 	{"system.run",		CF_HAVEPARAMS,	SYSTEM_RUN_LOCAL, 	"echo test"},
53 	{NULL}
54 };
55 
56 ZBX_METRIC	parameters_common[] =
57 /*	KEY			FLAG		FUNCTION		TEST PARAMETERS */
58 {
59 	{"system.localtime",	CF_HAVEPARAMS,	SYSTEM_LOCALTIME,	"utc"},
60 	{"system.run",		CF_HAVEPARAMS,	SYSTEM_RUN,		"echo test"},
61 
62 	{"vfs.file.size",	CF_HAVEPARAMS,	VFS_FILE_SIZE,		VFS_TEST_FILE},
63 	{"vfs.file.time",	CF_HAVEPARAMS,	VFS_FILE_TIME,		VFS_TEST_FILE ",modify"},
64 	{"vfs.file.exists",	CF_HAVEPARAMS,	VFS_FILE_EXISTS,	VFS_TEST_FILE},
65 	{"vfs.file.contents",	CF_HAVEPARAMS,	VFS_FILE_CONTENTS,	VFS_TEST_FILE},
66 	{"vfs.file.regexp",	CF_HAVEPARAMS,	VFS_FILE_REGEXP,	VFS_TEST_FILE "," VFS_TEST_REGEXP},
67 	{"vfs.file.regmatch",	CF_HAVEPARAMS,	VFS_FILE_REGMATCH,	VFS_TEST_FILE "," VFS_TEST_REGEXP},
68 	{"vfs.file.md5sum",	CF_HAVEPARAMS,	VFS_FILE_MD5SUM,	VFS_TEST_FILE},
69 	{"vfs.file.cksum",	CF_HAVEPARAMS,	VFS_FILE_CKSUM,		VFS_TEST_FILE},
70 
71 	{"vfs.dir.size",	CF_HAVEPARAMS,	VFS_DIR_SIZE,		VFS_TEST_DIR},
72 	{"vfs.dir.count",	CF_HAVEPARAMS,	VFS_DIR_COUNT,		VFS_TEST_DIR},
73 
74 	{"net.dns",		CF_HAVEPARAMS,	NET_DNS,		",zabbix.com"},
75 	{"net.dns.record",	CF_HAVEPARAMS,	NET_DNS_RECORD,		",zabbix.com"},
76 	{"net.tcp.dns",		CF_HAVEPARAMS,	NET_DNS,		",zabbix.com"}, /* deprecated */
77 	{"net.tcp.dns.query",	CF_HAVEPARAMS,	NET_DNS_RECORD,		",zabbix.com"}, /* deprecated */
78 	{"net.tcp.port",	CF_HAVEPARAMS,	NET_TCP_PORT,		",80"},
79 
80 	{"system.users.num",	0,		SYSTEM_USERS_NUM,	NULL},
81 
82 	{"log",			CF_HAVEPARAMS,	ONLY_ACTIVE,		"logfile"},
83 	{"log.count",		CF_HAVEPARAMS,	ONLY_ACTIVE,		"logfile"},
84 	{"logrt",		CF_HAVEPARAMS,	ONLY_ACTIVE,		"logfile"},
85 	{"logrt.count",		CF_HAVEPARAMS,	ONLY_ACTIVE,		"logfile"},
86 	{"eventlog",		CF_HAVEPARAMS,	ONLY_ACTIVE,		"system"},
87 
88 	{"zabbix.stats",	CF_HAVEPARAMS,	ZABBIX_STATS,		"127.0.0.1,10051"},
89 
90 	{NULL}
91 };
92 
93 static const char	*user_parameter_dir = NULL;
94 
set_user_parameter_dir(const char * path)95 void	set_user_parameter_dir(const char *path)
96 {
97 	user_parameter_dir = path;
98 }
99 
ONLY_ACTIVE(AGENT_REQUEST * request,AGENT_RESULT * result)100 static int	ONLY_ACTIVE(AGENT_REQUEST *request, AGENT_RESULT *result)
101 {
102 	ZBX_UNUSED(request);
103 
104 	SET_MSG_RESULT(result, zbx_strdup(NULL, "Accessible only as active check."));
105 
106 	return SYSINFO_RET_FAIL;
107 }
108 
execute_str(const char * command,AGENT_RESULT * result,const char * dir)109 static int	execute_str(const char *command, AGENT_RESULT *result, const char* dir)
110 {
111 	int		ret = SYSINFO_RET_FAIL;
112 	char		*cmd_result = NULL, error[MAX_STRING_LEN];
113 
114 	if (SUCCEED != zbx_execute(command, &cmd_result, error, sizeof(error), CONFIG_TIMEOUT,
115 			ZBX_EXIT_CODE_CHECKS_DISABLED, dir))
116 	{
117 		SET_MSG_RESULT(result, zbx_strdup(NULL, error));
118 		goto out;
119 	}
120 
121 	zbx_rtrim(cmd_result, ZBX_WHITESPACE);
122 
123 	zabbix_log(LOG_LEVEL_DEBUG, "%s() command:'%s' len:" ZBX_FS_SIZE_T " cmd_result:'%.20s'",
124 			__func__, command, (zbx_fs_size_t)strlen(cmd_result), cmd_result);
125 
126 	SET_TEXT_RESULT(result, zbx_strdup(NULL, cmd_result));
127 
128 	ret = SYSINFO_RET_OK;
129 out:
130 	zbx_free(cmd_result);
131 
132 	return ret;
133 }
134 
EXECUTE_USER_PARAMETER(AGENT_REQUEST * request,AGENT_RESULT * result)135 int	EXECUTE_USER_PARAMETER(AGENT_REQUEST *request, AGENT_RESULT *result)
136 {
137 	if (1 != request->nparam)
138 	{
139 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
140 		return SYSINFO_RET_FAIL;
141 	}
142 
143 	return execute_str(get_rparam(request, 0), result, user_parameter_dir);
144 }
145 
EXECUTE_STR(const char * command,AGENT_RESULT * result)146 int	EXECUTE_STR(const char *command, AGENT_RESULT *result)
147 {
148 	return execute_str(command, result, NULL);
149 }
150 
EXECUTE_DBL(const char * command,AGENT_RESULT * result)151 int	EXECUTE_DBL(const char *command, AGENT_RESULT *result)
152 {
153 	if (SYSINFO_RET_OK != EXECUTE_STR(command, result))
154 		return SYSINFO_RET_FAIL;
155 
156 	if (NULL == GET_DBL_RESULT(result))
157 	{
158 		zabbix_log(LOG_LEVEL_WARNING, "Remote command [%s] result is not double", command);
159 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid result. Double is expected."));
160 		return SYSINFO_RET_FAIL;
161 	}
162 
163 	UNSET_RESULT_EXCLUDING(result, AR_DOUBLE);
164 
165 	return SYSINFO_RET_OK;
166 }
167 
EXECUTE_INT(const char * command,AGENT_RESULT * result)168 int	EXECUTE_INT(const char *command, AGENT_RESULT *result)
169 {
170 	if (SYSINFO_RET_OK != EXECUTE_STR(command, result))
171 		return SYSINFO_RET_FAIL;
172 
173 	if (NULL == GET_UI64_RESULT(result))
174 	{
175 		zabbix_log(LOG_LEVEL_WARNING, "Remote command [%s] result is not unsigned integer", command);
176 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid result. Unsigned integer is expected."));
177 		return SYSINFO_RET_FAIL;
178 	}
179 
180 	UNSET_RESULT_EXCLUDING(result, AR_UINT64);
181 
182 	return SYSINFO_RET_OK;
183 }
184 
system_run(AGENT_REQUEST * request,AGENT_RESULT * result,int level)185 static int	system_run(AGENT_REQUEST *request, AGENT_RESULT *result, int level)
186 {
187 	char	*command, *flag;
188 
189 	if (2 < request->nparam)
190 	{
191 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
192 		return SYSINFO_RET_FAIL;
193 	}
194 
195 	command = get_rparam(request, 0);
196 	flag = get_rparam(request, 1);
197 
198 	if (NULL == command || '\0' == *command)
199 	{
200 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
201 		return SYSINFO_RET_FAIL;
202 	}
203 
204 	zabbix_log(level, "Executing command '%s'", command);
205 
206 	if (NULL == flag || '\0' == *flag || 0 == strcmp(flag, "wait"))	/* default parameter */
207 	{
208 		return EXECUTE_STR(command, result);
209 	}
210 	else if (0 == strcmp(flag, "nowait"))
211 	{
212 		if (SUCCEED != zbx_execute_nowait(command))
213 		{
214 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot execute command."));
215 			return SYSINFO_RET_FAIL;
216 		}
217 	}
218 	else
219 	{
220 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
221 		return SYSINFO_RET_FAIL;
222 	}
223 
224 	SET_UI64_RESULT(result, 1);
225 
226 	return SYSINFO_RET_OK;
227 }
228 
SYSTEM_RUN(AGENT_REQUEST * request,AGENT_RESULT * result)229 static int	SYSTEM_RUN(AGENT_REQUEST *request, AGENT_RESULT *result)
230 {
231 	int	level;
232 
233 	level = LOG_LEVEL_DEBUG;
234 
235 	if (0 != CONFIG_LOG_REMOTE_COMMANDS)
236 		level = LOG_LEVEL_WARNING;
237 
238 	return system_run(request, result, level);
239 }
240 
SYSTEM_RUN_LOCAL(AGENT_REQUEST * request,AGENT_RESULT * result)241 static int	SYSTEM_RUN_LOCAL(AGENT_REQUEST *request, AGENT_RESULT *result)
242 {
243 	return system_run(request, result, LOG_LEVEL_DEBUG);
244 }
245 
246