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 
ONLY_ACTIVE(AGENT_REQUEST * request,AGENT_RESULT * result)93 static int	ONLY_ACTIVE(AGENT_REQUEST *request, AGENT_RESULT *result)
94 {
95 	ZBX_UNUSED(request);
96 
97 	SET_MSG_RESULT(result, zbx_strdup(NULL, "Accessible only as active check."));
98 
99 	return SYSINFO_RET_FAIL;
100 }
101 
EXECUTE_USER_PARAMETER(AGENT_REQUEST * request,AGENT_RESULT * result)102 int	EXECUTE_USER_PARAMETER(AGENT_REQUEST *request, AGENT_RESULT *result)
103 {
104 	char	*command;
105 
106 	if (1 != request->nparam)
107 	{
108 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
109 		return SYSINFO_RET_FAIL;
110 	}
111 
112 	command = get_rparam(request, 0);
113 
114 	return EXECUTE_STR(command, result);
115 }
116 
EXECUTE_STR(const char * command,AGENT_RESULT * result)117 int	EXECUTE_STR(const char *command, AGENT_RESULT *result)
118 {
119 	int		ret = SYSINFO_RET_FAIL;
120 	char		*cmd_result = NULL, error[MAX_STRING_LEN];
121 
122 	if (SUCCEED != zbx_execute(command, &cmd_result, error, sizeof(error), CONFIG_TIMEOUT,
123 			ZBX_EXIT_CODE_CHECKS_DISABLED))
124 	{
125 		SET_MSG_RESULT(result, zbx_strdup(NULL, error));
126 		goto out;
127 	}
128 
129 	zbx_rtrim(cmd_result, ZBX_WHITESPACE);
130 
131 	zabbix_log(LOG_LEVEL_DEBUG, "%s() command:'%s' len:" ZBX_FS_SIZE_T " cmd_result:'%.20s'",
132 			__func__, command, (zbx_fs_size_t)strlen(cmd_result), cmd_result);
133 
134 	SET_TEXT_RESULT(result, zbx_strdup(NULL, cmd_result));
135 
136 	ret = SYSINFO_RET_OK;
137 out:
138 	zbx_free(cmd_result);
139 
140 	return ret;
141 }
142 
EXECUTE_DBL(const char * command,AGENT_RESULT * result)143 int	EXECUTE_DBL(const char *command, AGENT_RESULT *result)
144 {
145 	if (SYSINFO_RET_OK != EXECUTE_STR(command, result))
146 		return SYSINFO_RET_FAIL;
147 
148 	if (NULL == GET_DBL_RESULT(result))
149 	{
150 		zabbix_log(LOG_LEVEL_WARNING, "Remote command [%s] result is not double", command);
151 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid result. Double is expected."));
152 		return SYSINFO_RET_FAIL;
153 	}
154 
155 	UNSET_RESULT_EXCLUDING(result, AR_DOUBLE);
156 
157 	return SYSINFO_RET_OK;
158 }
159 
EXECUTE_INT(const char * command,AGENT_RESULT * result)160 int	EXECUTE_INT(const char *command, AGENT_RESULT *result)
161 {
162 	if (SYSINFO_RET_OK != EXECUTE_STR(command, result))
163 		return SYSINFO_RET_FAIL;
164 
165 	if (NULL == GET_UI64_RESULT(result))
166 	{
167 		zabbix_log(LOG_LEVEL_WARNING, "Remote command [%s] result is not unsigned integer", command);
168 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid result. Unsigned integer is expected."));
169 		return SYSINFO_RET_FAIL;
170 	}
171 
172 	UNSET_RESULT_EXCLUDING(result, AR_UINT64);
173 
174 	return SYSINFO_RET_OK;
175 }
176 
system_run(AGENT_REQUEST * request,AGENT_RESULT * result,int level)177 static int	system_run(AGENT_REQUEST *request, AGENT_RESULT *result, int level)
178 {
179 	char	*command, *flag;
180 
181 	if (2 < request->nparam)
182 	{
183 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
184 		return SYSINFO_RET_FAIL;
185 	}
186 
187 	command = get_rparam(request, 0);
188 	flag = get_rparam(request, 1);
189 
190 	if (NULL == command || '\0' == *command)
191 	{
192 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
193 		return SYSINFO_RET_FAIL;
194 	}
195 
196 	zabbix_log(level, "Executing command '%s'", command);
197 
198 	if (NULL == flag || '\0' == *flag || 0 == strcmp(flag, "wait"))	/* default parameter */
199 	{
200 		return EXECUTE_STR(command, result);
201 	}
202 	else if (0 == strcmp(flag, "nowait"))
203 	{
204 		if (SUCCEED != zbx_execute_nowait(command))
205 		{
206 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot execute command."));
207 			return SYSINFO_RET_FAIL;
208 		}
209 	}
210 	else
211 	{
212 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
213 		return SYSINFO_RET_FAIL;
214 	}
215 
216 	SET_UI64_RESULT(result, 1);
217 
218 	return SYSINFO_RET_OK;
219 }
220 
SYSTEM_RUN(AGENT_REQUEST * request,AGENT_RESULT * result)221 static int	SYSTEM_RUN(AGENT_REQUEST *request, AGENT_RESULT *result)
222 {
223 	int	level;
224 
225 	level = LOG_LEVEL_DEBUG;
226 
227 	if (0 != CONFIG_LOG_REMOTE_COMMANDS)
228 		level = LOG_LEVEL_WARNING;
229 
230 	return system_run(request, result, level);
231 }
232 
SYSTEM_RUN_LOCAL(AGENT_REQUEST * request,AGENT_RESULT * result)233 static int	SYSTEM_RUN_LOCAL(AGENT_REQUEST *request, AGENT_RESULT *result)
234 {
235 	return system_run(request, result, LOG_LEVEL_DEBUG);
236 }
237 
238