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 
22 #include "cfg.h"
23 #include "log.h"
24 #include "zbxgetopt.h"
25 #include "zbxembed.h"
26 #include "mutexs.h"
27 
28 const char	*progname;
29 const char	title_message[] = "zabbix_js";
30 const char	syslog_app_name[] = "zabbix_js";
31 const char	*usage_message[] = {
32 	"-s script-file", "-p input-param", "[-l log-level]", "[-t timeout]", NULL,
33 	"-s script-file", "-i input-file", "[-l log-level]", "[-t timeout]", NULL,
34 	"-h", NULL,
35 	"-V", NULL,
36 	NULL	/* end of text */
37 };
38 
39 unsigned char	program_type;
40 
41 const char	*help_message[] = {
42 	"Execute script using Zabbix embedded scripting engine.",
43 	"",
44 	"General options:",
45 	"  -s,--script script-file      Specify the filename of script to execute. Specify - for",
46 	"                               standard input.",
47 	"  -i,--input input-file        Specify input parameter file name. Specify - for",
48 	"                               standard input.",
49 	"  -p,--param input-param       Specify input parameter",
50 	"  -l,--loglevel log-level      Specify log level",
51 	"  -t,--timeout timeout         Specify timeout in seconds",
52 	"  -h --help                    Display this help message",
53 	"  -V --version                 Display version number",
54 	"",
55 	"Example:",
56 	"  zabbix_js -s script-file.js -p example",
57 	NULL	/* end of text */
58 };
59 
60 
61 /* long options */
62 struct zbx_option	longopts[] =
63 {
64 	{"script",			1,	NULL,	's'},
65 	{"input",			1,	NULL,	'i'},
66 	{"param",			1,	NULL,	'p'},
67 	{"loglevel",			1,	NULL,	'l'},
68 	{"timeout",			1,	NULL,	't'},
69 	{"help",			0,	NULL,	'h'},
70 	{"version",			0,	NULL,	'V'},
71 	{NULL}
72 };
73 
74 /* short options */
75 static char	shortopts[] = "s:i:p:hVl:t";
76 
77 /* end of COMMAND LINE OPTIONS */
78 
79 unsigned int	configured_tls_connect_mode;
80 unsigned int	configured_tls_accept_modes;	/* not used in zabbix_get, just for linking */
81 									/* with tls.c */
82 char	*CONFIG_TLS_CONNECT		= NULL;
83 char	*CONFIG_TLS_ACCEPT		= NULL;	/* not used in zabbix_js, just for linking with tls.c */
84 char	*CONFIG_TLS_CA_FILE		= NULL;
85 char	*CONFIG_TLS_CRL_FILE		= NULL;
86 char	*CONFIG_TLS_SERVER_CERT_ISSUER	= NULL;
87 char	*CONFIG_TLS_SERVER_CERT_SUBJECT	= NULL;
88 char	*CONFIG_TLS_CERT_FILE		= NULL;
89 char	*CONFIG_TLS_KEY_FILE		= NULL;
90 char	*CONFIG_TLS_PSK_IDENTITY	= NULL;
91 char	*CONFIG_TLS_PSK_FILE		= NULL;
92 
93 /* CONFIG_TLS_CIPHER_* are not used in zabbix_js, defined for linking with tls.c */
94 char	*CONFIG_TLS_CIPHER_CERT13	= NULL;
95 char	*CONFIG_TLS_CIPHER_CERT		= NULL;
96 char	*CONFIG_TLS_CIPHER_PSK13	= NULL;
97 char	*CONFIG_TLS_CIPHER_PSK		= NULL;
98 char	*CONFIG_TLS_CIPHER_ALL13	= NULL;
99 char	*CONFIG_TLS_CIPHER_ALL		= NULL;
100 char	*CONFIG_TLS_CIPHER_CMD13	= NULL;
101 char	*CONFIG_TLS_CIPHER_CMD		= NULL;
102 
103 int	CONFIG_PASSIVE_FORKS		= 0;	/* not used in zabbix_js, just for linking with tls.c */
104 int	CONFIG_ACTIVE_FORKS		= 0;	/* not used in zabbix_js, just for linking with tls.c */
105 
106 
107 char	*CONFIG_SOURCE_IP 		= NULL;
108 char	*CONFIG_SSL_CA_LOCATION		= NULL;
109 char	*CONFIG_SSL_CERT_LOCATION	= NULL;
110 char	*CONFIG_SSL_KEY_LOCATION	= NULL;
111 
read_file(const char * filename,char ** error)112 static char	*read_file(const char *filename, char **error)
113 {
114 	char	buffer[4096];
115 	int	n, fd;
116 	char	*data = NULL;
117 	size_t	data_alloc = 0, data_offset = 0;
118 
119 	if (0 != strcmp(filename, "-"))
120 	{
121 		if (-1 == (fd = open(filename, O_RDONLY)))
122 		{
123 			*error = zbx_strdup(NULL, zbx_strerror(errno));
124 			return NULL;
125 		}
126 	}
127 	else
128 		fd = STDIN_FILENO;
129 
130 	while (0 != (n = read(fd, buffer, sizeof(buffer))))
131 	{
132 		if (-1 == n)
133 		{
134 			if (fd != STDIN_FILENO)
135 				close(fd);
136 			zbx_free(data);
137 			*error = zbx_strdup(NULL, zbx_strerror(errno));
138 			return NULL;
139 		}
140 		zbx_strncpy_alloc(&data, &data_alloc, &data_offset, buffer, n);
141 	}
142 
143 	if (fd != STDIN_FILENO)
144 		close(fd);
145 
146 	return data;
147 }
148 
main(int argc,char ** argv)149 int	main(int argc, char **argv)
150 {
151 	int	ret = FAIL, loglevel = LOG_LEVEL_WARNING, timeout = 0;
152 	char	*script_file = NULL, *input_file = NULL, *param = NULL, ch, *script = NULL, *error = NULL,
153 		*result = NULL, script_error[MAX_STRING_LEN];
154 
155 	progname = get_program_name(argv[0]);
156 
157 	/* parse the command-line */
158 	while ((char)EOF != (ch = (char)zbx_getopt_long(argc, argv, shortopts, longopts, NULL)))
159 	{
160 		switch (ch)
161 		{
162 			case 's':
163 				if (NULL == script_file)
164 					script_file = zbx_strdup(NULL, zbx_optarg);
165 				break;
166 			case 'i':
167 				if (NULL == input_file)
168 					input_file = zbx_strdup(NULL, zbx_optarg);
169 				break;
170 			case 'p':
171 				if (NULL == param)
172 					param = zbx_strdup(NULL, zbx_optarg);
173 				break;
174 			case 'l':
175 				loglevel = atoi(zbx_optarg);
176 				break;
177 			case 't':
178 				timeout = atoi(zbx_optarg);
179 				break;
180 			case 'h':
181 				help();
182 				ret = SUCCEED;
183 				goto clean;
184 			case 'V':
185 				version();
186 				ret = SUCCEED;
187 				goto clean;
188 			default:
189 				usage();
190 				goto clean;
191 		}
192 	}
193 
194 	if (SUCCEED != zbx_locks_create(&error))
195 	{
196 		zbx_error("cannot create locks: %s", error);
197 		goto clean;
198 	}
199 
200 	if (SUCCEED != zabbix_open_log(LOG_TYPE_UNDEFINED, loglevel, NULL, &error))
201 	{
202 		zbx_error("cannot open log: %s", error);
203 		goto clean;
204 	}
205 
206 
207 	if (NULL == script_file || (NULL == input_file && NULL == param))
208 	{
209 		usage();
210 		goto close;
211 	}
212 
213 	if (NULL != input_file && NULL != param)
214 	{
215 		zbx_error("input and script options are mutually exclusive");
216 		goto close;
217 	}
218 
219 	if (0 == strcmp(script_file, "-") && NULL != input_file && 0 == strcmp(input_file, "-"))
220 	{
221 		zbx_error("cannot read script and input parameters from standard input at the same time");
222 		goto close;
223 	}
224 
225 	if (NULL == (script = read_file(script_file, &error)))
226 	{
227 		if (NULL != error)
228 			zbx_error("cannot read script file: %s", error);
229 		else
230 			zbx_error("cannot use empty script file");
231 
232 		goto close;
233 	}
234 
235 	if (NULL != input_file)
236 	{
237 		if (NULL == (param = read_file(input_file, &error)))
238 		{
239 			if (NULL != error)
240 				zbx_error("cannot read input file: %s", error);
241 			else
242 				zbx_error("cannot use empty input file");
243 
244 			goto close;
245 		}
246 	}
247 
248 	if (FAIL == zbx_es_execute_command(script, param, timeout, &result, script_error, sizeof(script_error), NULL))
249 	{
250 		zbx_error("error executing script:\n%s", script_error);
251 		goto close;
252 	}
253 	ret = SUCCEED;
254 	printf("\n%s\n", result);
255 close:
256 	zabbix_close_log();
257 clean:
258 	zbx_free(result);
259 	zbx_free(error);
260 	zbx_free(script);
261 	zbx_free(script_file);
262 	zbx_free(input_file);
263 	zbx_free(param);
264 
265 	return SUCCEED == ret ? EXIT_SUCCESS : EXIT_FAILURE;
266 }
267