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