Skip to content

Commit

Permalink
A.......S. [ZBX-9425] added check permissions to execute a global scr…
Browse files Browse the repository at this point in the history
…ipts

git-svn-id: svn://svn.zabbix.com/trunk@62776 97f52cf1-0a1b-0410-bd0e-c28be96e8082
  • Loading branch information
sergejs committed Sep 26, 2016
1 parent 20fbd28 commit e2b347a
Show file tree
Hide file tree
Showing 11 changed files with 136 additions and 34 deletions.
1 change: 1 addition & 0 deletions ChangeLog
@@ -1,6 +1,7 @@
Changes for 3.3.0

New features:
A.......S. [ZBX-9425] added check permissions to execute a global scripts (Sergejs)

Bug fixes:

Expand Down
2 changes: 1 addition & 1 deletion frontends/php/include/classes/api/services/CScript.php
Expand Up @@ -287,7 +287,7 @@ public function execute(array $data) {

// execute script
$zabbixServer = new CZabbixServer($ZBX_SERVER, $ZBX_SERVER_PORT, ZBX_SCRIPT_TIMEOUT, ZBX_SOCKET_BYTES_LIMIT);
$result = $zabbixServer->executeScript($scriptId, $hostId);
$result = $zabbixServer->executeScript($scriptId, $hostId, get_cookie('zbx_sessionid'));
if ($result !== false) {
// return the result in a backwards-compatible format
return [
Expand Down
5 changes: 3 additions & 2 deletions frontends/php/include/classes/server/CZabbixServer.php
Expand Up @@ -123,11 +123,12 @@ public function __construct($host, $port, $timeout, $totalBytesLimit) {
*
* @return bool|array
*/
public function executeScript($scriptId, $hostId) {
public function executeScript($scriptId, $hostId, $sessionId) {
return $this->request([
'request' => 'command',
'scriptid' => $scriptId,
'hostid' => $hostId
'hostid' => $hostId,
'sid' => $sessionId
]);
}

Expand Down
8 changes: 8 additions & 0 deletions include/common.h
Expand Up @@ -678,6 +678,13 @@ const char *zbx_item_logtype_string(unsigned char logtype);
#define ZBX_ACKNOWLEDGE_ACTION_NONE 0x0000
#define ZBX_ACKNOWLEDGE_ACTION_CLOSE_PROBLEM 0x0001

typedef struct
{
zbx_uint64_t userid;
unsigned char type;
}
zbx_user_t;

/* user permissions */
typedef enum
{
Expand Down Expand Up @@ -709,6 +716,7 @@ typedef struct
char *privatekey;
char *command;
zbx_uint64_t scriptid;
unsigned char host_access;
}
zbx_script_t;

Expand Down
1 change: 1 addition & 0 deletions include/db.h
Expand Up @@ -678,5 +678,6 @@ zbx_host_availability_t;

int zbx_sql_add_host_availability(char **sql, size_t *sql_alloc, size_t *sql_offset,
const zbx_host_availability_t *ha);
int DBget_user_by_active_session(zbx_user_t *user, const char *sessionid);

#endif
31 changes: 31 additions & 0 deletions src/libs/zbxdbhigh/db.c
Expand Up @@ -2471,3 +2471,34 @@ int zbx_sql_add_host_availability(char **sql, size_t *sql_alloc, size_t *sql_off
return SUCCEED;
}

int DBget_user_by_active_session(zbx_user_t *user, const char *sessionid)
{
const char *__function_name = "zbx_sql_get_user_by_active_session";
int ret = FAIL;
DB_RESULT result;
DB_ROW row;

zabbix_log(LOG_LEVEL_DEBUG, "In %s() sessionid:%s", __function_name, sessionid);

result = DBselect(
"select u.userid,u.type"
" from sessions s,users u"
" where s.userid=u.userid"
" and s.sessionid='%s'"
" and s.status=%d",
sessionid, ZBX_SESSION_ACTIVE);

if (NULL != (row = DBfetch(result)))
{
ZBX_STR2UINT64(user->userid, row[0]);
ZBX_STR2UCHAR(user->type, row[1]);

ret = SUCCEED;
}

DBfree_result(result);

zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));

return ret;
}
4 changes: 3 additions & 1 deletion src/zabbix_proxy/scripts.c
Expand Up @@ -30,10 +30,12 @@ void zbx_script_clean(zbx_script_t *script)
ZBX_UNUSED(script);
}

int zbx_execute_script(DC_HOST *host, zbx_script_t *script, char **result, char *error, size_t max_error_len)
int zbx_execute_script(DC_HOST *host, zbx_script_t *script, zbx_user_t *user, char **result, char *error,
size_t max_error_len)
{
ZBX_UNUSED(host);
ZBX_UNUSED(script);
ZBX_UNUSED(user);
ZBX_UNUSED(result);
ZBX_UNUSED(error);
ZBX_UNUSED(max_error_len);
Expand Down
2 changes: 1 addition & 1 deletion src/zabbix_server/escalator/escalator.c
Expand Up @@ -798,7 +798,7 @@ static void execute_commands(const DB_EVENT *event, zbx_uint64_t actionid, zbx_u
break;
}

rc = zbx_execute_script(&host, &script, NULL, error, sizeof(error));
rc = zbx_execute_script(&host, &script, NULL, NULL, error, sizeof(error));
}

status = (SUCCEED != rc ? ALERT_STATUS_FAILED : ALERT_STATUS_SENT);
Expand Down
87 changes: 66 additions & 21 deletions src/zabbix_server/scripts.c
Expand Up @@ -247,17 +247,18 @@ static int DBget_script_by_scriptid(zbx_uint64_t scriptid, zbx_script_t *script,
zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);

result = DBselect(
"select type,execute_on,command,groupid"
"select type,execute_on,command,groupid,host_access"
" from scripts"
" where scriptid=" ZBX_FS_UI64,
scriptid);

if (NULL != (row = DBfetch(result)))
{
script->type = (unsigned char)atoi(row[0]);
script->execute_on = (unsigned char)atoi(row[1]);
ZBX_STR2UCHAR(script->type, row[0]);
ZBX_STR2UCHAR(script->execute_on, row[1]);
script->command = zbx_strdup(script->command, row[2]);
ZBX_DBROW2UINT64(*groupid, row[3]);
ZBX_STR2UCHAR(script->host_access, row[4]);
ret = SUCCEED;
}
DBfree_result(result);
Expand All @@ -267,7 +268,7 @@ static int DBget_script_by_scriptid(zbx_uint64_t scriptid, zbx_script_t *script,
return ret;
}

static int check_script_permissions(zbx_uint64_t groupid, zbx_uint64_t hostid, char *error, size_t max_error_len)
static int check_script_permissions(zbx_uint64_t groupid, zbx_uint64_t hostid)
{
const char *__function_name = "check_script_permissions";
DB_RESULT result;
Expand All @@ -287,17 +288,50 @@ static int check_script_permissions(zbx_uint64_t groupid, zbx_uint64_t hostid, c
hostid, groupid);

if (NULL == DBfetch(result))
{
zbx_strlcpy(error, "Insufficient permissions. Host is not in an allowed host group.", max_error_len);
ret = FAIL;
}

DBfree_result(result);
exit:
zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));

return ret;
}

static int check_user_permissions(zbx_uint64_t userid, DC_HOST *host, zbx_script_t *script)
{
const char *__function_name = "check_user_permissions";
int ret = SUCCEED;
DB_RESULT result;
DB_ROW row;

zabbix_log(LOG_LEVEL_DEBUG, "In %s() userid:" ZBX_FS_UI64 " hostid:" ZBX_FS_UI64 " scriptid:" ZBX_FS_UI64,
__function_name, userid, host->hostid, script->scriptid);

result = DBselect(
"select null"
" from hosts_groups hg,rights r,users_groups ug"
" where hg.groupid=r.id"
" and r.groupid=ug.usrgrpid"
" and hg.hostid=" ZBX_FS_UI64
" and ug.userid=" ZBX_FS_UI64
" group by hg.hostid"
" having min(r.permission)>%d"
" and max(r.permission)>=%d",
host->hostid,
userid,
PERM_DENY,
script->host_access);

if (NULL == (row = DBfetch(result)))
ret = FAIL;

DBfree_result(result);

zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));

return ret;
}

void zbx_script_init(zbx_script_t *script)
{
memset(script, 0, sizeof(zbx_script_t));
Expand Down Expand Up @@ -327,7 +361,8 @@ void zbx_script_clean(zbx_script_t *script)
* 'zbx_execute_script' to clear allocated memory *
* *
******************************************************************************/
int zbx_execute_script(DC_HOST *host, zbx_script_t *script, char **result, char *error, size_t max_error_len)
int zbx_execute_script(DC_HOST *host, zbx_script_t *script, zbx_user_t *user, char **result, char *error,
size_t max_error_len)
{
const char *__function_name = "zbx_execute_script";
int ret = FAIL;
Expand All @@ -353,7 +388,7 @@ int zbx_execute_script(DC_HOST *host, zbx_script_t *script, char **result, char
CONFIG_TRAPPER_TIMEOUT);
break;
default:
zbx_snprintf(error, max_error_len, "Invalid 'Execute on' option [%d]",
zbx_snprintf(error, max_error_len, "Invalid 'Execute on' option \"%d\".",
(int)script->execute_on);
}
break;
Expand All @@ -362,10 +397,10 @@ int zbx_execute_script(DC_HOST *host, zbx_script_t *script, char **result, char
if (SUCCEED == (ret = zbx_execute_ipmi_command(host, script->command, error, max_error_len)))
{
if (NULL != result)
*result = zbx_strdup(*result, "IPMI command successfully executed");
*result = zbx_strdup(*result, "IPMI command successfully executed.");
}
#else
zbx_strlcpy(error, "Support for IPMI commands was not compiled in", max_error_len);
zbx_strlcpy(error, "Support for IPMI commands was not compiled in.", max_error_len);
#endif
break;
case ZBX_SCRIPT_TYPE_SSH:
Expand All @@ -376,7 +411,7 @@ int zbx_execute_script(DC_HOST *host, zbx_script_t *script, char **result, char
&script->privatekey, MACRO_TYPE_COMMON, NULL, 0);
/* break; is not missing here */
#else
zbx_strlcpy(error, "Support for SSH script was not compiled in", max_error_len);
zbx_strlcpy(error, "Support for SSH script was not compiled in.", max_error_len);
break;
#endif
case ZBX_SCRIPT_TYPE_TELNET:
Expand All @@ -390,21 +425,31 @@ int zbx_execute_script(DC_HOST *host, zbx_script_t *script, char **result, char
case ZBX_SCRIPT_TYPE_GLOBAL_SCRIPT:
if (SUCCEED != DBget_script_by_scriptid(script->scriptid, script, &groupid))
{
zbx_snprintf(error, max_error_len,
"Unknown Script ID [" ZBX_FS_UI64 "]", script->scriptid);
zbx_strlcpy(error, "Unknown script identifier.", max_error_len);
break;
}

if (SUCCEED == check_script_permissions(groupid, host->hostid, error, max_error_len))
if (groupid > 0 && SUCCEED != check_script_permissions(groupid, host->hostid))
{
substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, host, NULL, NULL,
&script->command, MACRO_TYPE_SCRIPT, NULL, 0);

ret = zbx_execute_script(host, script, result, error, max_error_len); /* recursion */
zbx_strlcpy(error, "Script does not have permission to be executed on the host.",
max_error_len);
break;
}
if (user != NULL && USER_TYPE_SUPER_ADMIN != user->type &&
SUCCEED != check_user_permissions(user->userid, host, script))
{
zbx_strlcpy(error, "User does not have permission to execute this script on the host.",
max_error_len);
break;
}

substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, host, NULL, NULL,
&script->command, MACRO_TYPE_SCRIPT, NULL, 0);

ret = zbx_execute_script(host, script, user, result, error, max_error_len); /* recursion */

break;
default:
zbx_snprintf(error, max_error_len, "Invalid command type [%d]", (int)script->type);
zbx_snprintf(error, max_error_len, "Invalid command type \"%d\".", (int)script->type);
}

if (SUCCEED != ret && NULL != result)
Expand Down
3 changes: 2 additions & 1 deletion src/zabbix_server/scripts.h
Expand Up @@ -25,6 +25,7 @@

void zbx_script_init(zbx_script_t *script);
void zbx_script_clean(zbx_script_t *script);
int zbx_execute_script(DC_HOST *host, zbx_script_t *script, char **result, char *error, size_t max_error_len);
int zbx_execute_script(DC_HOST *host, zbx_script_t *script, zbx_user_t *user, char **result, char *error,
size_t max_error_len);

#endif
26 changes: 19 additions & 7 deletions src/zabbix_server/trapper/nodecommand.c
Expand Up @@ -35,22 +35,28 @@
* FAIL - an error occurred *
* *
******************************************************************************/
static int execute_script(zbx_uint64_t scriptid, zbx_uint64_t hostid, char **result)
static int execute_script(zbx_uint64_t scriptid, zbx_uint64_t hostid, const char *sessionid, char **result)
{
const char *__function_name = "execute_script";
char error[MAX_STRING_LEN];
int ret = FAIL, rc;
DC_HOST host;
zbx_script_t script;
zbx_user_t user;

zabbix_log(LOG_LEVEL_DEBUG, "In %s() scriptid:" ZBX_FS_UI64 " hostid:" ZBX_FS_UI64,
__function_name, scriptid, hostid);
zabbix_log(LOG_LEVEL_DEBUG, "In %s() scriptid:" ZBX_FS_UI64 " hostid:" ZBX_FS_UI64 " sessionid:%s",
__function_name, scriptid, hostid, sessionid);

*error = '\0';

if (SUCCEED != (rc = DCget_host_by_hostid(&host, hostid)))
{
zbx_snprintf(error, sizeof(error), "Unknown Host ID [" ZBX_FS_UI64 "].", hostid);
zbx_strlcpy(error, "Unknown host identifier.", sizeof(error));
goto fail;
}
if (SUCCEED != (rc = DBget_user_by_active_session(&user, sessionid)))
{
zbx_strlcpy(error, "Active session identifier is missing.", sizeof(error));
goto fail;
}

Expand All @@ -59,7 +65,7 @@ static int execute_script(zbx_uint64_t scriptid, zbx_uint64_t hostid, char **res
script.type = ZBX_SCRIPT_TYPE_GLOBAL_SCRIPT;
script.scriptid = scriptid;

ret = zbx_execute_script(&host, &script, result, error, sizeof(error));
ret = zbx_execute_script(&host, &script, &user, result, error, sizeof(error));

zbx_script_clean(&script);
fail:
Expand All @@ -83,7 +89,7 @@ static int execute_script(zbx_uint64_t scriptid, zbx_uint64_t hostid, char **res
******************************************************************************/
int node_process_command(zbx_socket_t *sock, const char *data, struct zbx_json_parse *jp)
{
char *result = NULL, *send = NULL, tmp[64];
char *result = NULL, *send = NULL, tmp[64], sessionid[MAX_STRING_LEN];
int ret = FAIL;
zbx_uint64_t scriptid, hostid;
struct zbx_json j;
Expand All @@ -106,7 +112,13 @@ int node_process_command(zbx_socket_t *sock, const char *data, struct zbx_json_p
goto finish;
}

if (SUCCEED == (ret = execute_script(scriptid, hostid, &result)))
if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_SID, sessionid, sizeof(sessionid)))
{
result = zbx_dsprintf(result, "Failed to parse command request tag: %s.", ZBX_PROTO_TAG_SID);
goto finish;
}

if (SUCCEED == (ret = execute_script(scriptid, hostid, sessionid, &result)))
{
zbx_json_addstring(&j, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_SUCCESS, ZBX_JSON_TYPE_STRING);
zbx_json_addstring(&j, ZBX_PROTO_TAG_DATA, result, ZBX_JSON_TYPE_STRING);
Expand Down

0 comments on commit e2b347a

Please sign in to comment.