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 "comms.h"
22 #include "zbxserver.h"
23 #include "db.h"
24 #include "log.h"
25 #include "../scripts/scripts.h"
26 
27 #include "trapper_auth.h"
28 #include "nodecommand.h"
29 #include "../../libs/zbxserver/get_host_from_event.h"
30 #include "../../libs/zbxserver/zabbix_users.h"
31 
32 /******************************************************************************
33  *                                                                            *
34  * Function: execute_remote_script                                            *
35  *                                                                            *
36  * Purpose: execute remote command and wait for the result                    *
37  *                                                                            *
38  * Return value:  SUCCEED - the remote command was executed successfully      *
39  *                FAIL    - an error occurred                                 *
40  *                                                                            *
41  ******************************************************************************/
execute_remote_script(const zbx_script_t * script,const DC_HOST * host,char ** info,char * error,size_t max_error_len)42 static int	execute_remote_script(const zbx_script_t *script, const DC_HOST *host, char **info, char *error,
43 		size_t max_error_len)
44 {
45 	int		time_start;
46 	zbx_uint64_t	taskid;
47 	DB_RESULT	result = NULL;
48 	DB_ROW		row;
49 
50 	if (0 == (taskid = zbx_script_create_task(script, host, 0, time(NULL))))
51 	{
52 		zbx_snprintf(error, max_error_len, "Cannot create remote command task.");
53 		return FAIL;
54 	}
55 
56 	for (time_start = time(NULL); SEC_PER_MIN > time(NULL) - time_start; sleep(1))
57 	{
58 		result = DBselect(
59 				"select tr.status,tr.info"
60 				" from task t"
61 				" left join task_remote_command_result tr"
62 					" on tr.taskid=t.taskid"
63 				" where tr.parent_taskid=" ZBX_FS_UI64,
64 				taskid);
65 
66 		if (NULL != (row = DBfetch(result)))
67 		{
68 			int	ret;
69 
70 			if (SUCCEED == (ret = atoi(row[0])))
71 				*info = zbx_strdup(*info, row[1]);
72 			else
73 				zbx_strlcpy(error, row[1], max_error_len);
74 
75 			DBfree_result(result);
76 			return ret;
77 		}
78 
79 		DBfree_result(result);
80 	}
81 
82 	zbx_snprintf(error, max_error_len, "Timeout while waiting for remote command result.");
83 
84 	return FAIL;
85 }
86 
87 /******************************************************************************
88  *                                                                            *
89  * Function: auditlog_global_script                                           *
90  *                                                                            *
91  * Purpose: record global script execution results into audit log             *
92  *                                                                            *
93  * Comments: 'hostid' should be always > 0. 'eventid' is > 0 in case of       *
94  *           "manual script on event"                                         *
95  *                                                                            *
96  ******************************************************************************/
auditlog_global_script(const zbx_script_t * script,zbx_uint64_t hostid,zbx_uint64_t eventid,zbx_uint64_t proxy_hostid,zbx_uint64_t userid,const char * clientip,const char * output,const char * error)97 static void	auditlog_global_script(const zbx_script_t *script, zbx_uint64_t hostid, zbx_uint64_t eventid,
98 		zbx_uint64_t proxy_hostid, zbx_uint64_t userid, const char *clientip, const char *output,
99 		const char *error)
100 {
101 	int		now;
102 	zbx_uint64_t	auditid;
103 	char		execute_on_s[MAX_ID_LEN + 1], hostid_s[MAX_ID_LEN + 1], eventid_s[MAX_ID_LEN + 1],
104 			proxy_hostid_s[MAX_ID_LEN + 1];
105 
106 	now = time(NULL);
107 	auditid = DBget_maxid("auditlog");
108 	zbx_snprintf(execute_on_s, sizeof(execute_on_s), "%hhu", script->execute_on);
109 
110 	zbx_snprintf(hostid_s, sizeof(hostid_s), ZBX_FS_UI64, hostid);
111 
112 	if (0 != eventid)
113 		zbx_snprintf(eventid_s, sizeof(eventid_s), ZBX_FS_UI64, eventid);
114 
115 	if (0 != proxy_hostid)
116 		zbx_snprintf(proxy_hostid_s, sizeof(proxy_hostid_s), ZBX_FS_UI64, proxy_hostid);
117 
118 	do
119 	{
120 		zbx_db_insert_t	db_audit, db_details;
121 
122 		zbx_db_insert_prepare(&db_audit, "auditlog", "auditid", "userid", "clock", "action", "resourcetype",
123 				"ip", "resourceid", NULL);
124 
125 		zbx_db_insert_prepare(&db_details, "auditlog_details", "auditdetailid", "auditid", "table_name",
126 				"field_name", "newvalue", NULL);
127 
128 		DBbegin();
129 
130 		zbx_db_insert_add_values(&db_audit, auditid, userid, now, AUDIT_ACTION_EXECUTE, AUDIT_RESOURCE_SCRIPT,
131 				clientip, script->scriptid);
132 
133 
134 		zbx_db_insert_add_values(&db_details, __UINT64_C(0), auditid, "script", "execute_on", execute_on_s);
135 
136 		if (0 != eventid)
137 			zbx_db_insert_add_values(&db_details, __UINT64_C(0), auditid, "script", "eventid", eventid_s);
138 
139 		zbx_db_insert_add_values(&db_details, __UINT64_C(0), auditid, "script", "hostid", hostid_s);
140 
141 		if (0 != proxy_hostid)
142 		{
143 			zbx_db_insert_add_values(&db_details, __UINT64_C(0), auditid, "script", "proxy_hostid",
144 					proxy_hostid_s);
145 		}
146 
147 		if (ZBX_SCRIPT_TYPE_WEBHOOK != script->type)
148 		{
149 			zbx_db_insert_add_values(&db_details, __UINT64_C(0), auditid, "script", "command",
150 					script->command_orig);
151 		}
152 
153 		if (NULL != output)
154 			zbx_db_insert_add_values(&db_details, __UINT64_C(0), auditid, "script", "output", output);
155 
156 		if (NULL != error)
157 			zbx_db_insert_add_values(&db_details, __UINT64_C(0), auditid, "script", "error", error);
158 
159 		zbx_db_insert_execute(&db_audit);
160 		zbx_db_insert_clean(&db_audit);
161 
162 		zbx_db_insert_autoincrement(&db_details, "auditdetailid");
163 		zbx_db_insert_execute(&db_details);
164 		zbx_db_insert_clean(&db_details);
165 	}
166 	while (ZBX_DB_DOWN == DBcommit());
167 }
168 
169 /******************************************************************************
170  *                                                                            *
171  * Function: zbx_check_user_administration_permissions                        *
172  *                                                                            *
173  * Purpose: check if the user has specific or default access for              *
174  *          administration actions                                            *
175  *                                                                            *
176  * Return value:  SUCCEED - the access is granted                             *
177  *                FAIL    - the access is denied                              *
178  *                                                                            *
179  ******************************************************************************/
zbx_check_user_administration_actions_permissions(const zbx_user_t * user,const char * role_rule)180 static int	zbx_check_user_administration_actions_permissions(const zbx_user_t *user, const char *role_rule)
181 {
182 	int		ret = FAIL;
183 	DB_RESULT	result;
184 	DB_ROW		row;
185 
186 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() userid:" ZBX_FS_UI64 , __func__, user->userid);
187 
188 	result = DBselect("select value_int,name from role_rule where roleid=" ZBX_FS_UI64
189 			" and (name='%s' or name='%s')", user->roleid, role_rule,
190 			ZBX_USER_ROLE_PERMISSION_ACTIONS_DEFAULT_ACCESS);
191 
192 	while (NULL != (row = DBfetch(result)))
193 	{
194 		if (0 == strcmp(role_rule, row[1]))
195 		{
196 			if (ROLE_PERM_ALLOW == atoi(row[0]))
197 				ret = SUCCEED;
198 			else
199 				ret = FAIL;
200 			break;
201 		}
202 		else if (0 == strcmp(ZBX_USER_ROLE_PERMISSION_ACTIONS_DEFAULT_ACCESS, row[1]))
203 		{
204 			if (ROLE_PERM_ALLOW == atoi(row[0]))
205 				ret = SUCCEED;
206 		}
207 		else
208 			THIS_SHOULD_NEVER_HAPPEN;
209 	}
210 	DBfree_result(result);
211 
212 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
213 
214 	return ret;
215 }
216 
zbx_get_script_details(zbx_uint64_t scriptid,zbx_script_t * script,int * scope,zbx_uint64_t * usrgrpid,zbx_uint64_t * groupid,char * error,size_t error_len)217 static int	zbx_get_script_details(zbx_uint64_t scriptid, zbx_script_t *script, int *scope, zbx_uint64_t *usrgrpid,
218 		zbx_uint64_t *groupid, char *error, size_t error_len)
219 {
220 	int		ret = FAIL;
221 	DB_RESULT	db_result;
222 	DB_ROW		row;
223 	zbx_uint64_t	usrgrpid_l, groupid_l;
224 
225 	db_result = DBselect("select command,host_access,usrgrpid,groupid,type,execute_on,timeout,scope,port,authtype"
226 			",username,password,publickey,privatekey"
227 			" from scripts"
228 			" where scriptid=" ZBX_FS_UI64, scriptid);
229 
230 	if (NULL == db_result)
231 	{
232 		zbx_strlcpy(error, "Cannot select from table 'scripts'.", error_len);
233 		return FAIL;
234 	}
235 
236 	if (NULL == (row = DBfetch(db_result)))
237 	{
238 		zbx_strlcpy(error, "Script not found.", error_len);
239 		goto fail;
240 	}
241 
242 	ZBX_DBROW2UINT64(usrgrpid_l, row[2]);
243 	*usrgrpid = usrgrpid_l;
244 
245 	ZBX_DBROW2UINT64(groupid_l, row[3]);
246 	*groupid = groupid_l;
247 
248 	ZBX_STR2UCHAR(script->type, row[4]);
249 
250 	if (ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT == script->type)
251 		ZBX_STR2UCHAR(script->execute_on, row[5]);
252 
253 	if (ZBX_SCRIPT_TYPE_SSH == script->type)
254 	{
255 		ZBX_STR2UCHAR(script->authtype, row[9]);
256 		script->publickey = zbx_strdup(script->publickey, row[12]);
257 		script->privatekey = zbx_strdup(script->privatekey, row[13]);
258 	}
259 
260 	if (ZBX_SCRIPT_TYPE_SSH == script->type || ZBX_SCRIPT_TYPE_TELNET == script->type)
261 	{
262 		script->port = zbx_strdup(script->port, row[8]);
263 		script->username = zbx_strdup(script->username, row[10]);
264 		script->password = zbx_strdup(script->password, row[11]);
265 	}
266 
267 	script->command = zbx_strdup(script->command, row[0]);
268 	script->command_orig = zbx_strdup(script->command_orig, row[0]);
269 
270 	script->scriptid = scriptid;
271 
272 	ZBX_STR2UCHAR(script->host_access, row[1]);
273 
274 	if (SUCCEED != is_time_suffix(row[6], &script->timeout, ZBX_LENGTH_UNLIMITED))
275 	{
276 		zbx_strlcpy(error, "Invalid timeout value in script configuration.", error_len);
277 		goto fail;
278 	}
279 
280 	*scope = atoi(row[7]);
281 
282 	ret = SUCCEED;
283 fail:
284 	DBfree_result(db_result);
285 
286 	return ret;
287 }
288 
is_user_in_allowed_group(zbx_uint64_t userid,zbx_uint64_t usrgrpid,char * error,size_t error_len)289 static int	is_user_in_allowed_group(zbx_uint64_t userid, zbx_uint64_t usrgrpid, char *error, size_t error_len)
290 {
291 	DB_RESULT	result;
292 	int		ret = FAIL;
293 
294 	result = DBselect("select null"
295 			" from users_groups"
296 			" where usrgrpid=" ZBX_FS_UI64
297 			" and userid=" ZBX_FS_UI64,
298 			usrgrpid, userid);
299 
300 	if (NULL == result)
301 	{
302 		zbx_strlcpy(error, "Database error, cannot get user rights.", error_len);
303 		goto fail;
304 	}
305 
306 	if (NULL == DBfetch(result))
307 		zbx_strlcpy(error, "User has no rights to execute this script.", error_len);
308 	else
309 		ret = SUCCEED;
310 
311 	DBfree_result(result);
312 fail:
313 	return ret;
314 }
315 
316 /******************************************************************************
317  *                                                                            *
318  * Function: zbx_check_event_end_recovery_event                               *
319  *                                                                            *
320  * Purpose: check if the specified event id corresponds to a problem event    *
321  *          caused by a trigger, find its recovery event (if it exists)       *
322  *                                                                            *
323  * Parameters:  eventid       - [IN] the id of event                          *
324  *              r_eventid     - [OUT] the id of recovery event (0 if there is *
325  *                              no recovery event                             *
326  *              error         - [OUT] the error message buffer                *
327  *              error_len     - [IN] the size of error message buffer         *
328  *                                                                            *
329  * Return value:  SUCCEED or FAIL (with 'error' message)                      *
330  *                                                                            *
331  ******************************************************************************/
zbx_check_event_end_recovery_event(zbx_uint64_t eventid,zbx_uint64_t * r_eventid,char * error,size_t error_len)332 static int	zbx_check_event_end_recovery_event(zbx_uint64_t eventid, zbx_uint64_t *r_eventid, char *error,
333 		size_t error_len)
334 {
335 	DB_RESULT	db_result;
336 	DB_ROW		row;
337 
338 	if (NULL == (db_result = DBselect("select r_eventid from event_recovery where eventid="ZBX_FS_UI64, eventid)))
339 	{
340 		zbx_strlcpy(error, "Database error, cannot read from 'events' and 'event_recovery' tables.", error_len);
341 		return FAIL;
342 	}
343 
344 	if (NULL == (row = DBfetch(db_result)))
345 		*r_eventid = 0;
346 	else
347 		ZBX_DBROW2UINT64(*r_eventid, row[0]);
348 
349 	DBfree_result(db_result);
350 
351 	return SUCCEED;
352 }
353 
354 /******************************************************************************
355  *                                                                            *
356  * Function: execute_script                                                   *
357  *                                                                            *
358  * Purpose: executing command                                                 *
359  *                                                                            *
360  * Parameters:  scriptid - [IN] the id of a script to be executed             *
361  *              hostid   - [IN] the host the script will be executed on       *
362  *              eventid  - [IN] the id of an event                            *
363  *              user     - [IN] the user who executes the command             *
364  *              clientip - [IN] the IP of client                              *
365  *              result   - [OUT] the result of a script execution             *
366  *              debug    - [OUT] the debug data (optional)                    *
367  *                                                                            *
368  * Return value:  SUCCEED - processed successfully                            *
369  *                FAIL - an error occurred                                    *
370  *                                                                            *
371  * Comments: either 'hostid' or 'eventid' must be > 0, but not both           *
372  *                                                                            *
373  ******************************************************************************/
execute_script(zbx_uint64_t scriptid,zbx_uint64_t hostid,zbx_uint64_t eventid,zbx_user_t * user,const char * clientip,char ** result,char ** debug)374 static int	execute_script(zbx_uint64_t scriptid, zbx_uint64_t hostid, zbx_uint64_t eventid, zbx_user_t *user,
375 		const char *clientip, char **result, char **debug)
376 {
377 	int			ret = FAIL, scope = 0, i, macro_type;
378 	DC_HOST			host;
379 	zbx_script_t		script;
380 	zbx_uint64_t		usrgrpid, groupid;
381 	zbx_vector_uint64_t	eventids;
382 	zbx_vector_ptr_t	events;
383 	zbx_vector_ptr_pair_t	webhook_params;
384 	char			*user_timezone = NULL, *webhook_params_json = NULL, error[MAX_STRING_LEN];
385 	DB_EVENT		*problem_event = NULL, *recovery_event = NULL;
386 
387 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() scriptid:" ZBX_FS_UI64 " hostid:" ZBX_FS_UI64 " eventid:" ZBX_FS_UI64
388 			" userid:" ZBX_FS_UI64 " clientip:%s",
389 			__func__, scriptid, hostid, eventid, user->userid, clientip);
390 
391 	*error = '\0';
392 	memset(&host, 0, sizeof(host));
393 	zbx_vector_uint64_create(&eventids);
394 	zbx_vector_ptr_create(&events);
395 	zbx_vector_ptr_pair_create(&webhook_params);
396 
397 	zbx_script_init(&script);
398 
399 	if (SUCCEED != zbx_get_script_details(scriptid, &script, &scope, &usrgrpid, &groupid, error, sizeof(error)))
400 		goto fail;
401 
402 	/* validate script permissions */
403 
404 	if (0 < usrgrpid &&
405 			USER_TYPE_SUPER_ADMIN != user->type &&
406 			SUCCEED != is_user_in_allowed_group(user->userid, usrgrpid, error, sizeof(error)))
407 	{
408 		goto fail;
409 	}
410 
411 	if (0 != hostid)
412 	{
413 		if (ZBX_SCRIPT_SCOPE_HOST != scope)
414 		{
415 			zbx_snprintf(error, sizeof(error), "Script is not allowed in manual host action: scope:%d",
416 					scope);
417 			goto fail;
418 		}
419 	}
420 	else if (ZBX_SCRIPT_SCOPE_EVENT != scope)
421 	{
422 		zbx_snprintf(error, sizeof(error), "Script is not allowed in manual event action: scope:%d", scope);
423 		goto fail;
424 	}
425 
426 	/* get host or event details */
427 
428 	if (0 != hostid)
429 	{
430 		if (SUCCEED != DCget_host_by_hostid(&host, hostid))
431 		{
432 			zbx_strlcpy(error, "Unknown host identifier.", sizeof(error));
433 			goto fail;
434 		}
435 	}
436 	else /* eventid */
437 	{
438 		zbx_uint64_t	r_eventid;
439 
440 		if (SUCCEED != zbx_check_event_end_recovery_event(eventid, &r_eventid, error, sizeof(error)))
441 			goto fail;
442 
443 		zbx_vector_uint64_reserve(&eventids, 2);
444 		zbx_vector_ptr_reserve(&events, 2);
445 
446 		zbx_vector_uint64_append(&eventids, eventid);	/* problem event in element [0]*/
447 
448 		if (0 != r_eventid)				/* optional recovery event in element [1] */
449 			zbx_vector_uint64_append(&eventids, r_eventid);
450 
451 		zbx_db_get_events_by_eventids(&eventids, &events);
452 
453 		if (events.values_num != eventids.values_num)
454 		{
455 			zbx_strlcpy(error, "Specified event data not found.", sizeof(error));
456 			goto fail;
457 		}
458 
459 		switch (events.values_num)
460 		{
461 			case 1:
462 				if (eventid == ((DB_EVENT *)(events.values[0]))->eventid)
463 				{
464 					problem_event = events.values[0];
465 				}
466 				else
467 				{
468 					zbx_strlcpy(error, "Specified event data not found.", sizeof(error));
469 					goto fail;
470 				}
471 				break;
472 			case 2:
473 				if (r_eventid == ((DB_EVENT *)(events.values[0]))->eventid)
474 				{
475 					problem_event = events.values[1];
476 					recovery_event = events.values[0];
477 				}
478 				else
479 				{
480 					problem_event = events.values[0];
481 					recovery_event = events.values[1];
482 				}
483 				break;
484 			default:
485 				THIS_SHOULD_NEVER_HAPPEN;
486 				zbx_snprintf(error, sizeof(error), "Internal error in %s() events.values_num:%d",
487 						__func__, events.values_num);
488 				goto fail;
489 		}
490 
491 		if (EVENT_SOURCE_TRIGGERS != problem_event->source)
492 		{
493 			zbx_strlcpy(error, "The source of specified event is not a trigger.", sizeof(error));
494 			goto fail;
495 		}
496 
497 		if (TRIGGER_VALUE_PROBLEM != problem_event->value)
498 		{
499 			zbx_strlcpy(error, "The specified event is not a problem event.", sizeof(error));
500 			goto fail;
501 		}
502 
503 		if (SUCCEED != get_host_from_event((NULL != recovery_event) ? recovery_event : problem_event,
504 				&host, error, sizeof(error)))
505 		{
506 			goto fail;
507 		}
508 	}
509 
510 	if (SUCCEED != zbx_check_script_permissions(groupid, host.hostid))
511 	{
512 		zbx_strlcpy(error, "Script does not have permission to be executed on the host.", sizeof(error));
513 		goto fail;
514 	}
515 
516 	if (USER_TYPE_SUPER_ADMIN != user->type &&
517 			SUCCEED != zbx_check_script_user_permissions(user->userid, host.hostid, &script))
518 	{
519 		zbx_strlcpy(error, "User does not have permission to execute this script on the host.", sizeof(error));
520 		goto fail;
521 	}
522 
523 	user_timezone = get_user_timezone(user->userid);
524 
525 	/* substitute macros in script body and webhook parameters */
526 
527 	if (0 != hostid)	/* script on host */
528 		macro_type = MACRO_TYPE_SCRIPT;
529 	else
530 		macro_type = (NULL != recovery_event) ? MACRO_TYPE_SCRIPT_RECOVERY : MACRO_TYPE_SCRIPT_NORMAL;
531 
532 	if (ZBX_SCRIPT_TYPE_WEBHOOK != script.type)
533 	{
534 		if (SUCCEED != substitute_simple_macros_unmasked(NULL, problem_event, recovery_event, &user->userid,
535 				NULL, &host, NULL, NULL, NULL, user_timezone, &script.command, macro_type, error,
536 				sizeof(error)))
537 		{
538 			goto fail;
539 		}
540 
541 		if (SUCCEED != substitute_simple_macros(NULL, problem_event, recovery_event, &user->userid, NULL, &host,
542 				NULL, NULL, NULL, user_timezone, &script.command_orig, macro_type, error,
543 				sizeof(error)))
544 		{
545 			THIS_SHOULD_NEVER_HAPPEN;
546 			goto fail;
547 		}
548 	}
549 	else
550 	{
551 		if (SUCCEED != DBfetch_webhook_params(script.scriptid, &webhook_params, error, sizeof(error)))
552 			goto fail;
553 
554 		for (i = 0; i < webhook_params.values_num; i++)
555 		{
556 			if (SUCCEED != substitute_simple_macros_unmasked(NULL, problem_event, recovery_event,
557 					&user->userid, NULL, &host, NULL, NULL, NULL, user_timezone,
558 					(char **)&webhook_params.values[i].second, macro_type, error,
559 					sizeof(error)))
560 			{
561 				goto fail;
562 			}
563 		}
564 
565 		zbx_webhook_params_pack_json(&webhook_params, &webhook_params_json);
566 	}
567 
568 	if (SUCCEED == (ret = zbx_script_prepare(&script, &host.hostid, error, sizeof(error))))
569 	{
570 		const char	*poutput = NULL, *perror = NULL;
571 
572 		if (0 == host.proxy_hostid || ZBX_SCRIPT_EXECUTE_ON_SERVER == script.execute_on ||
573 				ZBX_SCRIPT_TYPE_WEBHOOK == script.type)
574 		{
575 			ret = zbx_script_execute(&script, &host, webhook_params_json, result, error, sizeof(error),
576 					debug);
577 		}
578 		else
579 			ret = execute_remote_script(&script, &host, result, error, sizeof(error));
580 
581 		if (SUCCEED == ret)
582 			poutput = *result;
583 		else
584 			perror = error;
585 
586 		auditlog_global_script(&script, host.hostid, eventid, host.proxy_hostid, user->userid, clientip,
587 				poutput, perror);
588 	}
589 fail:
590 	if (SUCCEED != ret)
591 		*result = zbx_strdup(*result, error);
592 
593 	zbx_script_clean(&script);
594 	zbx_free(webhook_params_json);
595 	zbx_free(user_timezone);
596 
597 	for (i = 0; i < webhook_params.values_num; i++)
598 	{
599 		zbx_free(webhook_params.values[i].first);
600 		zbx_free(webhook_params.values[i].second);
601 	}
602 
603 	zbx_vector_ptr_pair_destroy(&webhook_params);
604 	zbx_vector_ptr_clear_ext(&events, (zbx_clean_func_t)zbx_db_free_event);
605 	zbx_vector_ptr_destroy(&events);
606 	zbx_vector_uint64_destroy(&eventids);
607 
608 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
609 
610 	return ret;
611 }
612 
613 /******************************************************************************
614  *                                                                            *
615  * Function: node_process_command                                             *
616  *                                                                            *
617  * Purpose: process command received from the frontend                        *
618  *                                                                            *
619  * Return value:  SUCCEED - processed successfully                            *
620  *                FAIL - an error occurred                                    *
621  *                                                                            *
622  ******************************************************************************/
node_process_command(zbx_socket_t * sock,const char * data,const struct zbx_json_parse * jp)623 int	node_process_command(zbx_socket_t *sock, const char *data, const struct zbx_json_parse *jp)
624 {
625 	char			*result = NULL, *send = NULL, *debug = NULL, tmp[64], tmp_hostid[64], tmp_eventid[64],
626 				clientip[MAX_STRING_LEN];
627 	int			ret = FAIL, got_hostid = 0, got_eventid = 0;
628 	zbx_uint64_t		scriptid, hostid = 0, eventid = 0;
629 	struct zbx_json		j;
630 	zbx_user_t		user;
631 
632 	zabbix_log(LOG_LEVEL_DEBUG, "In %s(): data:%s ", __func__, data);
633 
634 	zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN);
635 
636 	/* check who is connecting, get user details, check access rights */
637 
638 	if (FAIL == zbx_get_user_from_json(jp, &user, &result))
639 		goto finish;
640 
641 	if (SUCCEED != check_perm2system(user.userid))
642 	{
643 		result = zbx_strdup(result, "Permission denied. User is a member of group with disabled access.");
644 		goto finish;
645 	}
646 
647 	if (SUCCEED != zbx_check_user_administration_actions_permissions(&user,
648 			ZBX_USER_ROLE_PERMISSION_ACTIONS_EXECUTE_SCRIPTS))
649 	{
650 		result = zbx_strdup(result, "Permission denied. No role access.");
651 		goto finish;
652 	}
653 
654 	/* extract and validate other JSON elements */
655 
656 	if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_SCRIPTID, tmp, sizeof(tmp), NULL) ||
657 			FAIL == is_uint64(tmp, &scriptid))
658 	{
659 		result = zbx_dsprintf(result, "Failed to parse command request tag: %s.", ZBX_PROTO_TAG_SCRIPTID);
660 		goto finish;
661 	}
662 
663 	if (SUCCEED == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_HOSTID, tmp_hostid, sizeof(tmp_hostid), NULL))
664 		got_hostid = 1;
665 
666 	if (SUCCEED == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_EVENTID, tmp_eventid, sizeof(tmp_eventid), NULL))
667 		got_eventid = 1;
668 
669 	if (0 == got_hostid && 0 == got_eventid)
670 	{
671 		result = zbx_dsprintf(result, "Failed to parse command request tag %s or %s.",
672 				ZBX_PROTO_TAG_HOSTID, ZBX_PROTO_TAG_EVENTID);
673 		goto finish;
674 	}
675 
676 	if (1 == got_hostid && 1 == got_eventid)
677 	{
678 		result = zbx_dsprintf(result, "Command request tags %s and %s cannot be used together.",
679 				ZBX_PROTO_TAG_HOSTID, ZBX_PROTO_TAG_EVENTID);
680 		goto finish;
681 	}
682 
683 	if (1 == got_hostid)
684 	{
685 		if (SUCCEED != is_uint64(tmp_hostid, &hostid))
686 		{
687 			result = zbx_dsprintf(result, "Failed to parse value of command request tag %s.",
688 					ZBX_PROTO_TAG_HOSTID);
689 			goto finish;
690 		}
691 
692 		if (0 == hostid)
693 		{
694 			result = zbx_dsprintf(result, "%s value cannot be 0.", ZBX_PROTO_TAG_HOSTID);
695 			goto finish;
696 		}
697 	}
698 	else
699 	{
700 		if (SUCCEED != is_uint64(tmp_eventid, &eventid))
701 		{
702 			result = zbx_dsprintf(result, "Failed to parse value of command request tag %s.",
703 					ZBX_PROTO_TAG_EVENTID);
704 			goto finish;
705 		}
706 
707 		if (0 == eventid)
708 		{
709 			result = zbx_dsprintf(result, "%s value cannot be 0.", ZBX_PROTO_TAG_EVENTID);
710 			goto finish;
711 		}
712 	}
713 
714 	if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_CLIENTIP, clientip, sizeof(clientip), NULL))
715 		*clientip = '\0';
716 
717 	if (SUCCEED == (ret = execute_script(scriptid, hostid, eventid, &user, clientip, &result, &debug)))
718 	{
719 		zbx_json_addstring(&j, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_SUCCESS, ZBX_JSON_TYPE_STRING);
720 		zbx_json_addstring(&j, ZBX_PROTO_TAG_DATA, result, ZBX_JSON_TYPE_STRING);
721 
722 		if (NULL != debug)
723 			zbx_json_addraw(&j, "debug", debug);
724 
725 		send = j.buffer;
726 	}
727 finish:
728 	if (SUCCEED != ret)
729 	{
730 		zbx_json_addstring(&j, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_FAILED, ZBX_JSON_TYPE_STRING);
731 		zbx_json_addstring(&j, ZBX_PROTO_TAG_INFO, (NULL != result ? result : "Unknown error."),
732 				ZBX_JSON_TYPE_STRING);
733 		send = j.buffer;
734 	}
735 
736 	zbx_alarm_on(CONFIG_TIMEOUT);
737 	if (SUCCEED != zbx_tcp_send(sock, send))
738 		zabbix_log(LOG_LEVEL_WARNING, "Error sending result of command");
739 	else
740 		zabbix_log(LOG_LEVEL_DEBUG, "Sending back command '%s' result '%s'", data, send);
741 	zbx_alarm_off();
742 
743 	zbx_json_free(&j);
744 	zbx_free(result);
745 	zbx_free(debug);
746 
747 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
748 
749 	return ret;
750 }
751