Skip to content

Commit

Permalink
.......PS. [ZBXNEXT-8091] added support for legacy additional SSH opt…
Browse files Browse the repository at this point in the history
…ions
  • Loading branch information
arseniuss-zabbix committed Dec 7, 2022
1 parent 7587a11 commit b03206e
Show file tree
Hide file tree
Showing 10 changed files with 278 additions and 13 deletions.
37 changes: 37 additions & 0 deletions m4/check_enum.m4
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
##
# ----------------------------------------------------------
# SYNOPSIS
#
# ENUM_CHECK(ENUM,INCLUDE)
#
# DESCRIPTION
#
# Checks if certain enumerator (or macro) constant exists
# in a header and defines C macro with prefix HAVE_.
#
# This macro is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

AC_DEFUN([ENUM_CHECK], [
AC_MSG_CHECKING([for enum constant $1])
AS_VAR_PUSHDEF([enum_var], [enum_var_have_$1])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <$2>
]], [[
int e = $1;
]])],
[AS_VAR_SET([enum_var], [yes])],
[AS_VAR_SET([enum_var], [no])])
AS_IF([test yes = AS_VAR_GET([enum_var])],[
AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$1), 1, [Define to 1 if the library has the $1 enum value])
AC_MSG_RESULT(yes)
], [
AC_MSG_RESULT(no)
])
AS_VAR_POPDEF([enum_var])
])dnl
7 changes: 7 additions & 0 deletions m4/libssh.m4
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,13 @@ AS_HELP_STRING([--with-ssh@<:@=DIR@:>@],[use SSH package @<:@default=no@:>@, DIR
if test "x$found_ssh" = "xyes"; then
AC_DEFINE([HAVE_SSH], 1, [Define to 1 if you have the 'libssh' library (-lssh)])
AC_MSG_RESULT(yes)
ENUM_CHECK([SSH_OPTIONS_KEY_EXCHANGE],[libssh/libssh.h])
ENUM_CHECK([SSH_OPTIONS_HOSTKEYS],[libssh/libssh.h])
ENUM_CHECK([SSH_OPTIONS_CIPHERS_C_S],[libssh/libssh.h])
ENUM_CHECK([SSH_OPTIONS_CIPHERS_S_C],[libssh/libssh.h])
ENUM_CHECK([SSH_OPTIONS_HMAC_C_S],[libssh/libssh.h])
ENUM_CHECK([SSH_OPTIONS_HMAC_S_C],[libssh/libssh.h])
else
AC_MSG_RESULT(no)
SSH_CFLAGS=""
Expand Down
7 changes: 7 additions & 0 deletions m4/libssh2.m4
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ AS_HELP_STRING([--with-ssh2@<:@=DIR@:>@],[use SSH2 package @<:@default=no@:>@, D
if test "x$found_ssh2" = "xyes"; then
AC_DEFINE([HAVE_SSH2], 1, [Define to 1 if you have the 'libssh2' library (-lssh2)])
AC_MSG_RESULT(yes)
ENUM_CHECK([LIBSSH2_METHOD_KEX],[libssh2.h])
ENUM_CHECK([LIBSSH2_METHOD_HOSTKEY],[libssh2.h])
ENUM_CHECK([LIBSSH2_METHOD_CRYPT_CS],[libssh2.h])
ENUM_CHECK([LIBSSH2_METHOD_CRYPT_SC],[libssh2.h])
ENUM_CHECK([LIBSSH2_METHOD_MAC_CS],[libssh2.h])
ENUM_CHECK([LIBSSH2_METHOD_MAC_SC],[libssh2.h])
else
AC_MSG_RESULT(no)
SSH2_CFLAGS=""
Expand Down
7 changes: 4 additions & 3 deletions src/zabbix_server/poller/checks_ssh.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ int get_value_ssh(DC_ITEM *item, AGENT_RESULT *result)
{
AGENT_REQUEST request;
int ret = NOTSUPPORTED;
const char *port, *encoding, *dns;
const char *port, *encoding, *dns, *options;

zbx_init_agent_request(&request);

Expand All @@ -46,7 +46,7 @@ int get_value_ssh(DC_ITEM *item, AGENT_RESULT *result)
}
#undef SSH_RUN_KEY

if (4 < get_rparams_num(&request))
if (5 < get_rparams_num(&request))
{
SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
goto out;
Expand Down Expand Up @@ -77,8 +77,9 @@ int get_value_ssh(DC_ITEM *item, AGENT_RESULT *result)
item->interface.port = ZBX_DEFAULT_SSH_PORT;

encoding = get_rparam(&request, 3);
options = get_rparam(&request, 4);

ret = ssh_run(item, result, ZBX_NULL2EMPTY_STR(encoding));
ret = ssh_run(item, result, ZBX_NULL2EMPTY_STR(encoding), ZBX_NULL2EMPTY_STR(options));
out:
zbx_free_agent_request(&request);

Expand Down
120 changes: 118 additions & 2 deletions src/zabbix_server/poller/ssh2_run.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,114 @@ extern char *CONFIG_SSH_KEY_LOCATION;

static const char *password;

static int ssh_set_options(LIBSSH2_SESSION *session, int type, const char *key_str, const char *value,
char **err_msg)
{
if (0 > libssh2_session_method_pref(session, type, value))
{
char *err;
const char **algs;
int i, rc;

*err_msg = zbx_dsprintf(NULL, "Error while setting %s SSH option", key_str);

if (0 > libssh2_session_last_error(session, &err, NULL, 0))
{
*err_msg = zbx_strdcatf(*err_msg, ": %s.", err);
}
else
{
*err_msg = zbx_strdcat(*err_msg, ".");
}

if (0 < (rc = libssh2_session_supported_algs(session, type, &algs)))
{
*err_msg = zbx_strdcat(*err_msg, " Supported values are: ");

for (i = 0; i < rc; i++)
{
*err_msg = zbx_strdcat(*err_msg, algs[i]);
if (i < rc - 1)
*err_msg = zbx_strdcat(*err_msg, ", ");
}
*err_msg = zbx_strdcat(*err_msg, ".");
}

return -1;
}

return 0;
}

static int ssh_parse_options(LIBSSH2_SESSION *session, const char *options, char **err_msg)
{
int ret = SUCCEED;
char opt_copy[1024] = {0};
char *line, *rest = opt_copy;

zbx_strscpy(opt_copy, options);

while ((line = strtok_r(opt_copy, ";", &rest)))
{
char *eq_str = strchr(line, '=');

*eq_str = '\0';

#ifdef HAVE_LIBSSH2_METHOD_KEX
if(ZBX_CONST_STRLEN(KEY_EXCHANGE_STR) == (eq_str - line) &&
0 == strncmp(line, KEY_EXCHANGE_STR, ZBX_CONST_STRLEN(KEY_EXCHANGE_STR)))
{
if (0 != (ret = ssh_set_options(session, LIBSSH2_METHOD_KEX, KEY_EXCHANGE_STR, eq_str + 1,
err_msg)))
break;
continue;
}
#endif
#ifdef HAVE_LIBSSH2_METHOD_HOSTKEY
if(ZBX_CONST_STRLEN(KEY_HOSTKEY_STR) == (eq_str - line) &&
0 == strncmp(line, KEY_HOSTKEY_STR, ZBX_CONST_STRLEN(KEY_HOSTKEY_STR)))
{
if (0 != (ret = ssh_set_options(session, LIBSSH2_METHOD_HOSTKEY, KEY_HOSTKEY_STR, eq_str + 1,
err_msg)))
break;
continue;
}
#endif
#if defined(HAVE_LIBSSH2_METHOD_CRYPT_CS) && defined(HAVE_LIBSSH2_METHOD_CRYPT_SC)
if(ZBX_CONST_STRLEN(KEY_CIPHERS_STR) == (eq_str - line) &&
0 == strncmp(line, KEY_CIPHERS_STR, ZBX_CONST_STRLEN(KEY_CIPHERS_STR)))
{
if (0 != (ret = ssh_set_options(session, LIBSSH2_METHOD_CRYPT_CS, KEY_CIPHERS_STR, eq_str + 1,
err_msg)))
break;
if (0 != (ret = ssh_set_options(session, LIBSSH2_METHOD_CRYPT_SC, KEY_CIPHERS_STR, eq_str + 1,
err_msg)))
break;
continue;
}
#endif
#if defined(HAVE_LIBSSH2_METHOD_MAC_CS) && defined(HAVE_LIBSSH2_METHOD_MAC_SC)
if(ZBX_CONST_STRLEN(KEY_MACS_STR) == (eq_str - line) &&
0 == strncmp(line, KEY_MACS_STR, ZBX_CONST_STRLEN(KEY_MACS_STR)))
{
if (0 != (ret = ssh_set_options(session, LIBSSH2_METHOD_MAC_CS, KEY_MACS_STR, eq_str + 1,
err_msg)))
break;
if (0 != (ret = ssh_set_options(session, LIBSSH2_METHOD_MAC_SC, KEY_MACS_STR, eq_str + 1,
err_msg)))
break;
continue;
}
#endif

*err_msg = zbx_dsprintf(NULL, "SSH option %s is not supported", line);
ret = FAIL;
break;
}

return ret;
}

static void kbd_callback(const char *name, int name_len, const char *instruction,
int instruction_len, int num_prompts,
const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
Expand Down Expand Up @@ -80,14 +188,14 @@ static int waitsocket(int socket_fd, LIBSSH2_SESSION *session)
}

/* example ssh.run["ls /"] */
int ssh_run(DC_ITEM *item, AGENT_RESULT *result, const char *encoding)
int ssh_run(DC_ITEM *item, AGENT_RESULT *result, const char *encoding, const char *options)
{
zbx_socket_t s;
LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *channel;
int auth_pw = 0, rc, ret = NOTSUPPORTED, exitcode;
char tmp_buf[DATA_BUFFER_SIZE], *userauthlist, *publickey = NULL, *privatekey = NULL, *ssherr,
*output, *buffer = NULL;
*output, *buffer = NULL, *err_msg = NULL;
size_t offset = 0, buf_size = DATA_BUFFER_SIZE;

zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
Expand All @@ -106,6 +214,14 @@ int ssh_run(DC_ITEM *item, AGENT_RESULT *result, const char *encoding)
goto tcp_close;
}

if (0 != ssh_parse_options(session, options, &err_msg))
{
SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot set additional SSH session options: %s",
err_msg));
zbx_free(err_msg);
goto session_free;
}

/* set blocking mode on session */
libssh2_session_set_blocking(session, 1);

Expand Down
95 changes: 93 additions & 2 deletions src/zabbix_server/poller/ssh_run.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,97 @@
extern char *CONFIG_SOURCE_IP;
extern char *CONFIG_SSH_KEY_LOCATION;

static int ssh_set_options(ssh_session session, enum ssh_options_e type, const char *key_str, const char *value,
char **err_msg)
{
if (0 > ssh_options_set(session, type, value))
{
*err_msg = zbx_dsprintf(NULL, "Error while setting %s SSH option: %s.", key_str,
ssh_get_error(session));

return -1;
}

return 0;
}

static int ssh_parse_options(ssh_session session, const char *options, char **err_msg)
{
int ret = SUCCEED;
char opt_copy[1024] = {0};
char *line, *rest = opt_copy;

zbx_strscpy(opt_copy, options);

while ((line = strtok_r(opt_copy, ";", &rest)))
{
char *eq_str = strchr(line, '=');

*eq_str = '\0';

#ifdef HAVE_SSH_OPTIONS_KEY_EXCHANGE
if(ZBX_CONST_STRLEN(KEY_EXCHANGE_STR) == (eq_str - line) &&
0 == strncmp(line, KEY_EXCHANGE_STR, ZBX_CONST_STRLEN(KEY_EXCHANGE_STR)))
{
if (0 != (ret = ssh_set_options(session, SSH_OPTIONS_KEY_EXCHANGE, KEY_EXCHANGE_STR, eq_str + 1,
err_msg)))
break;
continue;
}
#endif
#ifdef HAVE_SSH_OPTIONS_HOSTKEYS
if(ZBX_CONST_STRLEN(KEY_HOSTKEY_STR) == (eq_str - line) &&
0 == strncmp(line, KEY_HOSTKEY_STR, ZBX_CONST_STRLEN(KEY_HOSTKEY_STR)))
{
if (0 != (ret = ssh_set_options(session, SSH_OPTIONS_HOSTKEYS, KEY_HOSTKEY_STR, eq_str + 1,
err_msg)))
break;
continue;
}
#endif
#if defined(HAVE_SSH_OPTIONS_CIPHERS_C_S) && defined(HAVE_SSH_OPTIONS_CIPHERS_S_C)
if(ZBX_CONST_STRLEN(KEY_CIPHERS_STR) == (eq_str - line) &&
0 == strncmp(line, KEY_CIPHERS_STR, ZBX_CONST_STRLEN(KEY_CIPHERS_STR)))
{
if (0 != (ret = ssh_set_options(session, SSH_OPTIONS_CIPHERS_C_S, KEY_CIPHERS_STR, eq_str + 1,
err_msg)))
break;
if (0 != (ret = ssh_set_options(session, SSH_OPTIONS_CIPHERS_S_C, KEY_CIPHERS_STR, eq_str + 1,
err_msg)))
break;
continue;
}
#endif
#if defined(HAVE_SSH_OPTIONS_HMAC_C_S) && defined(HAVE_SSH_OPTIONS_HMAC_S_C)
if(ZBX_CONST_STRLEN(KEY_MACS_STR) == (eq_str - line) &&
0 == strncmp(line, KEY_MACS_STR, ZBX_CONST_STRLEN(KEY_MACS_STR)))
{
if (0 != (ret = ssh_set_options(session, SSH_OPTIONS_HMAC_C_S, KEY_MACS_STR, eq_str + 1,
err_msg)))
break;
if (0 != (ret = ssh_set_options(session, SSH_OPTIONS_HMAC_S_C, KEY_MACS_STR, eq_str + 1,
err_msg)))
break;
continue;
}
#endif

*err_msg = zbx_dsprintf(NULL, "SSH option %s is not supported", line);
ret = FAIL;
break;
}

return ret;
}

/* example ssh.run["ls /"] */
int ssh_run(DC_ITEM *item, AGENT_RESULT *result, const char *encoding)
int ssh_run(DC_ITEM *item, AGENT_RESULT *result, const char *encoding, const char *options)
{
ssh_session session;
ssh_channel channel;
ssh_key privkey = NULL, pubkey = NULL;
int rc, userauth, ret = NOTSUPPORTED;
char *output, *publickey = NULL, *privatekey = NULL, *buffer = NULL;
char *output, *publickey = NULL, *privatekey = NULL, *buffer = NULL, *err_msg = NULL;
char tmp_buf[DATA_BUFFER_SIZE], userauthlist[64];
size_t offset = 0, buf_size = DATA_BUFFER_SIZE;

Expand Down Expand Up @@ -68,6 +151,14 @@ int ssh_run(DC_ITEM *item, AGENT_RESULT *result, const char *encoding)
goto session_free;
}

if (0 != ssh_parse_options(session, options, &err_msg))
{
SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot set additional SSH session options: %s",
err_msg));
zbx_free(err_msg);
goto session_free;
}

if (SSH_OK != ssh_connect(session))
{
SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot establish SSH session: %s", ssh_get_error(session)));
Expand Down
7 changes: 6 additions & 1 deletion src/zabbix_server/poller/ssh_run.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@
#if defined(HAVE_SSH2) || defined(HAVE_SSH)
#include "zbxcacheconfig.h"

int ssh_run(DC_ITEM *item, AGENT_RESULT *result, const char *encoding);
#define KEY_EXCHANGE_STR "KexAlgorithms"
#define KEY_HOSTKEY_STR "HostkeyAlgorithms"
#define KEY_CIPHERS_STR "Ciphers"
#define KEY_MACS_STR "MACs"

int ssh_run(DC_ITEM *item, AGENT_RESULT *result, const char *encoding, const char *options);
#endif /* defined(HAVE_SSH2) || defined(HAVE_SSH)*/

#endif
7 changes: 4 additions & 3 deletions tests/zabbix_server/poller/test_get_value_ssh.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@

#include "zbxsysinfo.h"

int __wrap_ssh_run(DC_ITEM *item, AGENT_RESULT *result, const char *encoding);
int __wrap_ssh_run(DC_ITEM *item, AGENT_RESULT *result, const char *encoding, const char *options);

#if defined(HAVE_SSH2) || defined(HAVE_SSH)
int zbx_get_value_ssh_test_run(DC_ITEM *item, char **error)
int zbx_get_value_ssh_test_run(DC_ITEM *item, char **error, const char *options)
{
AGENT_RESULT result;
int ret;
Expand All @@ -46,11 +46,12 @@ int zbx_get_value_ssh_test_run(DC_ITEM *item, char **error)
}
#endif /*POLLER_GET_VALUE_SSH_TEST_H*/

int __wrap_ssh_run(DC_ITEM *item, AGENT_RESULT *result, const char *encoding)
int __wrap_ssh_run(DC_ITEM *item, AGENT_RESULT *result, const char *encoding, const char *options)
{
ZBX_UNUSED(item);
ZBX_UNUSED(result);
ZBX_UNUSED(encoding);
ZBX_UNUSED(options);

return SYSINFO_RET_OK;
}
Loading

0 comments on commit b03206e

Please sign in to comment.