diff options
Diffstat (limited to 'src/libs/zbxaudit/audit.c')
-rw-r--r-- | src/libs/zbxaudit/audit.c | 218 |
1 files changed, 162 insertions, 56 deletions
diff --git a/src/libs/zbxaudit/audit.c b/src/libs/zbxaudit/audit.c index 061f53bd15c..0ae7b0907e9 100644 --- a/src/libs/zbxaudit/audit.c +++ b/src/libs/zbxaudit/audit.c @@ -40,22 +40,25 @@ zbx_hashset_t *zbx_get_audit_hashset(void) return &zbx_audit; } -zbx_audit_entry_t *zbx_audit_entry_init(zbx_uint64_t id, const char *name, int audit_action, int resource_type) +zbx_audit_entry_t *zbx_audit_entry_init(zbx_uint64_t id, const int id_table, const char *name, int audit_action, + int resource_type) { zbx_audit_entry_t *audit_entry; audit_entry = (zbx_audit_entry_t*)zbx_malloc(NULL, sizeof(zbx_audit_entry_t)); audit_entry->id = id; audit_entry->cuid = NULL; + audit_entry->id_table = id_table; audit_entry->name = zbx_strdup(NULL, name); audit_entry->audit_action = audit_action; audit_entry->resource_type = resource_type; + zbx_new_cuid(audit_entry->audit_cuid); zbx_json_init(&(audit_entry->details_json), ZBX_JSON_STAT_BUF_LEN); return audit_entry; } -zbx_audit_entry_t *zbx_audit_entry_init_cuid(const char *cuid, const char *name, int audit_action, +zbx_audit_entry_t *zbx_audit_entry_init_cuid(const char *cuid, const int id_table, const char *name, int audit_action, int resource_type) { zbx_audit_entry_t *audit_entry; @@ -63,9 +66,11 @@ zbx_audit_entry_t *zbx_audit_entry_init_cuid(const char *cuid, const char *name, audit_entry = (zbx_audit_entry_t*)zbx_malloc(NULL, sizeof(zbx_audit_entry_t)); audit_entry->id = 0; audit_entry->cuid = zbx_strdup(NULL, cuid); + audit_entry->id_table = id_table; audit_entry->name = zbx_strdup(NULL, name); audit_entry->audit_action = audit_action; audit_entry->resource_type = resource_type; + zbx_new_cuid(audit_entry->audit_cuid); zbx_json_init(&(audit_entry->details_json), ZBX_JSON_STAT_BUF_LEN); return audit_entry; @@ -168,10 +173,10 @@ int zbx_auditlog_global_script(unsigned char script_type, unsigned char script_e zbx_uint64_t proxy_hostid, zbx_uint64_t userid, const char *username, const char *clientip, const char *output, const char *error) { - int ret = SUCCEED; - char auditid_cuid[CUID_LEN], execute_on_s[MAX_ID_LEN + 1], hostid_s[MAX_ID_LEN + 1], - eventid_s[MAX_ID_LEN + 1], proxy_hostid_s[MAX_ID_LEN + 1]; - + int ret = SUCCEED; + char auditid_cuid[CUID_LEN], execute_on_s[MAX_ID_LEN + 1], hostid_s[MAX_ID_LEN + 1], + eventid_s[MAX_ID_LEN + 1], proxy_hostid_s[MAX_ID_LEN + 1]; + char *details_esc; struct zbx_json details_json; zbx_config_t cfg; @@ -209,27 +214,24 @@ int zbx_auditlog_global_script(unsigned char script_type, unsigned char script_e append_str_json(&details_json, AUDIT_DETAILS_ACTION_ADD, "script.command", script_command_orig); if (NULL != output) - { - char *output_esc; - - output_esc = zbx_strdup(NULL, output); - zbx_json_escape(&output_esc); - append_str_json(&details_json, AUDIT_DETAILS_ACTION_ADD, "script.output", output_esc); - zbx_free(output_esc); - } + append_str_json(&details_json, AUDIT_DETAILS_ACTION_ADD, "script.output", output); if (NULL != error) append_str_json(&details_json, AUDIT_DETAILS_ACTION_ADD, "script.error", error); + details_esc = DBdyn_escape_string(details_json.buffer); + if (ZBX_DB_OK > DBexecute("insert into auditlog (auditid,userid,username,clock,action,ip,resourceid," "resourcename,resourcetype,recordsetid,details) values ('%s'," ZBX_FS_UI64 ",'%s',%d,'%d','%s'," ZBX_FS_UI64 ",'%s',%d,'%s','%s')", auditid_cuid, userid, username, (int)time(NULL), AUDIT_ACTION_EXECUTE, clientip, hostid, hostname, AUDIT_RESOURCE_SCRIPT, auditid_cuid, - details_json.buffer)) + details_esc)) { ret = FAIL; } + zbx_free(details_esc); + zbx_json_free(&details_json); out: zabbix_log(LOG_LEVEL_TRACE, "End of %s():%s", __func__, zbx_result_string(ret)); @@ -239,15 +241,15 @@ out: static unsigned zbx_audit_hash_func(const void *data) { - const zbx_audit_entry_t * const *audit_entry = (const zbx_audit_entry_t * const *)data; zbx_hash_t hash; + const zbx_audit_entry_t * const *audit_entry = (const zbx_audit_entry_t * const *)data; hash = ZBX_DEFAULT_UINT64_HASH_FUNC(&(*audit_entry)->id); if (NULL != (*audit_entry)->cuid) hash = ZBX_DEFAULT_STRING_HASH_ALGO((*audit_entry)->cuid, strlen((*audit_entry)->cuid), hash); - return hash; + return ZBX_DEFAULT_UINT64_HASH_ALGO(&((*audit_entry)->id_table), sizeof((*audit_entry)->id_table), hash); } static int zbx_audit_compare_func(const void *d1, const void *d2) @@ -256,6 +258,7 @@ static int zbx_audit_compare_func(const void *d1, const void *d2) const zbx_audit_entry_t * const *audit_entry_2 = (const zbx_audit_entry_t * const *)d2; ZBX_RETURN_IF_NOT_EQUAL((*audit_entry_1)->id, (*audit_entry_2)->id); + ZBX_RETURN_IF_NOT_EQUAL((*audit_entry_1)->id_table, (*audit_entry_2)->id_table); return zbx_strcmp_null((*audit_entry_1)->cuid, (*audit_entry_2)->cuid); } @@ -299,7 +302,7 @@ int zbx_audit_initialized(void) void zbx_audit_flush(void) { - char audit_cuid[CUID_LEN], recsetid_cuid[CUID_LEN]; + char recsetid_cuid[CUID_LEN]; zbx_hashset_iter_t iter; zbx_audit_entry_t **audit_entry; zbx_db_insert_t db_insert_audit; @@ -314,15 +317,18 @@ void zbx_audit_flush(void) while (NULL != (audit_entry = (zbx_audit_entry_t **)zbx_hashset_iter_next(&iter))) { - zbx_new_cuid(audit_cuid); if (AUDIT_ACTION_DELETE == (*audit_entry)->audit_action || 0 != strcmp((*audit_entry)->details_json.buffer, "{}")) { - zbx_db_insert_add_values(&db_insert_audit, audit_cuid, AUDIT_USERID, AUDIT_USERNAME, - (int)time(NULL), (*audit_entry)->audit_action, AUDIT_IP, (*audit_entry)->id, - (*audit_entry)->name, (*audit_entry)->resource_type, - recsetid_cuid, 0 == strcmp((*audit_entry)->details_json.buffer, "{}") ? "" : - (*audit_entry)->details_json.buffer); + char *details_esc; + + details_esc = DBdyn_escape_string((*audit_entry)->details_json.buffer); + + zbx_db_insert_add_values(&db_insert_audit, (*audit_entry)->audit_cuid, AUDIT_USERID, + AUDIT_USERNAME, (int)time(NULL), (*audit_entry)->audit_action, AUDIT_IP, + (*audit_entry)->id, (*audit_entry)->name, (*audit_entry)->resource_type, + recsetid_cuid, 0 == strcmp(details_esc, "{}") ? "" : details_esc); + zbx_free(details_esc); } } @@ -334,7 +340,7 @@ void zbx_audit_flush(void) int zbx_audit_flush_once(void) { - char audit_cuid[CUID_LEN], recsetid_cuid[CUID_LEN]; + char recsetid_cuid[CUID_LEN]; int ret = ZBX_DB_OK; zbx_hashset_iter_t iter; zbx_audit_entry_t **audit_entry; @@ -347,7 +353,7 @@ int zbx_audit_flush_once(void) while (NULL != (audit_entry = (zbx_audit_entry_t **)zbx_hashset_iter_next(&iter))) { - char id[ZBX_MAX_UINT64_LEN + 1], *pfield, *pvalue, *name_esc; + char id[ZBX_MAX_UINT64_LEN + 1], *pfield, *pvalue, *name_esc, *details_esc; if (AUDIT_ACTION_DELETE != (*audit_entry)->audit_action && 0 == strcmp((*audit_entry)->details_json.buffer, "{}")) @@ -355,8 +361,6 @@ int zbx_audit_flush_once(void) continue; } - zbx_new_cuid(audit_cuid); - if (0 != (*audit_entry)->id) { zbx_snprintf(id, sizeof(id), ZBX_FS_UI64, (*audit_entry)->id); @@ -370,15 +374,16 @@ int zbx_audit_flush_once(void) } name_esc = DBdyn_escape_string((*audit_entry)->name); + details_esc = DBdyn_escape_string((*audit_entry)->details_json.buffer); ret = DBexecute_once("insert into auditlog (auditid,userid,username," "clock,action,ip,%s,resourcename,resourcetype,recordsetid,details) values" " ('%s',%d,'%s','%d','%d','%s','%s','%s',%d,'%s','%s')", - pfield, audit_cuid, AUDIT_USERID, AUDIT_USERNAME, (int)time(NULL), + pfield, (*audit_entry)->audit_cuid, AUDIT_USERID, AUDIT_USERNAME, (int)time(NULL), (*audit_entry)->audit_action, AUDIT_IP, pvalue, name_esc, (*audit_entry)->resource_type, - recsetid_cuid, 0 == strcmp((*audit_entry)->details_json.buffer, "{}") ? "" : - (*audit_entry)->details_json.buffer); + recsetid_cuid, 0 == strcmp(details_esc, "{}") ? "" : details_esc); + zbx_free(details_esc); zbx_free(name_esc); if (ZBX_DB_OK > ret) @@ -390,15 +395,65 @@ int zbx_audit_flush_once(void) return ret; } -void zbx_audit_update_json_append_string(const zbx_uint64_t id, const char *audit_op, const char *key, - const char *value) +static int audit_field_default(const char *table_name, const char *field_name, const char *value, uint64_t id) +{ + static ZBX_THREAD_LOCAL char cached_table_name[ZBX_TABLENAME_LEN_MAX]; + static ZBX_THREAD_LOCAL const ZBX_TABLE *table = NULL; + const ZBX_FIELD *field; + + if (NULL == table_name) + return FAIL; + + /* Often 'table_name' stays the same and only 'field_name' changes in successive calls of this function. */ + /* Here a simple caching of DBget_table() result is implemented. We rely on static array 'cached_table_name' */ + /* initialization with zero bytes, i.e. with empty string. */ + + if ('\0' == cached_table_name[0] || 0 != strcmp(cached_table_name, table_name)) + { + if (NULL == (table = DBget_table(table_name))) + { + zabbix_log(LOG_LEVEL_CRIT, "%s(): cannot find table '%s'", __func__, table_name); + THIS_SHOULD_NEVER_HAPPEN; + return FAIL; + } + + zbx_strlcpy(cached_table_name, table_name, sizeof(cached_table_name)); + } + + if (NULL == (field = DBget_field(table, field_name))) + { + zabbix_log(LOG_LEVEL_CRIT, "%s(): table '%s', cannot find field '%s'", __func__, table_name, + field_name); + THIS_SHOULD_NEVER_HAPPEN; + return FAIL; + } + + if (NULL != field->default_value) + { + if (NULL != value && (0 == strcmp(value, field->default_value) || + (ZBX_TYPE_FLOAT == field->type && SUCCEED == zbx_double_compare(atof(value), + atof(field->default_value))))) + { + return SUCCEED; + } + } + else if (NULL == value || (ZBX_TYPE_ID == field->type && 0 == id)) + return SUCCEED; + + return FAIL; +} + +void zbx_audit_update_json_append_string(const zbx_uint64_t id, const int id_table, const char *audit_op, + const char *key, const char *value, const char *table, const char *field) { zbx_audit_entry_t local_audit_entry, **found_audit_entry; zbx_audit_entry_t *local_audit_entry_x = &local_audit_entry; - local_audit_entry.id = id; - local_audit_entry.cuid = NULL; + if (SUCCEED == audit_field_default(table, field, value, 0)) + return; + local_audit_entry.id = id; + local_audit_entry.id_table = id_table; found_audit_entry = (zbx_audit_entry_t**)zbx_hashset_search(&zbx_audit, &(local_audit_entry_x)); if (NULL == found_audit_entry) @@ -410,15 +465,41 @@ void zbx_audit_update_json_append_string(const zbx_uint64_t id, const char *audi append_str_json(&((*found_audit_entry)->details_json), audit_op, key, value); } -void zbx_audit_update_json_append_uint64(const zbx_uint64_t id, const char *audit_op, const char *key, - uint64_t value) +void zbx_audit_update_json_append_string_secret(const zbx_uint64_t id, const int id_table, const char *audit_op, + const char *key, const char *value, const char *table, const char *field) { zbx_audit_entry_t local_audit_entry, **found_audit_entry; zbx_audit_entry_t *local_audit_entry_x = &local_audit_entry; + if (SUCCEED == audit_field_default(table, field, value, 0)) + return; + local_audit_entry.id = id; - local_audit_entry.cuid = NULL; + local_audit_entry.id_table = id_table; + found_audit_entry = (zbx_audit_entry_t**)zbx_hashset_search(&zbx_audit, &(local_audit_entry_x)); + + if (NULL == found_audit_entry) + { + THIS_SHOULD_NEVER_HAPPEN; + exit(EXIT_FAILURE); + } + + append_str_json(&((*found_audit_entry)->details_json), audit_op, key, ZBX_MACRO_SECRET_MASK); +} + +void zbx_audit_update_json_append_uint64(const zbx_uint64_t id, const int id_table, const char *audit_op, + const char *key, uint64_t value, const char *table, const char *field) +{ + char buffer[MAX_ID_LEN]; + zbx_audit_entry_t local_audit_entry, **found_audit_entry; + zbx_audit_entry_t *local_audit_entry_x = &local_audit_entry; + + zbx_snprintf(buffer, sizeof(buffer), ZBX_FS_UI64, value); + if (SUCCEED == audit_field_default(table, field, buffer, value)) + return; + local_audit_entry.id = id; + local_audit_entry.id_table = id_table; found_audit_entry = (zbx_audit_entry_t**)zbx_hashset_search(&zbx_audit, &(local_audit_entry_x)); if (NULL == found_audit_entry) @@ -435,8 +516,7 @@ void zbx_audit_update_json_append_uint64(const zbx_uint64_t id, const char *audi zbx_audit_entry_t *local_audit_entry_x = &local_audit_entry; \ \ local_audit_entry.id = id; \ - local_audit_entry.cuid = NULL; \ - \ + local_audit_entry.id_table = id_table; \ found_audit_entry = (zbx_audit_entry_t**)zbx_hashset_search(&zbx_audit, \ &(local_audit_entry_x)); \ if (NULL == found_audit_entry) \ @@ -445,64 +525,90 @@ void zbx_audit_update_json_append_uint64(const zbx_uint64_t id, const char *audi exit(EXIT_FAILURE); \ } \ -void zbx_audit_update_json_append_no_value(const zbx_uint64_t id, const char *audit_op, const char *key) +void zbx_audit_update_json_append_no_value(const zbx_uint64_t id, const int id_table, const char *audit_op, + const char *key) { PREPARE_UPDATE_JSON_APPEND_OP(); append_json_no_value(&((*found_audit_entry)->details_json), audit_op, key); } -void zbx_audit_update_json_append_int(const zbx_uint64_t id, const char *audit_op, const char *key, int value) +void zbx_audit_update_json_append_int(const zbx_uint64_t id, const int id_table, const char *audit_op, + const char *key, int value, const char *table, const char *field) { - PREPARE_UPDATE_JSON_APPEND_OP(); - append_int_json(&((*found_audit_entry)->details_json), audit_op, key, value); + char buffer[MAX_ID_LEN]; + + zbx_snprintf(buffer, sizeof(buffer), "%d", value); + + if (SUCCEED == audit_field_default(table, field, buffer, 0)) + { + return; + } + else + { + PREPARE_UPDATE_JSON_APPEND_OP(); + append_int_json(&((*found_audit_entry)->details_json), audit_op, key, value); + } } -void zbx_audit_update_json_append_double(const zbx_uint64_t id, const char *audit_op, const char *key, double value) +void zbx_audit_update_json_append_double(const zbx_uint64_t id, const int id_table, const char *audit_op, + const char *key, double value, const char *table, const char *field) { - PREPARE_UPDATE_JSON_APPEND_OP(); - append_double_json(&((*found_audit_entry)->details_json), audit_op, key, value); + char buffer[MAX_ID_LEN]; + + zbx_snprintf(buffer, sizeof(buffer), ZBX_FS_DBL, value); + + if (SUCCEED == audit_field_default(table, field, buffer, 0)) + { + return; + } + else + { + PREPARE_UPDATE_JSON_APPEND_OP(); + append_double_json(&((*found_audit_entry)->details_json), audit_op, key, value); + } } -void zbx_audit_update_json_update_string(const zbx_uint64_t id, const char *key, const char *value_old, - const char *value_new) +void zbx_audit_update_json_update_string(const zbx_uint64_t id, const int id_table, const char *key, + const char *value_old, const char *value_new) { PREPARE_UPDATE_JSON_APPEND_OP(); update_str_json(&((*found_audit_entry)->details_json), key, value_old, value_new); } -void zbx_audit_update_json_update_uint64(const zbx_uint64_t id, const char *key, uint64_t value_old, - uint64_t value_new) +void zbx_audit_update_json_update_uint64(const zbx_uint64_t id, const int id_table, const char *key, + uint64_t value_old, uint64_t value_new) { PREPARE_UPDATE_JSON_APPEND_OP(); update_uint64_json(&((*found_audit_entry)->details_json), key, value_old, value_new); } -void zbx_audit_update_json_update_int(const zbx_uint64_t id, const char *key, int value_old, +void zbx_audit_update_json_update_int(const zbx_uint64_t id, const int id_table, const char *key, int value_old, int value_new) { PREPARE_UPDATE_JSON_APPEND_OP(); update_int_json(&((*found_audit_entry)->details_json), key, value_old, value_new); } -void zbx_audit_update_json_update_double(const zbx_uint64_t id, const char *key, double value_old, - double value_new) +void zbx_audit_update_json_update_double(const zbx_uint64_t id, const int id_table, const char *key, + double value_old, double value_new) { PREPARE_UPDATE_JSON_APPEND_OP(); update_double_json(&((*found_audit_entry)->details_json), key, value_old, value_new); } -void zbx_audit_update_json_delete(const zbx_uint64_t id, const char *audit_op, const char *key) +void zbx_audit_update_json_delete(const zbx_uint64_t id, const int id_table, const char *audit_op, const char *key) { PREPARE_UPDATE_JSON_APPEND_OP(); delete_json(&((*found_audit_entry)->details_json), audit_op, key); } -zbx_audit_entry_t *zbx_audit_get_entry(zbx_uint64_t id, const char *cuid) +zbx_audit_entry_t *zbx_audit_get_entry(zbx_uint64_t id, const char *cuid, int id_table) { zbx_audit_entry_t local_audit_entry, *plocal_audit_entry = &local_audit_entry, **paudit_entry; local_audit_entry.id = id; local_audit_entry.cuid = (char *)cuid; + local_audit_entry.id_table = id_table; if (NULL == (paudit_entry = (zbx_audit_entry_t**)zbx_hashset_search(&zbx_audit, &plocal_audit_entry))) { |