diff options
author | Andris Zeila <andris.zeila@zabbix.com> | 2021-03-12 13:02:40 +0300 |
---|---|---|
committer | Andris Zeila <andris.zeila@zabbix.com> | 2021-03-12 13:02:40 +0300 |
commit | 65a6c53b003bef831288145a59dd75c07dbf0dbd (patch) | |
tree | 97e2375ec574c25d2070dac74b3a22f15a56254e /src/libs/zbxembed | |
parent | 5ef309d8a24243f6f03fc64f63d61aa5ef6e4661 (diff) | |
parent | 671768fb49c5198a6cf174c41f0243d4574610fc (diff) |
.......... [ZBXNEXT-6451] merged branch 'master' of ssh://git.zabbix.lan:7999/zbx/zabbix into feature/ZBXNEXT-6451-5.3
Diffstat (limited to 'src/libs/zbxembed')
-rw-r--r-- | src/libs/zbxembed/embed.c | 136 | ||||
-rw-r--r-- | src/libs/zbxembed/global.c | 90 | ||||
-rw-r--r-- | src/libs/zbxembed/httprequest.c | 89 |
3 files changed, 292 insertions, 23 deletions
diff --git a/src/libs/zbxembed/embed.c b/src/libs/zbxembed/embed.c index 31e9da774d3..c2d6b5ebbb3 100644 --- a/src/libs/zbxembed/embed.c +++ b/src/libs/zbxembed/embed.c @@ -27,7 +27,7 @@ #include "xml.h" #include "embed.h" -#define ZBX_ES_MEMORY_LIMIT (1024 * 1024 * 10) +#define ZBX_ES_MEMORY_LIMIT (1024 * 1024 * 64) #define ZBX_ES_TIMEOUT 10 #define ZBX_ES_STACK_LIMIT 1000 @@ -418,13 +418,13 @@ out: * * * Purpose: executes script * * * - * Parameters: es - [IN] the embedded scripting engine * - * script - [IN] the script to execute * - * code - [IN] the precompiled bytecode * - * size - [IN] the size of precompiled bytecode * - * param - [IN] the parameter to pass to the script * - * output - [OUT] the result value * - * error - [OUT] the error message * + * Parameters: es - [IN] the embedded scripting engine * + * script - [IN] the script to execute * + * code - [IN] the precompiled bytecode * + * size - [IN] the size of precompiled bytecode * + * param - [IN] the parameter to pass to the script * + * script_ret - [OUT] the result value * + * error - [OUT] the error message * * * * Return value: SUCCEED * * FAIL * @@ -435,7 +435,7 @@ out: * bytecode parameters. * * * ******************************************************************************/ -int zbx_es_execute(zbx_es_t *es, const char *script, const char *code, int size, const char *param, char **output, +int zbx_es_execute(zbx_es_t *es, const char *script, const char *code, int size, const char *param, char **script_ret, char **error) { void *buffer; @@ -495,24 +495,45 @@ int zbx_es_execute(zbx_es_t *es, const char *script, const char *code, int size, goto out; } - if (0 == duk_check_type(es->env->ctx, -1, DUK_TYPE_UNDEFINED)) + if (NULL != script_ret || SUCCEED == ZBX_CHECK_LOG_LEVEL(LOG_LEVEL_DEBUG)) { - if (0 != duk_check_type(es->env->ctx, -1, DUK_TYPE_NULL)) + if (0 == duk_check_type(es->env->ctx, -1, DUK_TYPE_UNDEFINED)) { - ret = SUCCEED; - *output = NULL; - zabbix_log(LOG_LEVEL_DEBUG, "%s() output: null", __func__); + if (0 != duk_check_type(es->env->ctx, -1, DUK_TYPE_NULL)) + { + ret = SUCCEED; + + if (NULL != script_ret) + *script_ret = NULL; + + zabbix_log(LOG_LEVEL_DEBUG, "%s() output: null", __func__); + } + else + { + char *output = NULL; + + if (SUCCEED != (ret = zbx_cesu8_to_utf8(duk_safe_to_string(es->env->ctx, -1), &output))) + *error = zbx_strdup(*error, "could not convert return value to utf8"); + else + zabbix_log(LOG_LEVEL_DEBUG, "%s() output:'%s'", __func__, output); + + if (SUCCEED == ret && NULL != script_ret) + *script_ret = output; + else + zbx_free(output); + } } else { - if (SUCCEED != (ret = zbx_cesu8_to_utf8(duk_safe_to_string(es->env->ctx, -1), output))) - *error = zbx_strdup(*error, "could not convert return value to utf8"); + if (NULL == script_ret) + { + zabbix_log(LOG_LEVEL_DEBUG, "%s(): undefined return value", __func__); + ret = SUCCEED; + } else - zabbix_log(LOG_LEVEL_DEBUG, "%s() output:'%s'", __func__, *output); + *error = zbx_strdup(*error, "undefined return value"); } } - else - *error = zbx_strdup(*error, "undefined return value"); duk_pop(es->env->ctx); es->env->rt_error_num = 0; @@ -531,7 +552,7 @@ out: /****************************************************************************** * * * Function: zbx_es_set_timeout * - * es_init_global_functions * + * * * Purpose: sets script execution timeout * * * * Parameters: es - [IN] the embedded scripting engine * @@ -568,3 +589,78 @@ void zbx_es_debug_disable(zbx_es_t *es) zbx_json_free(es->env->json); zbx_free(es->env->json); } + +/****************************************************************************** + * * + * Function: zbx_es_execute_command * + * * + * Purpose: executes command (script in form of a text) * + * * + * Parameters: command - [IN] the command in form of a text * + * param - [IN] the script parameters * + * timeout - [IN] the timeout for the execution (seconds) * + * result - [OUT] the result of an execution * + * error - [OUT] the error message * + * max_error_len - [IN] the maximum length of an error * + * debug - [OUT] the debug data (optional) * + * * + * Return value: SUCCEED * + * FAIL * + * * + ******************************************************************************/ +int zbx_es_execute_command(const char *command, const char *param, int timeout, char **result, + char *error, size_t max_error_len, char **debug) +{ + int size, ret = SUCCEED; + char *code = NULL, *errmsg = NULL; + zbx_es_t es; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + zbx_es_init(&es); + if (FAIL == zbx_es_init_env(&es, &errmsg)) + { + zbx_snprintf(error, max_error_len, "cannot initialize scripting environment: %s", errmsg); + zbx_free(errmsg); + ret = FAIL; + goto failure; + } + + if (NULL != debug) + zbx_es_debug_enable(&es); + + if (FAIL == zbx_es_compile(&es, command, &code, &size, &errmsg)) + { + zbx_snprintf(error, max_error_len, "cannot compile script: %s", errmsg); + zbx_free(errmsg); + ret = FAIL; + goto out; + } + + if (0 != timeout) + zbx_es_set_timeout(&es, timeout); + + if (FAIL == zbx_es_execute(&es, NULL, code, size, param, result, &errmsg)) + { + zbx_snprintf(error, max_error_len, "cannot execute script: %s", errmsg); + zbx_free(errmsg); + ret = FAIL; + goto out; + } +out: + if (NULL != debug) + *debug = zbx_strdup(NULL, zbx_es_debug_info(&es)); + + if (FAIL == zbx_es_destroy_env(&es, &errmsg)) + { + zabbix_log(LOG_LEVEL_WARNING, "cannot destroy embedded scripting engine environment: %s", errmsg); + zbx_free(errmsg); + } + + zbx_free(code); + zbx_free(errmsg); +failure: + zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); + + return ret; +} diff --git a/src/libs/zbxembed/global.c b/src/libs/zbxembed/global.c index b84c3a38bef..58649e18e0f 100644 --- a/src/libs/zbxembed/global.c +++ b/src/libs/zbxembed/global.c @@ -23,6 +23,7 @@ #include "global.h" #include "duktape.h" #include "base64.h" +#include "sha256crypt.h" /****************************************************************************** * * @@ -83,6 +84,89 @@ static duk_ret_t es_atob(duk_context *ctx) /****************************************************************************** * * + * Function: es_md5 * + * * + * Purpose: compute a md5 checksum * + * * + * Parameters: ctx - [IN] pointer to duk_context * + * * + * Comments: Throws an error: * + * - if the top value at ctx value stack is not a string * + * - if the value stack is empty * + * * + ******************************************************************************/ +static duk_ret_t es_md5(duk_context *ctx) +{ + const char *hex = "0123456789abcdef"; + md5_state_t state; + md5_byte_t hash[MD5_DIGEST_SIZE]; + int i; + char *str = NULL, *md5sum, *ptr; + + if (SUCCEED != zbx_cesu8_to_utf8(duk_require_string(ctx, 0), &str)) + return duk_error(ctx, DUK_RET_TYPE_ERROR, "cannot convert value to utf8"); + + ptr = md5sum = (char *)zbx_malloc(NULL, MD5_DIGEST_SIZE * 2 + 1); + + zbx_md5_init(&state); + zbx_md5_append(&state, (const md5_byte_t *)str, strlen(str)); + zbx_md5_finish(&state, hash); + + for (i = 0; i < MD5_DIGEST_SIZE; i++) + { + *ptr++ = hex[hash[i] >> 4]; + *ptr++ = hex[hash[i] & 15]; + } + + *ptr = '\0'; + + duk_push_string(ctx, md5sum); + zbx_free(str); + zbx_free(md5sum); + return 1; +} + +/****************************************************************************** + * * + * Function: es_sha256 * + * * + * Purpose: compute a sha256 checksum * + * * + * Parameters: ctx - [IN] pointer to duk_context * + * * + * Comments: Throws an error: * + * - if the top value at ctx value stack is not a string * + * - if the value stack is empty * + * * + ******************************************************************************/ +static duk_ret_t es_sha256(duk_context *ctx) +{ + char *str = NULL, hash_res[ZBX_SHA256_DIGEST_SIZE], hash_res_stringhexes[ZBX_SHA256_DIGEST_SIZE * 2 + 1]; + int i; + + if (SUCCEED != zbx_cesu8_to_utf8(duk_require_string(ctx, 0), &str)) + return duk_error(ctx, DUK_RET_TYPE_ERROR, "cannot convert value to utf8"); + + zbx_sha256_hash(str, hash_res); + + for (i = 0 ; i < ZBX_SHA256_DIGEST_SIZE; i++) + { + char z[3]; + + zbx_snprintf(z, 3, "%02x", (unsigned char)hash_res[i]); + hash_res_stringhexes[i * 2] = z[0]; + hash_res_stringhexes[i * 2 + 1] = z[1]; + } + + hash_res_stringhexes[ZBX_SHA256_DIGEST_SIZE * 2] = '\0'; + + duk_push_string(ctx, hash_res_stringhexes); + zbx_free(str); + return 1; +} + +/****************************************************************************** + * * * Function: es_init_global_functions * * * * Purpose: initializes additional global functions * @@ -97,4 +181,10 @@ void es_init_global_functions(zbx_es_t *es) duk_push_c_function(es->env->ctx, es_btoa, 1); duk_put_global_string(es->env->ctx, "btoa"); + + duk_push_c_function(es->env->ctx, es_md5, 1); + duk_put_global_string(es->env->ctx, "md5"); + + duk_push_c_function(es->env->ctx, es_sha256, 1); + duk_put_global_string(es->env->ctx, "sha256"); } diff --git a/src/libs/zbxembed/httprequest.c b/src/libs/zbxembed/httprequest.c index 41598a5aac8..8ad63a2750a 100644 --- a/src/libs/zbxembed/httprequest.c +++ b/src/libs/zbxembed/httprequest.c @@ -28,6 +28,16 @@ #ifdef HAVE_LIBCURL +#define ZBX_HTTPAUTH_NONE CURLAUTH_NONE +#define ZBX_HTTPAUTH_BASIC CURLAUTH_BASIC +#define ZBX_HTTPAUTH_DIGEST CURLAUTH_DIGEST +#if LIBCURL_VERSION_NUM >= 0x072600 +# define ZBX_HTTPAUTH_NEGOTIATE CURLAUTH_NEGOTIATE +#else +# define ZBX_HTTPAUTH_NEGOTIATE CURLAUTH_GSSNEGOTIATE +#endif +#define ZBX_HTTPAUTH_NTLM CURLAUTH_NTLM + extern char *CONFIG_SOURCE_IP; typedef struct @@ -320,8 +330,6 @@ static duk_ret_t es_httprequest_query(duk_context *ctx, const char *http_request curl_easy_strerror(err)); goto out; } - - duk_push_string(ctx, request->data); out: zbx_free(url); zbx_free(contents); @@ -329,6 +337,8 @@ out: if (-1 != err_index) return duk_throw(ctx); + duk_push_string(ctx, request->data); + return 1; } @@ -401,7 +411,7 @@ out: if (-1 != err_index) return duk_throw(ctx); - return 1; + return 0; } /****************************************************************************** @@ -486,6 +496,64 @@ static duk_ret_t es_httprequest_get_headers(duk_context *ctx) return 1; } +/****************************************************************************** + * * + * Function: es_httprequest_set_httpauth * + * * + * Purpose: CurlHttpRequest.SetHttpAuth method * + * * + ******************************************************************************/ +static duk_ret_t es_httprequest_set_httpauth(duk_context *ctx) +{ + zbx_es_httprequest_t *request; + char *username = NULL, *password = NULL; + int err_index = -1, mask; + CURLcode err; + + if (NULL == (request = es_httprequest(ctx))) + return duk_error(ctx, DUK_RET_EVAL_ERROR, "internal scripting error: null object"); + + mask = duk_to_int32(ctx, 0); + + if (0 != (mask & ~(ZBX_HTTPAUTH_BASIC | ZBX_HTTPAUTH_DIGEST | ZBX_HTTPAUTH_NEGOTIATE | ZBX_HTTPAUTH_NTLM))) + return duk_error(ctx, DUK_RET_EVAL_ERROR, "invalid HTTP authentication mask"); + + if (0 == duk_is_null_or_undefined(ctx, 1)) + { + if (SUCCEED != zbx_cesu8_to_utf8(duk_to_string(ctx, 1), &username)) + { + err_index = duk_push_error_object(ctx, DUK_RET_TYPE_ERROR, "cannot convert username to utf8"); + goto out; + } + } + + if (0 == duk_is_null_or_undefined(ctx, 2)) + { + if (SUCCEED != zbx_cesu8_to_utf8(duk_to_string(ctx, 2), &password)) + { + err_index = duk_push_error_object(ctx, DUK_RET_TYPE_ERROR, "cannot convert username to utf8"); + goto out; + } + } + + ZBX_CURL_SETOPT(ctx, request->handle, CURLOPT_HTTPAUTH, mask, err); + + if (NULL != username) + ZBX_CURL_SETOPT(ctx, request->handle, CURLOPT_USERNAME, username, err); + + if (NULL != password) + ZBX_CURL_SETOPT(ctx, request->handle, CURLOPT_PASSWORD, password, err); + +out: + zbx_free(password); + zbx_free(username); + + if (-1 != err_index) + return duk_throw(ctx); + + return 0; +} + static const duk_function_list_entry curlhttprequest_methods[] = { {"AddHeader", es_httprequest_add_header, 1}, {"ClearHeader", es_httprequest_clear_header, 0}, @@ -496,6 +564,7 @@ static const duk_function_list_entry curlhttprequest_methods[] = { {"Status", es_httprequest_status, 0}, {"SetProxy", es_httprequest_set_proxy, 1}, {"GetHeaders", es_httprequest_get_headers, 0}, + {"SetHttpAuth", es_httprequest_set_httpauth, 3}, {NULL, NULL, 0} }; @@ -509,6 +578,7 @@ static const duk_function_list_entry httprequest_methods[] = { {"getStatus", es_httprequest_status, 0}, {"setProxy", es_httprequest_set_proxy, 1}, {"getHeaders", es_httprequest_get_headers, 0}, + {"setHttpAuth", es_httprequest_set_httpauth, 3}, {NULL, NULL, 0} }; @@ -562,5 +632,18 @@ int zbx_es_init_httprequest(zbx_es_t *es, char **error) return FAIL; } +#ifdef HAVE_LIBCURL + duk_push_number(es->env->ctx, ZBX_HTTPAUTH_NONE); + duk_put_global_string(es->env->ctx, "HTTPAUTH_NONE"); + duk_push_number(es->env->ctx, ZBX_HTTPAUTH_BASIC); + duk_put_global_string(es->env->ctx, "HTTPAUTH_BASIC"); + duk_push_number(es->env->ctx, ZBX_HTTPAUTH_DIGEST); + duk_put_global_string(es->env->ctx, "HTTPAUTH_DIGEST"); + duk_push_number(es->env->ctx, ZBX_HTTPAUTH_NEGOTIATE); + duk_put_global_string(es->env->ctx, "HTTPAUTH_NEGOTIATE"); + duk_push_number(es->env->ctx, ZBX_HTTPAUTH_NTLM); + duk_put_global_string(es->env->ctx, "HTTPAUTH_NTLM"); +#endif + return SUCCEED; } |