* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
* Portions Copyright (c) 2021, openGauss Contributors
*
* openGauss is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* --------------------------------------------------------------------------
* auditfuncs.cpp
* record the aduit informations of the database operation
*
* IDENTIFICATION
* src/gausskernel/process/auditfuncs.cpp
*
* -------------------------------------------------------------------------
*/
#include "postgres.h"
#include "commands/dbcommands.h"
#include "knl/knl_variable.h"
#include "executor/executor.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "tcop/utility.h"
#include "pgaudit.h"
#include "libpq/libpq-be.h"
#include "catalog/namespace.h"
#include "auditfuncs.h"
#include "utils/elog.h"
#include "libpq/libpq-be.h"
#include "utils/builtins.h"
#include "miscadmin.h"
#include "utils/rangetypes.h"
#include "utils/inet.h"
#include "fmgr.h"
#include "utils/nabstime.h"
#include "access/tupmacs.h"
#include "utils/fmgrtab.h"
#include "lib/stringinfo.h"
#include "utils/cash.h"
#include "utils/lsyscache.h"
#include "catalog/namespace.h"
#include "utils/uuid.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/numeric.h"
#include "utils/numeric_gs.h"
#include "workload/cpwlm.h"
#define AUDIT_BUFFERSIZ 512
typedef void (*AuditFunc)(const char* objectname, const char* cmdtext);
typedef struct AuditFuncMap {
ObjectType objType;
AuditFunc auditFunc;
}AuditFuncMap;
static THR_LOCAL ExecutorEnd_hook_type prev_ExecutorEnd = NULL;
static THR_LOCAL ProcessUtility_hook_type prev_ProcessUtility = NULL;
static char* pgaudit_get_function_name(List* funcnamelist);
static void pgaudit_ExecutorEnd(QueryDesc* queryDesc);
static void pgaudit_store_auditstat(
AuditType audittype, AuditResult auditresult, const char* objectname, const char* detailsinfo);
static void pgaudit_ProcessUtility(processutility_context* processutility_cxt,
DestReceiver* dest,
#ifdef PGXC
bool sentToRemote,
#endif
char* completionTag,
ProcessUtilityContext context,
bool isCTAS);
static void pgaudit_ddl_database(const char* objectname, const char* cmdtext);
static void pgaudit_ddl_directory(const char* objectname, const char* cmdtext);
static void pgaudit_ddl_database_object(
AuditType audittype, AuditResult auditresult, const char* objectname, const char* cmdtext);
static void pgaudit_ddl_index(const char* objectname, const char* cmdtext);
static void pgaudit_ddl_schema(const char* objectname, const char* cmdtext);
static void pgaudit_ddl_table(const char* objectname, const char* cmdtext);
static void pgaudit_ddl_tablespace(const char* objectname, const char* cmdtext);
static void pgaudit_ddl_trigger(const char* objectname, const char* cmdtext);
static void pgaudit_ddl_user(const char* objectname, const char* cmdtext);
static void pgaudit_ddl_view(const char* objectname, const char* cmdtext);
static void pgaudit_ddl_matview(const char* objectname, const char* cmdtext);
static void pgaudit_ddl_event(const char* objectname, const char* cmdtext);
static void pgaudit_ddl_function(const char* objectname, const char* cmdtext);
static void pgaudit_ddl_package(const char* objectname, const char* cmdtext);
static void pgaudit_ddl_resourcepool(const char* objectname, const char* cmdtext);
static void pgaudit_alter_globalconfig(const AlterGlobalConfigStmt* stmt, const char* cmdtext);
static void pgaudit_drop_globalconfig(const DropGlobalConfigStmt* stmt, const char* cmdtext);
static void pgaudit_ddl_workload(const char* objectname, const char* cmdtext);
static void pgaudit_ddl_serverforhardoop(const char* objectname, const char* cmdtext);
static void pgaudit_ddl_model(const char* objectname, const char* cmdtext);
static void pgaudit_process_alter_object(Node* node, const char* querystring);
static void pgaudit_process_alter_owner(Node* node, const char* querystring);
static void pgaudit_process_drop_objects(Node* node, const char* querystring);
static void pgaudit_process_reindex(Node* node, const char* querystring);
static void pgaudit_process_rename_object(Node* node, const char* querystring);
static void pgaudit_process_grant_or_revoke_roles(List* grantee_name_list, bool isgrant, const char* querystring);
static void pgaudit_delete_files(const char* objectname, const char* cmdtext);
static void pgaudit_ddl_weak_password(const char* cmdtext);
static void pgaudit_ddl_full_encryption_key(const char* cmdtext);
static void pgaudit_ddl_type(const char* objectname, const char* cmdtext);
static void pgaudit_ddl_datasource(const char* objectname, const char* cmdtext);
static void pgaudit_ddl_rowlevelsecurity(const char* objectname, const char* cmdtext);
static void pgaudit_ddl_synonym(const char* objectName, const char* cmdText);
static void pgaudit_ddl_textsearch(const char* objectname, const char* cmdtext);
static void pgaudit_ddl_publication_subscription(const char* objectname, const char* cmdtext);
static void pgaudit_ddl_fdw(const char* objectname, const char* cmdtext);
static char* audit_get_func_args(FunctionCallInfo fcinfo);
static char* audit_get_text_array_value(ArrayType* array, int* numitems);
#define BUF_LENGTH 64
#define PG_GETARG_COMMANDID(n) DatumGetCommandId(PG_GETARG_DATUM(n))
#define SYSTEM_FUNC_DEFAULT_VALUE "NULL"
static const AuditFuncMap g_auditFuncMap[] = {
{OBJECT_SCHEMA, pgaudit_ddl_schema},
{OBJECT_TABLE, pgaudit_ddl_table},
{OBJECT_FOREIGN_TABLE, pgaudit_ddl_table},
{OBJECT_STREAM, pgaudit_ddl_table},
{OBJECT_INTERNAL, pgaudit_ddl_table},
{OBJECT_TABLESPACE, pgaudit_ddl_tablespace},
{OBJECT_ROLE, pgaudit_ddl_user},
{OBJECT_USER, pgaudit_ddl_user},
{OBJECT_TRIGGER, pgaudit_ddl_trigger},
{OBJECT_CONTQUERY, pgaudit_ddl_view},
{OBJECT_VIEW, pgaudit_ddl_view},
{OBJECT_MATVIEW, pgaudit_ddl_matview},
{OBJECT_INDEX, pgaudit_ddl_index},
{OBJECT_TYPE, pgaudit_ddl_type},
{OBJECT_DATABASE, pgaudit_ddl_database},
{OBJECT_FUNCTION, pgaudit_ddl_function},
{OBJECT_PACKAGE, pgaudit_ddl_package},
{OBJECT_FOREIGN_SERVER, pgaudit_ddl_serverforhardoop},
{OBJECT_DATA_SOURCE, pgaudit_ddl_datasource},
{OBJECT_DIRECTORY, pgaudit_ddl_directory},
{OBJECT_RLSPOLICY, pgaudit_ddl_rowlevelsecurity},
{OBJECT_SYNONYM, pgaudit_ddl_synonym},
{OBJECT_TSDICTIONARY, pgaudit_ddl_textsearch},
{OBJECT_TSCONFIGURATION, pgaudit_ddl_textsearch},
{OBJECT_PUBLICATION, pgaudit_ddl_publication_subscription},
{OBJECT_SUBSCRIPTION, pgaudit_ddl_publication_subscription},
{OBJECT_FDW, pgaudit_ddl_fdw},
{OBJECT_EVENT, pgaudit_ddl_event}
};
static const int g_auditFuncMapNum = sizeof(g_auditFuncMap) / sizeof(AuditFuncMap);
* Brief : perfstat_agent_init()
* Description : Module load callback.
* Notes : Called from postmaster.
*/
void pgaudit_agent_init(void)
{
if (!IsPostmasterEnvironment || !u_sess->attr.attr_security.Audit_enabled ||
u_sess->exec_cxt.g_pgaudit_agent_attached) {
return;
}
prev_ExecutorEnd = ExecutorEnd_hook;
ExecutorEnd_hook = pgaudit_ExecutorEnd;
prev_ProcessUtility = ProcessUtility_hook;
ProcessUtility_hook = (ProcessUtility_hook_type)pgaudit_ProcessUtility;
u_sess->exec_cxt.g_pgaudit_agent_attached = true;
}
* Brief : perfstat_agent_fini()
* Description : Module unload callback.
*/
void pgaudit_agent_fini(void)
{
if (!u_sess->exec_cxt.g_pgaudit_agent_attached) {
return;
}
u_sess->exec_cxt.g_pgaudit_agent_attached = false;
ExecutorEnd_hook = prev_ExecutorEnd;
ProcessUtility_hook = prev_ProcessUtility;
}
* Brief : void pgaudit_system_recovery_ok()
* Description : audit the system recovery ok
*/
void pgaudit_system_recovery_ok()
{
AuditType audit_type;
AuditResult audit_result;
char details[PGAUDIT_MAXLENGTH] = {0};
audit_type = AUDIT_SYSTEM_RECOVER;
audit_result = AUDIT_OK;
int rc = snprintf_s(details, sizeof(details), sizeof(details) - 1, "system recovery success");
securec_check_ss(rc, "", "");
audit_report(audit_type, audit_result, NULL, details);
}
* Brief : void pgaudit_system_start_ok(int port)
* Description : audit the system startup
*/
void pgaudit_system_start_ok(int port)
{
AuditType audit_type;
AuditResult audit_result;
char details[PGAUDIT_MAXLENGTH] = {0};
audit_type = AUDIT_SYSTEM_START;
audit_result = AUDIT_OK;
int rc = snprintf_s(details, sizeof(details), sizeof(details) - 1, "system startup success(port = %d)", port);
securec_check_ss(rc, "", "");
audit_report(audit_type, audit_result, NULL, details);
}
* Brief : void pgaudit_user_login(bool login_ok, char* object_name,const char* detaisinfo)
* Description : audit the user login
*/
void pgaudit_user_login(bool login_ok, const char* object_name, const char* detailinfo)
{
AuditType audit_type;
AuditResult audit_result;
Assert(detailinfo);
if (login_ok) {
audit_type = AUDIT_LOGIN_SUCCESS;
audit_result = AUDIT_OK;
} else {
audit_type = AUDIT_LOGIN_FAILED;
audit_result = AUDIT_FAILED;
}
char new_login_info[PGAUDIT_MAXLENGTH] = {0};
Port *port = u_sess->proc_cxt.MyProcPort;
if (port != NULL) {
int rc = snprintf_s(new_login_info, PGAUDIT_MAXLENGTH, PGAUDIT_MAXLENGTH - 1, "%s, SSL=%s", detailinfo,
port->ssl != NULL ? "on" : "off");
securec_check_ss(rc, "", "");
}
audit_report(audit_type, audit_result, object_name, port != NULL ? new_login_info : detailinfo);
}
* Brief : void pgaudit_user_logout()
* Description : audit the user logout
*/
void pgaudit_user_logout()
{
if (!u_sess->misc_cxt.authentication_finished)
return;
AuditType audit_type;
AuditResult audit_result;
char details[PGAUDIT_MAXLENGTH] = {0};
audit_type = AUDIT_USER_LOGOUT;
audit_result = AUDIT_OK;
TimestampTz now = GetCurrentTimestamp();
int rc;
if (now >= u_sess->storage_cxt.session_fin_time && u_sess->attr.attr_common.SessionTimeout) {
rc = snprintf_s(details,
sizeof(details),
sizeof(details) - 1,
"session timeout, logout db(%s) success",
u_sess->proc_cxt.MyProcPort->database_name);
} else {
rc = snprintf_s(details,
sizeof(details),
sizeof(details) - 1,
"logout db(%s) success",
u_sess->proc_cxt.MyProcPort->database_name);
}
securec_check_ss(rc, "", "");
audit_report(audit_type, audit_result, u_sess->proc_cxt.MyProcPort->database_name, details);
}
* Brief : void pgaudit_system_stop_ok(int shutdown)
* Description : audit the system stop
*/
void pgaudit_system_stop_ok(int shutdown)
{
AuditType audit_type;
AuditResult audit_result;
const char* shutdowmothods[] = {"smart", "fast", "immediate"};
char details[PGAUDIT_MAXLENGTH] = {0};
if (shutdown > ImmediateShutdown || shutdown < SmartShutdown)
return;
audit_type = AUDIT_SYSTEM_STOP;
audit_result = AUDIT_OK;
int rc = snprintf_s(
details, sizeof(details), sizeof(details) - 1, "system stop %s success", shutdowmothods[shutdown - 1]);
securec_check_ss(rc, "", "");
audit_report(audit_type, audit_result, NULL, details);
}
* Brief : void pgaudit_system_switchover_ok(const char* detaisinfo)
* Description : audit the system switchover
*/
void pgaudit_system_switchover_ok(const char* detaisinfo)
{
AuditType audit_type;
AuditResult audit_result;
char details[PGAUDIT_MAXLENGTH] = {0};
Assert(detaisinfo);
audit_type = AUDIT_SYSTEM_SWITCH;
audit_result = AUDIT_OK;
int rc = snprintf_s(details, sizeof(details), sizeof(details) - 1, "%s", detaisinfo);
securec_check_ss(rc, "", "");
audit_report(audit_type, audit_result, NULL, details);
}
* Brief : void pgaudit_user_no_privileges(const char* object_name,const char* detailsinfo)
* Description : audit the user have no privileges
*/
void pgaudit_user_no_privileges(const char* object_name, const char* detailsinfo)
{
AuditType audit_type;
AuditResult audit_result;
audit_type = AUDIT_USER_VIOLATION;
audit_result = AUDIT_FAILED;
audit_report(audit_type, audit_result, object_name, detailsinfo);
}
* Brief : void pgaudit_lock_or_unlock_user(bool islocked,const char* user_name)
* Description : audit lock or unlock user
*/
void pgaudit_lock_or_unlock_user(bool islocked, const char* user_name)
{
AuditType audit_type;
AuditResult audit_result;
char details[PGAUDIT_MAXLENGTH] = {0};
int rc = 0;
if (user_name == NULL) {
user_name = "UNKOWN USER";
}
if (islocked) {
audit_type = AUDIT_LOCK_USER;
audit_result = AUDIT_OK;
rc = snprintf_s(details, sizeof(details), sizeof(details) - 1, "the user(%s) has been locked", user_name);
} else {
audit_type = AUDIT_UNLOCK_USER;
audit_result = AUDIT_OK;
rc = snprintf_s(details, sizeof(details), sizeof(details) - 1, "the user(%s) has been unlocked", user_name);
}
securec_check_ss(rc, "", "");
audit_report(audit_type, audit_result, user_name, details);
}
* Brief : void PGAuditNotify(const char* conditionname)
* Description : audit the NOTIFY statement
*/
static void PGAuditNotify(const char* conditionname)
{
AuditType auditType = AUDIT_ASYNC;
AuditResult auditResult = AUDIT_OK;
char details[PGAUDIT_MAXLENGTH] = {0};
int rc = 0;
rc = snprintf_s(details, sizeof(details), sizeof(details) - 1,
"notify channel \"%s\" success", conditionname);
securec_check_ss(rc, "", "");
audit_report(auditType, auditResult, NULL, details);
}
* Brief : void PGAuditListen(const char* conditionname)
* Description : audit the LISTEN statement
*/
static void PGAuditListen(const char* conditionname)
{
AuditType auditType = AUDIT_ASYNC;
AuditResult auditResult = AUDIT_OK;
char details[PGAUDIT_MAXLENGTH] = {0};
int rc = snprintf_s(details, sizeof(details), sizeof(details) - 1,
"listen channel \"%s\" success", conditionname);
securec_check_ss(rc, "", "");
audit_report(auditType, auditResult, NULL, details);
}
* Brief : void PGAuditUnlisten(const char* conditionname)
* Description : audit the UNLISTEN statement
*/
static void PGAuditUnlisten(const char* conditionname)
{
AuditType auditType = AUDIT_ASYNC;
AuditResult auditResult = AUDIT_OK;
char details[PGAUDIT_MAXLENGTH] = {0};
int rc = 0;
if (conditionname) {
rc = snprintf_s(details, sizeof(details), sizeof(details) - 1,
"unlisten channel \"%s\" success", conditionname);
} else {
rc = snprintf_s(details, sizeof(details), sizeof(details) - 1,
"unlisten all channels success");
}
securec_check_ss(rc, "", "");
audit_report(auditType, auditResult, NULL, details);
}
* Description: store the audit informations
*/
static void pgaudit_store_auditstat(
AuditType audittype, AuditResult auditresult, const char* objectname, const char* detailsinfo)
{
Assert(detailsinfo);
audit_report(audittype, auditresult, objectname, detailsinfo);
}
* Description :Audit the ddl cmd
*/
static void pgaudit_ddl_database_object(
AuditType audit_type, AuditResult audit_result, const char* objectname, const char* cmdtext)
{
Assert(cmdtext != NULL);
char* mask_string = maskPassword(cmdtext);
if (mask_string == NULL) {
if (u_sess->attr.attr_sql.dolphin) {
mask_string = mask_error_password(cmdtext, strlen(cmdtext));
} else {
mask_string = (char*)cmdtext;
}
}
switch (audit_type) {
case AUDIT_DDL_DATABASE:
case AUDIT_DDL_DIRECTORY:
case AUDIT_DDL_INDEX:
case AUDIT_DDL_SCHEMA:
case AUDIT_DDL_FUNCTION:
case AUDIT_DDL_PACKAGE:
case AUDIT_DDL_TABLE:
case AUDIT_DDL_TABLESPACE:
case AUDIT_DDL_TRIGGER:
case AUDIT_DDL_USER:
case AUDIT_DDL_VIEW:
case AUDIT_DDL_EVENT:
case AUDIT_DDL_RESOURCEPOOL:
case AUDIT_DDL_GLOBALCONFIG:
case AUDIT_DDL_WORKLOAD:
case AUDIT_DDL_SERVERFORHADOOP:
case AUDIT_DDL_DATASOURCE:
case AUDIT_DDL_NODEGROUP:
case AUDIT_DDL_ROWLEVELSECURITY:
case AUDIT_DDL_SYNONYM:
case AUDIT_DDL_TYPE:
case AUDIT_DDL_TEXTSEARCH:
case AUDIT_DDL_SEQUENCE:
case AUDIT_DDL_KEY:
case AUDIT_DDL_MODEL:
case AUDIT_DDL_PUBLICATION_SUBSCRIPTION:
case AUDIT_DDL_FOREIGN_DATA_WRAPPER:
case AUDIT_DDL_SQL_PATCH:
pgaudit_store_auditstat(audit_type, audit_result, objectname, mask_string);
break;
default:
ereport(LOG, (errmsg("UNKOWN AUDIT TYPE FOR DDL OPERATION.")));
break;
}
if (mask_string != cmdtext) {
selfpfree(mask_string);
}
return;
}
* Brief :void pgaudit_dml_table(char* objectname,const char* cmdtext)
* Description :Audit the DML cmd
*/
void pgaudit_dml_table(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DML_ACTION;
AuditResult audit_result = AUDIT_OK;
char* mask_string = NULL;
Assert(cmdtext);
bool is_full_audit_user = audit_check_full_audit_user();
if (u_sess->attr.attr_security.Audit_DML == 0 && !is_full_audit_user) {
return;
}
mask_string = maskPassword(cmdtext);
if (mask_string == NULL)
mask_string = (char*)cmdtext;
pgaudit_store_auditstat(audit_type, audit_result, objectname, mask_string);
if (mask_string != cmdtext)
pfree(mask_string);
}
* Brief :void pgaudit_dml_select(char* objectname,const char* cmdtext)
* Description :Audit the DML select cmd
*/
void pgaudit_dml_table_select(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DML_ACTION_SELECT;
AuditResult audit_result = AUDIT_OK;
char* mask_string = NULL;
bool is_full_audit_user = audit_check_full_audit_user();
if (u_sess->attr.attr_security.Audit_DML_SELECT == 0 && !is_full_audit_user) {
return;
}
mask_string = maskPassword(cmdtext);
if (mask_string == NULL)
mask_string = (char*)cmdtext;
pgaudit_store_auditstat(audit_type, audit_result, objectname, mask_string);
if (mask_string != cmdtext)
pfree(mask_string);
}
* Brief : pgaudit_delete_files(char* objectname,const char* cmdtext)
* Description : audit delete DDL operations of the given table
*/
static void pgaudit_delete_files(const char* objectname, const char* cmdtext)
{
AuditType audit_type;
AuditResult audit_result;
Assert(cmdtext);
audit_type = AUDIT_INTERNAL_EVENT;
audit_result = AUDIT_OK;
pgaudit_store_auditstat(audit_type, audit_result, objectname, cmdtext);
}
* Brief : pgaudit_ddl_table(char* objectname, const char* cmdtext)
* Description : audit DDL operations of the given table
*/
static void pgaudit_ddl_table(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_TABLE;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_TABLE)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
* Brief : pgaudit_ddl_type(char* objectname, const char* cmdtext)
* Description : audit DDL operations of the given type
*/
static void pgaudit_ddl_type(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_TYPE;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_TYPE)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
* Brief : pgaudit_ddl_user(char* objectname, const char* cmdtext)
* Description : Audit the operations of user
*/
static void pgaudit_ddl_user(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_USER;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_USER)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
static void pgaudit_ddl_model(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_MODEL;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_MODEL)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
* Brief : pgaudit_ddl_view(char* objectname, const char* cmdtext)
* Description : Audit the operations of view
*/
static void pgaudit_ddl_view(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_VIEW;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_VIEW)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
static void pgaudit_ddl_event(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_EVENT;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_EVENT)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
* Brief : pgaudit_ddl_matview(char* objectname, const char* cmdtext)
* Description : Audit the operations of matview
*/
static void pgaudit_ddl_matview(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_VIEW;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_VIEW)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
* Brief : pgaudit_ddl_database(char* objectname, const char* cmdtext)
* Description : Audit the operations of database
*/
static void pgaudit_ddl_database(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_DATABASE;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_DATABASE)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
* Brief : pgaudit_ddl_directory(char* objectname, const char* cmdtext)
* Description : Audit the operations of directory
*/
static void pgaudit_ddl_directory(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_DIRECTORY;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_DIRECTORY)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
* Brief : pgaudit_ddl_schema(char* objectname, const char* cmdtext)
* Description : Audit the operations of schema
*/
static void pgaudit_ddl_schema(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_SCHEMA;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_SCHEMA)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
* Brief : pgaudit_ddl_tablespace(char* objectname, const char* cmdtext)
* Description : Audit the operations of tablespace
*/
static void pgaudit_ddl_tablespace(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_TABLESPACE;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_TABLESPACE)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
* Brief : pgaudit_grant_or_revoke_role(bool isgrant, char* objectname, const char* cmdtext)
* Description : Audit the operations of role,grant or revoke
*/
static void pgaudit_grant_or_revoke_role(bool isgrant, const char* objectname, const char* cmdtext)
{
AuditType audit_type = isgrant ? AUDIT_GRANT_ROLE : AUDIT_REVOKE_ROLE;
AuditResult audit_result = AUDIT_OK;
char* mask_string = NULL;
Assert(cmdtext != NULL);
if (u_sess->attr.attr_security.Audit_PrivilegeAdmin == 0 && !audit_check_full_audit_user()) {
return;
}
mask_string = maskPassword(cmdtext);
if (mask_string == NULL) {
mask_string = (char*)cmdtext;
}
pgaudit_store_auditstat(audit_type, audit_result, objectname, mask_string);
if (mask_string != cmdtext) {
selfpfree(mask_string);
}
return;
}
* Brief : pgaudit_ddl_index(const char* objectname, const char* cmdtext)
* Description : Audit the operations of index
*/
static void pgaudit_ddl_index(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_INDEX;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_INDEX)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
* Brief : pgaudit_ddl_trigger(const char* objectname, const char* cmdtext)
* Description : Audit the operations of trigger
*/
static void pgaudit_ddl_trigger(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_TRIGGER;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_TRIGGER)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
* Brief : pgaudit_ddl_sequence(const char* objectname, const char* cmdtext)
* Description : Audit the operations of sequence
*/
static void pgaudit_ddl_sequence(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_SEQUENCE;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_SEQUENCE)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
* Brief : pgaudit_ddl_function(const char* objectname, const char* cmdtext)
* Description : Audit the operations of function
*/
static void pgaudit_ddl_function(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_FUNCTION;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_FUNCTION)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
* Brief : pgaudit_ddl_package(const char* objectname, const char* cmdtext)
* Description : Audit the operations of package
*/
static void pgaudit_ddl_package(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_PACKAGE;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_PACKAGE)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
* Brief : pgaudit_ddl_resourcepool(const char* objectname, const char* cmdtext)
* Description : Audit the operations of resource pool
*/
static void pgaudit_ddl_resourcepool(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_RESOURCEPOOL;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_RESOURCEPOOL)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
* Brief : pgaudit_ddl_resourcepool(const char* objectname, const char* cmdtext)
* Description : Audit the operations of gs_global_config
*/
static void pgaudit_alter_globalconfig(const AlterGlobalConfigStmt* stmt, const char* cmdtext)
{
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_GLOBALCONFIG)) {
return;
}
ListCell* option = NULL;
foreach (option, stmt->options) {
DefElem *defel = (DefElem *)lfirst(option);
pgaudit_ddl_database_object(AUDIT_DDL_GLOBALCONFIG, AUDIT_OK, defel->defname, cmdtext);
}
return;
}
* Brief : pgaudit_ddl_resourcepool(const char* objectname, const char* cmdtext)
* Description : Audit the operations of gs_global_config
*/
static void pgaudit_drop_globalconfig(const DropGlobalConfigStmt* stmt, const char* cmdtext)
{
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_GLOBALCONFIG)) {
return;
}
ListCell* option = NULL;
foreach (option, stmt->options) {
const char *global_name = strVal(lfirst(option));
pgaudit_ddl_database_object(AUDIT_DDL_GLOBALCONFIG, AUDIT_OK, global_name, cmdtext);
}
return;
}
* Brief : pgaudit_ddl_workload(const char* objectname, const char* cmdtext)
* Description : Audit the operations of workload
*/
static void pgaudit_ddl_workload(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_WORKLOAD;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_WORKLOAD)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
* Brief : pgaudit_ddl_serverforhardoop(const char* objectname, const char* cmdtext)
* Description : Audit the operations of server for hardoop
*/
static void pgaudit_ddl_serverforhardoop(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_SERVERFORHADOOP;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_SERVERFORHADOOP)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
* pgaudit_ddl_weak_password:
* AUDIT FOR WEAK PASSWORD DICTIONARY
*
* @RETURN: void
*/
static void pgaudit_ddl_weak_password(const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_TABLE;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_TABLE)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, "weak_password", cmdtext);
return;
}
* pgaudit_ddl_full_encryption_key:
* AUDIT FOR security client key create
*
* @RETURN: void
*/
static void pgaudit_ddl_full_encryption_key(const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_KEY;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_KEY)) {
return;
}
char *making_query = (char *)mask_encrypted_key(cmdtext, strlen(cmdtext));
pgaudit_ddl_database_object(audit_type, audit_result, "full_encryption_key", making_query);
if (making_query != cmdtext) {
selfpfree(making_query);
}
return;
}
* pgaudit_ddl_datasource:
* Audit the operations of data source
*
* @IN objectname: data source name
* @IN cmdtext: cmd string
* @RETURN: void
*/
static void pgaudit_ddl_datasource(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_DATASOURCE;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_DATASOURCE)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
* pgaudit_ddl_nodegroup:
* Audit the operations of node group
*
* @IN objectname: node group name
* @IN cmdtext: cmd string
* @RETURN: void
*/
static void pgaudit_ddl_nodegroup(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_NODEGROUP;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_NODEGROUP)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
* pgaudit_ddl_rowlevelsecurity:
* Audit the operations of node row level security
*
* @IN objectname: node row level security policy name
* @IN cmdtext: cmd string
* @RETURN: void
*/
static void pgaudit_ddl_rowlevelsecurity(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_ROWLEVELSECURITY;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_ROWLEVELSECURITY)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
* pgaudit_ddl_synonym:
* Audit the operations of synonym
*
* @IN objectname: synonym name
* @IN cmdtext: cmd string
* @RETURN: void
*/
static void pgaudit_ddl_synonym(const char* objectName, const char* cmdText)
{
AuditType auditType = AUDIT_DDL_SYNONYM;
AuditResult auditResult = AUDIT_OK;
Assert(cmdText);
if (!CHECK_AUDIT_DDL(DDL_SYNONYM)) {
return;
}
pgaudit_ddl_database_object(auditType, auditResult, objectName, cmdText);
return;
}
* Brief : pgaudit_ddl_textsearch(char* objectname, const char* cmdtext)
* Description : audit DDL operations of the given text search object
*/
static void pgaudit_ddl_textsearch(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_DDL_TEXTSEARCH;
AuditResult audit_result = AUDIT_OK;
Assert(cmdtext != NULL);
if (!CHECK_AUDIT_DDL(DDL_TEXTSEARCH)) {
return;
}
pgaudit_ddl_database_object(audit_type, audit_result, objectname, cmdtext);
return;
}
* pgaudit_ddl_publication_subscription:
* Audit the operations of publication and subscription
*
* @IN objectname: publication name or subscription name
* @IN cmdtext: cmd string
* @RETURN: void
*/
static void pgaudit_ddl_publication_subscription(const char* objectname, const char* cmdtext)
{
if (!CHECK_AUDIT_DDL(DDL_PUBLICATION_SUBSCRIPTION)) {
return;
}
pgaudit_ddl_database_object(AUDIT_DDL_PUBLICATION_SUBSCRIPTION, AUDIT_OK, objectname, cmdtext);
return;
}
* pgaudit_ddl_fdw:
* Audit the operations of foreign data wrapper
*
* @IN objectname: foreign data wrapper name
* @IN cmdtext: cmd string
* @RETURN: void
*/
static void pgaudit_ddl_fdw(const char* objectname, const char* cmdtext)
{
if (!CHECK_AUDIT_DDL(DDL_FOREIGN_DATA_WRAPPER)) {
return;
}
pgaudit_ddl_database_object(AUDIT_DDL_FOREIGN_DATA_WRAPPER, AUDIT_OK, objectname, cmdtext);
return;
}
void pgaudit_ddl_sql_patch(const char* objectname, const char* cmdtext)
{
if (!CHECK_AUDIT_DDL(DDL_SQL_PATCH)) {
return;
}
pgaudit_ddl_database_object(AUDIT_DDL_SQL_PATCH, AUDIT_OK, objectname, cmdtext);
}
* @Description: audit the operation of set parameter.
* @in objectname : the object name need audited.
* @in cmdtext : the command text need audited.
* @return : non-return.
*/
static void pgaudit_process_set_parameter(const char* objectname, const char* cmdtext)
{
AuditType audit_type = AUDIT_SET_PARAMETER;
AuditResult audit_result = AUDIT_OK;
char* mask_string = NULL;
Assert(cmdtext != NULL);
if (u_sess->attr.attr_security.Audit_Set == 0 && !audit_check_full_audit_user()) {
return;
}
mask_string = maskPassword(cmdtext);
if (mask_string == NULL)
mask_string = (char*)cmdtext;
audit_report(audit_type, audit_result, objectname, mask_string);
if (mask_string != cmdtext)
pfree(mask_string);
}
* Brief : pgaudit_process_drop_objects(Node* node,const char* querystring)
* Description : Audit the drop operation
*/
static void pgaudit_process_drop_objects(Node* node, const char* querystring)
{
DropStmt* stmt = (DropStmt*)node;
ListCell* arg = NULL;
char* objectname = NULL;
foreach (arg, stmt->objects) {
List* names = NIL;
RangeVar* rel = NULL;
if (stmt->removeType == OBJECT_DOMAIN ||
stmt->removeType == OBJECT_TYPE ) {
List *objname = (List*)lfirst(arg);
Node *ptype = (Node *) linitial(objname);
TypeName* typname = NULL;
if(ptype->type == T_String)
typname = makeTypeNameFromNameList(list_make1(ptype));
else if(ptype->type == T_TypeName)
typname = (TypeName *) linitial(objname);
else
ereport(ERROR, (errcode(ERRCODE_UNRECOGNIZED_NODE_TYPE), errmsg("unkonw type: %d", (int)ptype->type)));
names = typname->names;
} else {
names = (List*)lfirst(arg);
}
switch (stmt->removeType) {
case OBJECT_TABLE:
case OBJECT_STREAM:
case OBJECT_FOREIGN_TABLE: {
rel = makeRangeVarFromNameList(names);
objectname = rel->relname;
pgaudit_ddl_table(objectname, querystring);
} break;
case OBJECT_CONTQUERY:
case OBJECT_VIEW: {
rel = makeRangeVarFromNameList(names);
objectname = rel->relname;
pgaudit_ddl_view(objectname, querystring);
} break;
case OBJECT_EVENT: {
rel = makeRangeVarFromNameList(names);
objectname = rel->relname;
pgaudit_ddl_view(objectname, querystring);
} break;
case OBJECT_MATVIEW: {
rel = makeRangeVarFromNameList(names);
objectname = rel->relname;
pgaudit_ddl_matview(objectname, querystring);
} break;
case OBJECT_INDEX: {
rel = makeRangeVarFromNameList(names);
objectname = rel->relname;
pgaudit_ddl_index(objectname, querystring);
} break;
case OBJECT_SCHEMA: {
objectname = strVal(linitial(names));
pgaudit_ddl_schema(objectname, querystring);
} break;
case OBJECT_TRIGGER: {
objectname = strVal(lfirst(list_tail((List*)lfirst(list_tail(names)))));
pgaudit_ddl_trigger(objectname, querystring);
} break;
case OBJECT_FUNCTION: {
objectname = NameListToString(names);
pgaudit_ddl_function(objectname, querystring);
} break;
case OBJECT_PACKAGE:
case OBJECT_PACKAGE_BODY: {
objectname = NameListToString(names);
pgaudit_ddl_package(objectname, querystring);
} break;
case OBJECT_FOREIGN_SERVER: {
objectname = NameListToString(names);
pgaudit_ddl_serverforhardoop(objectname, querystring);
} break;
case OBJECT_DATA_SOURCE: {
objectname = NameListToString(names);
pgaudit_ddl_datasource(objectname, querystring);
} break;
case OBJECT_RLSPOLICY: {
objectname = strVal(lfirst(list_tail(names)));
pgaudit_ddl_rowlevelsecurity(objectname, querystring);
} break;
case OBJECT_TYPE: {
objectname = NameListToString(names);
pgaudit_ddl_type(objectname, querystring);
} break;
case OBJECT_TSDICTIONARY:
case OBJECT_TSCONFIGURATION: {
objectname = NameListToString(names);
pgaudit_ddl_textsearch(objectname, querystring);
} break;
case OBJECT_SEQUENCE:
case OBJECT_LARGE_SEQUENCE:
case OBJECT_SEQUENCE_GSC:
case OBJECT_LARGE_SEQUENCE_GSC: {
objectname = strVal(lfirst(list_tail(names)));
pgaudit_ddl_sequence(objectname, querystring);
} break;
case OBJECT_GLOBAL_SETTING:
case OBJECT_COLUMN_SETTING: {
pgaudit_ddl_full_encryption_key(querystring);
} break;
case OBJECT_DB4AI_MODEL: {
rel = makeRangeVarFromNameList(names);
objectname = rel->relname;
pgaudit_ddl_model(objectname, querystring);
} break;
case OBJECT_PUBLICATION:
objectname = NameListToString(names);
pgaudit_ddl_publication_subscription(objectname, querystring);
break;
case OBJECT_FDW:
objectname = NameListToString(names);
pgaudit_ddl_fdw(objectname, querystring);
break;
default:
break;
}
}
}
* Brief : pgaudit_audit_object(const char* objname,int ObjectType,const char* cmdtext)
* Description : Audit the operations of database objects
*/
static void pgaudit_audit_object(const char* objname, int ObjectType, const char* cmdtext)
{
Assert(cmdtext);
for (int i = 0; i < g_auditFuncMapNum; i++) {
if (g_auditFuncMap[i].objType == ObjectType) {
g_auditFuncMap[i].auditFunc(objname, cmdtext);
return;
}
}
}
* Brief : pgaudit_process_alter_owner(Node * node,const char* querystring)
* Description : process alter owner operation
*/
static void pgaudit_process_alter_owner(Node* node, const char* querystring)
{
char* objectname = NULL;
AlterOwnerStmt* alterownerstmt = (AlterOwnerStmt*)(node);
switch (alterownerstmt->objectType) {
case OBJECT_DATABASE:
case OBJECT_DATA_SOURCE:
case OBJECT_DIRECTORY:
case OBJECT_FDW:
case OBJECT_FOREIGN_SERVER:
case OBJECT_LANGUAGE:
case OBJECT_LARGEOBJECT:
case OBJECT_SCHEMA:
case OBJECT_TABLESPACE:
objectname = strVal(linitial(alterownerstmt->object));
break;
case OBJECT_COLLATION:
case OBJECT_CONVERSION:
case OBJECT_DOMAIN:
case OBJECT_FUNCTION:
case OBJECT_OPCLASS:
case OBJECT_OPERATOR:
case OBJECT_OPFAMILY:
case OBJECT_SYNONYM:
case OBJECT_TSDICTIONARY:
case OBJECT_TSCONFIGURATION:
case OBJECT_TYPE:
case OBJECT_PACKAGE:
case OBJECT_PUBLICATION:
case OBJECT_SUBSCRIPTION:
case OBJECT_TRIGGER:
objectname = NameListToString(alterownerstmt->object);
break;
default:
break;
}
pgaudit_audit_object(objectname, alterownerstmt->objectType, querystring);
}
* Brief : pgaudit_process_reindex(Node* node,const char* querystring)
* Description : process reinex operation
*/
static void pgaudit_process_reindex(Node* node, const char* querystring)
{
ReindexStmt* reindexstmt = (ReindexStmt*)(node);
switch (reindexstmt->kind) {
case OBJECT_INDEX:
case OBJECT_TABLE:
case OBJECT_INTERNAL:
pgaudit_audit_object(reindexstmt->relation->relname, reindexstmt->kind, querystring);
break;
case OBJECT_DATABASE:
pgaudit_audit_object(reindexstmt->name, reindexstmt->kind, querystring);
break;
default:
break;
}
}
* Brief : pgaudit_process_rename_object(Node* node,const char* querystring)
* Description : process the rename operation
*/
static void pgaudit_process_rename_object(Node* node, const char* querystring)
{
RenameStmt* stmt = (RenameStmt*)(node);
char* objectname = NULL;
switch (stmt->renameType) {
case OBJECT_DATABASE:
case OBJECT_ROLE:
case OBJECT_USER:
case OBJECT_SCHEMA:
case OBJECT_TABLESPACE:
case OBJECT_TRIGGER:
case OBJECT_RLSPOLICY:
case OBJECT_DATA_SOURCE:
objectname = stmt->subname;
break;
case OBJECT_EVENT_TRIGGER:
case OBJECT_FDW:
case OBJECT_FOREIGN_SERVER:
case OBJECT_FUNCTION:
case OBJECT_TYPE:
case OBJECT_TSDICTIONARY:
case OBJECT_TSCONFIGURATION:
case OBJECT_PUBLICATION:
case OBJECT_SUBSCRIPTION:
objectname = NameListToString(stmt->object);
break;
case OBJECT_TABLE:
case OBJECT_CONTQUERY:
case OBJECT_VIEW:
case OBJECT_MATVIEW:
case OBJECT_INDEX:
case OBJECT_FOREIGN_TABLE:
case OBJECT_STREAM:
if (stmt->renameTableflag && PointerIsValid(stmt->renameTargetList) &&
PointerIsValid(stmt->renameTargetList->head)) {
objectname = ((RenameCell*)stmt->renameTargetList->head->data.ptr_value)->original_name->relname;
} else {
objectname = stmt->relation->relname;
}
break;
default:
break;
}
pgaudit_audit_object(objectname, stmt->renameType, querystring);
}
* Brief : pgaudit_process_alter_object(Node* node,const char* querystring)
* Description : process alter object operation
*/
static void pgaudit_process_alter_object(Node* node, const char* querystring)
{
AlterObjectSchemaStmt* alterstmt = (AlterObjectSchemaStmt*)(node);
char* objectname = NULL;
switch (alterstmt->objectType) {
case OBJECT_TABLE:
case OBJECT_FOREIGN_TABLE:
case OBJECT_STREAM:
case OBJECT_CONTQUERY:
case OBJECT_VIEW:
objectname = alterstmt->relation->relname;
break;
case OBJECT_FUNCTION:
case OBJECT_TYPE:
case OBJECT_TSDICTIONARY:
case OBJECT_TSCONFIGURATION:
objectname = NameListToString(alterstmt->object);
break;
default:
break;
}
pgaudit_audit_object(objectname, alterstmt->objectType, querystring);
}
static char* pgaudit_get_function_name(List* funcnamelist)
{
char* objname = NULL;
switch (list_length(funcnamelist)) {
case 1:
objname = strVal(linitial(funcnamelist));
break;
case 2:
objname = strVal(lsecond(funcnamelist));
break;
case 3:
objname = strVal(lthird(funcnamelist));
break;
default:
break;
}
return objname;
}
* Brief : pgaudit_ProcessUtility(Node *parsetree,const char *queryString, ParamListInfo params,
bool isTopLevel,DestReceiver *dest, char *completionTag)
* Description : ProcessUtility hook
*/
static void pgaudit_ProcessUtility(processutility_context* processutility_cxt,
DestReceiver* dest,
#ifdef PGXC
bool sentToRemote,
#endif
char* completionTag,
ProcessUtilityContext context,
bool isCTAS)
{
char* object_name_pointer = NULL;
if (prev_ProcessUtility)
prev_ProcessUtility(processutility_cxt,
dest,
#ifdef PGXC
sentToRemote,
#endif
completionTag,
context,
isCTAS);
else
standard_ProcessUtility(processutility_cxt,
dest,
#ifdef PGXC
sentToRemote,
#endif
completionTag,
context,
isCTAS);
Node* parsetree = processutility_cxt->parse_tree;
const char* queryString = processutility_cxt->query_string;
switch (nodeTag(parsetree)) {
case T_CreateStmt: {
CreateStmt* createtablestmt = (CreateStmt*)(parsetree);
pgaudit_ddl_table(createtablestmt->relation->relname, queryString);
} break;
case T_LockStmt: {
LockStmt* locktablestmt = (LockStmt*)(parsetree);
ListCell* arg = NULL;
foreach (arg, locktablestmt->relations) {
RangeVar* rv = NULL;
List* rv_lockmode = NULL;
if (u_sess->attr.attr_sql.dolphin && locktablestmt->mode == NoLock){
rv_lockmode = (List*)lfirst(arg);
rv = (RangeVar*)linitial(rv_lockmode);
} else {
rv = (RangeVar*)lfirst(arg);
}
pgaudit_ddl_table(rv->relname, queryString);
}
} break;
case T_AlterTableStmt: {
AlterTableStmt* altertablestmt = (AlterTableStmt*)(parsetree);
if (OBJECT_IS_SEQUENCE(altertablestmt->relkind)) {
pgaudit_ddl_sequence(altertablestmt->relation->relname, queryString);
} else {
pgaudit_ddl_table(altertablestmt->relation->relname, queryString);
}
} break;
case T_CreateTableAsStmt: {
CreateTableAsStmt* createtablestmt = (CreateTableAsStmt*)(parsetree);
IntoClause* intoclause = createtablestmt->into;
pgaudit_ddl_table(intoclause->rel->relname, queryString);
} break;
case T_TruncateStmt: {
TruncateStmt* truncatestmt = (TruncateStmt*)(parsetree);
ListCell* arg = NULL;
foreach (arg, truncatestmt->relations) {
RangeVar* rv = (RangeVar*)lfirst(arg);
pgaudit_ddl_table(rv->relname, queryString);
}
} break;
case T_CreateForeignTableStmt: {
CreateStmt* createforeignstmt = (CreateStmt*)(parsetree);
pgaudit_ddl_table(createforeignstmt->relation->relname, queryString);
} break;
case T_CreateUserMappingStmt: {
CreateUserMappingStmt *createUserMappingStmt = (CreateUserMappingStmt*)parsetree;
pgaudit_ddl_user(createUserMappingStmt->username, queryString);
} break;
case T_AlterUserMappingStmt: {
AlterUserMappingStmt *alterUserMappingStmt = (AlterUserMappingStmt*)parsetree;
pgaudit_ddl_user(alterUserMappingStmt->username, queryString);
} break;
case T_DropUserMappingStmt: {
DropUserMappingStmt *dropUserMappingStmt = (DropUserMappingStmt*)parsetree;
pgaudit_ddl_user(dropUserMappingStmt->username, queryString);
} break;
case T_CreateRoleStmt: {
CreateRoleStmt* createrolestmt = (CreateRoleStmt*)(parsetree);
pgaudit_ddl_user(createrolestmt->role, queryString);
} break;
case T_AlterRoleStmt: {
AlterRoleStmt* alterrolestmt = (AlterRoleStmt*)(parsetree);
pgaudit_ddl_user(alterrolestmt->role, queryString);
} break;
case T_AlterRoleSetStmt: {
AlterRoleSetStmt* alterrolesetstmt = (AlterRoleSetStmt*)(parsetree);
pgaudit_ddl_user(alterrolesetstmt->role, queryString);
} break;
case T_DropRoleStmt: {
DropRoleStmt* droprolestmt = (DropRoleStmt*)(parsetree);
ListCell* arg = NULL;
foreach (arg, droprolestmt->roles) {
object_name_pointer = strVal(lfirst(arg));
pgaudit_ddl_user(object_name_pointer, queryString);
}
} break;
case T_DropOwnedStmt: {
DropOwnedStmt* dropownedstmt = (DropOwnedStmt*)(parsetree);
ListCell* arg = NULL;
foreach (arg, dropownedstmt->roles) {
object_name_pointer = strVal(lfirst(arg));
pgaudit_ddl_user(object_name_pointer, queryString);
}
} break;
case T_ReassignOwnedStmt: {
ReassignOwnedStmt* reassignownedstmt = (ReassignOwnedStmt*)(parsetree);
ListCell* arg = NULL;
foreach (arg, reassignownedstmt->roles) {
object_name_pointer = strVal(lfirst(arg));
pgaudit_ddl_user(object_name_pointer, queryString);
}
} break;
case T_IndexStmt: {
IndexStmt* indexstmt = (IndexStmt*)parsetree;
pgaudit_ddl_index(indexstmt->idxname, queryString);
} break;
case T_CreateSchemaStmt: {
CreateSchemaStmt* schemastmt = (CreateSchemaStmt*)(parsetree);
pgaudit_ddl_schema(schemastmt->schemaname, queryString);
} break;
case T_CreateTableSpaceStmt: {
CreateTableSpaceStmt* createtabelspacestmt = (CreateTableSpaceStmt*)(parsetree);
pgaudit_ddl_tablespace(createtabelspacestmt->tablespacename, queryString);
} break;
case T_AlterTableSpaceOptionsStmt: {
AlterTableSpaceOptionsStmt* altertabelspaceoptionsstmt =
(AlterTableSpaceOptionsStmt*)(parsetree);
pgaudit_ddl_tablespace(altertabelspaceoptionsstmt->tablespacename, queryString);
} break;
case T_DropTableSpaceStmt: {
DropTableSpaceStmt* droptabelspacestmt = (DropTableSpaceStmt*)(parsetree);
pgaudit_ddl_tablespace(droptabelspacestmt->tablespacename, queryString);
} break;
case T_ViewStmt: {
ViewStmt* viewstmt = (ViewStmt*)(parsetree);
pgaudit_ddl_view(viewstmt->view->relname, queryString);
} break;
case T_CreateEventStmt: {
CreateEventStmt* eventstmt = (CreateEventStmt*)(parsetree);
pgaudit_ddl_event(eventstmt->event_name->relname, queryString);
} break;
case T_AlterEventStmt: {
AlterEventStmt* eventstmt = (AlterEventStmt*)(parsetree);
pgaudit_ddl_event(eventstmt->event_name->relname, queryString);
} break;
case T_DropEventStmt: {
DropEventStmt* eventstmt = (DropEventStmt*)(parsetree);
pgaudit_ddl_event(eventstmt->event_name->relname, queryString);
} break;
case T_CreateEnumStmt: {
CreateEnumStmt* enumstmt = (CreateEnumStmt*)(parsetree);
object_name_pointer = NameListToString(enumstmt->typname);
pgaudit_ddl_type(object_name_pointer, queryString);
} break;
case T_AlterEnumStmt: {
AlterEnumStmt* alterenumstmt = (AlterEnumStmt*)(parsetree);
object_name_pointer = NameListToString(alterenumstmt->typname);
pgaudit_ddl_type(object_name_pointer, queryString);
} break;
case T_CompositeTypeStmt: {
CompositeTypeStmt* stmt = (CompositeTypeStmt*)(parsetree);
pgaudit_ddl_type(stmt->typevar->relname, queryString);
} break;
case T_CreateSetStmt: {
CreateSetStmt* setstmt = (CreateSetStmt*)parsetree;
object_name_pointer = NameListToString(setstmt->typname->names);
pgaudit_ddl_type(object_name_pointer, queryString);
} break;
case T_CreateFunctionStmt: {
CreateFunctionStmt* createfunctionstmt = (CreateFunctionStmt*)(parsetree);
object_name_pointer = pgaudit_get_function_name(createfunctionstmt->funcname);
pgaudit_ddl_function(object_name_pointer, queryString);
} break;
case T_CreatePackageStmt:
case T_CreatePackageBodyStmt: {
pgaudit_ddl_package(object_name_pointer, queryString);
} break;
case T_AlterFunctionStmt: {
AlterFunctionStmt* alterfunctionstmt = (AlterFunctionStmt*)(parsetree);
object_name_pointer = NameListToString(alterfunctionstmt->func->funcname);
pgaudit_ddl_function(object_name_pointer, queryString);
} break;
case T_CreatedbStmt: {
CreatedbStmt* createdbstmt = (CreatedbStmt*)(parsetree);
pgaudit_ddl_database(createdbstmt->dbname, queryString);
} break;
case T_AlterDatabaseStmt: {
AlterDatabaseStmt* alterdatabasestmt = (AlterDatabaseStmt*)(parsetree);
pgaudit_ddl_database(alterdatabasestmt->dbname, queryString);
} break;
case T_AlterDatabaseSetStmt: {
AlterDatabaseSetStmt* alterdatabasesetstmt = (AlterDatabaseSetStmt*)(parsetree);
pgaudit_ddl_database(alterdatabasesetstmt->dbname, queryString);
} break;
case T_DropdbStmt: {
DropdbStmt* dropdbstmt = (DropdbStmt*)(parsetree);
pgaudit_ddl_database(dropdbstmt->dbname, queryString);
} break;
case T_CreateTrigStmt: {
CreateTrigStmt* createstmt = (CreateTrigStmt*)(parsetree);
pgaudit_ddl_trigger(createstmt->trigname, queryString);
} break;
case T_AlterTriggerStmt: {
AlterTriggerStmt *alterstmt = (AlterTriggerStmt *)(parsetree);
pgaudit_ddl_trigger(alterstmt->trigname, queryString);
} break;
case T_AlterDefaultPrivilegesStmt: {
AlterDefaultPrivilegesStmt* alterprivilegesstmt = (AlterDefaultPrivilegesStmt*)(parsetree);
pgaudit_grant_or_revoke_role(alterprivilegesstmt->action->is_grant, NULL, queryString);
} break;
case T_GrantStmt: {
GrantStmt* grantstmt = (GrantStmt*)(parsetree);
pgaudit_process_grant_or_revoke_roles(grantstmt->grantees, grantstmt->is_grant, queryString);
} break;
case T_GrantRoleStmt: {
GrantRoleStmt* grantrolestmt = (GrantRoleStmt*)(parsetree);
pgaudit_process_grant_or_revoke_roles(grantrolestmt->grantee_roles, grantrolestmt->is_grant, queryString);
} break;
case T_GrantDbStmt: {
GrantDbStmt* grantdbstmt = (GrantDbStmt*)(parsetree);
pgaudit_process_grant_or_revoke_roles(grantdbstmt->grantees, grantdbstmt->is_grant, queryString);
} break;
case T_DropStmt:
pgaudit_process_drop_objects(parsetree, queryString);
break;
case T_RenameStmt:
pgaudit_process_rename_object(parsetree, queryString);
break;
case T_AlterObjectSchemaStmt:
pgaudit_process_alter_object(parsetree, queryString);
break;
case T_AlterOwnerStmt:
pgaudit_process_alter_owner(parsetree, queryString);
break;
case T_ReindexStmt:
pgaudit_process_reindex(parsetree, queryString);
break;
case T_CreateResourcePoolStmt: {
CreateResourcePoolStmt* createresourcepoolStmt = (CreateResourcePoolStmt*)(parsetree);
pgaudit_ddl_resourcepool(createresourcepoolStmt->pool_name, queryString);
} break;
case T_AlterResourcePoolStmt: {
AlterResourcePoolStmt* alterresourcepoolStmt = (AlterResourcePoolStmt*)(parsetree);
pgaudit_ddl_resourcepool(alterresourcepoolStmt->pool_name, queryString);
} break;
case T_DropResourcePoolStmt: {
DropResourcePoolStmt* dropresourcepoolStmt = (DropResourcePoolStmt*)(parsetree);
pgaudit_ddl_resourcepool(dropresourcepoolStmt->pool_name, queryString);
} break;
case T_AlterGlobalConfigStmt: {
AlterGlobalConfigStmt* alterglobalconfigStmt = (AlterGlobalConfigStmt*)(parsetree);
pgaudit_alter_globalconfig(alterglobalconfigStmt, queryString);
} break;
case T_DropGlobalConfigStmt: {
DropGlobalConfigStmt* dropglobalconfigStmt = (DropGlobalConfigStmt*)(parsetree);
pgaudit_drop_globalconfig(dropglobalconfigStmt, queryString);
} break;
case T_CreateWorkloadGroupStmt: {
CreateWorkloadGroupStmt* createworkloadgroupstmt = (CreateWorkloadGroupStmt*)(parsetree);
pgaudit_ddl_workload(createworkloadgroupstmt->group_name, queryString);
} break;
case T_AlterWorkloadGroupStmt: {
AlterWorkloadGroupStmt* alterworkloadgroupstmt = (AlterWorkloadGroupStmt*)(parsetree);
pgaudit_ddl_workload(alterworkloadgroupstmt->group_name, queryString);
} break;
case T_DropWorkloadGroupStmt: {
DropWorkloadGroupStmt* dropworkloadgroupstmt = (DropWorkloadGroupStmt*)(parsetree);
pgaudit_ddl_workload(dropworkloadgroupstmt->group_name, queryString);
} break;
case T_CreateAppWorkloadGroupMappingStmt: {
CreateAppWorkloadGroupMappingStmt* createappworkloadgroupmappingstmt =
(CreateAppWorkloadGroupMappingStmt*)(parsetree);
pgaudit_ddl_workload(createappworkloadgroupmappingstmt->app_name, queryString);
} break;
case T_AlterAppWorkloadGroupMappingStmt: {
AlterAppWorkloadGroupMappingStmt* alterappworkloadgroupmappingstmt =
(AlterAppWorkloadGroupMappingStmt*)(parsetree);
pgaudit_ddl_workload(alterappworkloadgroupmappingstmt->app_name, queryString);
} break;
case T_DropAppWorkloadGroupMappingStmt: {
DropAppWorkloadGroupMappingStmt* dropappworkloadgroupmappingstmt =
(DropAppWorkloadGroupMappingStmt*)(parsetree);
pgaudit_ddl_workload(dropappworkloadgroupmappingstmt->app_name, queryString);
} break;
case T_CreateForeignServerStmt: {
CreateForeignServerStmt* createforeignserverstmt = (CreateForeignServerStmt*)(parsetree);
pgaudit_ddl_serverforhardoop(createforeignserverstmt->servername, queryString);
} break;
case T_AlterForeignServerStmt: {
AlterForeignServerStmt* alterforeignserverstmt = (AlterForeignServerStmt*)(parsetree);
pgaudit_ddl_serverforhardoop(alterforeignserverstmt->servername, queryString);
} break;
case T_VariableSetStmt: {
VariableSetStmt* variablesetstmt = (VariableSetStmt*)(parsetree);
pgaudit_process_set_parameter(variablesetstmt->name, queryString);
} break;
case T_VariableMultiSetStmt: {
pgaudit_process_set_parameter("set stmt", queryString);
} break;
#ifndef ENABLE_MULTIPLE_NODES
case T_AlterSystemStmt: {
AlterSystemStmt* altersystemstmt = (AlterSystemStmt*)(parsetree);
pgaudit_process_set_parameter(altersystemstmt->setstmt->name, queryString);
} break;
#endif
case T_CreateDataSourceStmt: {
CreateDataSourceStmt* createdatasourcestmt = (CreateDataSourceStmt*)(parsetree);
pgaudit_ddl_datasource(createdatasourcestmt->srcname, queryString);
} break;
case T_AlterDataSourceStmt: {
AlterDataSourceStmt* alterdatasourcestmt = (AlterDataSourceStmt*)(parsetree);
pgaudit_ddl_datasource(alterdatasourcestmt->srcname, queryString);
} break;
case T_CreateGroupStmt: {
CreateGroupStmt* createnodegroupstmt = (CreateGroupStmt*)(parsetree);
pgaudit_ddl_nodegroup(createnodegroupstmt->group_name, queryString);
} break;
case T_AlterGroupStmt: {
AlterGroupStmt* alternodegroupstmt = (AlterGroupStmt*)(parsetree);
pgaudit_ddl_nodegroup(alternodegroupstmt->group_name, queryString);
} break;
case T_DropGroupStmt: {
DropGroupStmt* dropnodegroupstmt = (DropGroupStmt*)(parsetree);
pgaudit_ddl_nodegroup(dropnodegroupstmt->group_name, queryString);
} break;
case T_CreateDirectoryStmt: {
CreateDirectoryStmt* createdirectorystmt = (CreateDirectoryStmt*)(parsetree);
pgaudit_ddl_directory(createdirectorystmt->directoryname, queryString);
break;
}
case T_DropDirectoryStmt: {
DropDirectoryStmt* dropdirectorystmt = (DropDirectoryStmt*)(parsetree);
pgaudit_ddl_directory(dropdirectorystmt->directoryname, queryString);
break;
}
case T_CreateRlsPolicyStmt: {
CreateRlsPolicyStmt* createRlsPolicyStmt = (CreateRlsPolicyStmt*)(parsetree);
pgaudit_ddl_rowlevelsecurity(createRlsPolicyStmt->policyName, queryString);
} break;
case T_AlterRlsPolicyStmt: {
AlterRlsPolicyStmt* alterRlsPolicyStmt = (AlterRlsPolicyStmt*)(parsetree);
pgaudit_ddl_rowlevelsecurity(alterRlsPolicyStmt->policyName, queryString);
} break;
case T_CreateSynonymStmt: {
CreateSynonymStmt* createSynonymStmt = (CreateSynonymStmt*)(parsetree);
char* synName = NameListToString(createSynonymStmt->synName);
pgaudit_ddl_synonym(synName, queryString);
} break;
case T_DropSynonymStmt: {
DropSynonymStmt* dropSynonymStmt = (DropSynonymStmt*)(parsetree);
char* synName = NameListToString(dropSynonymStmt->synName);
pgaudit_ddl_synonym(synName, queryString);
} break;
case T_DefineStmt: {
DefineStmt* stmt = (DefineStmt*)parsetree;
object_name_pointer = NameListToString(stmt->defnames);
switch (stmt->kind) {
case OBJECT_TSDICTIONARY:
case OBJECT_TSCONFIGURATION:
pgaudit_ddl_textsearch(object_name_pointer, queryString);
break;
case OBJECT_TYPE:
pgaudit_ddl_type(object_name_pointer, queryString);
break;
default:
break;
}
} break;
case T_AlterTSDictionaryStmt: {
AlterTSDictionaryStmt* stmt = (AlterTSDictionaryStmt*)parsetree;
object_name_pointer = NameListToString(stmt->dictname);
pgaudit_ddl_textsearch(object_name_pointer, queryString);
} break;
case T_AlterTSConfigurationStmt: {
AlterTSConfigurationStmt* stmt = (AlterTSConfigurationStmt*)parsetree;
object_name_pointer = NameListToString(stmt->cfgname);
pgaudit_ddl_textsearch(object_name_pointer, queryString);
} break;
case T_CreateSeqStmt: {
CreateSeqStmt* stmt = (CreateSeqStmt*)parsetree;
pgaudit_ddl_sequence(stmt->sequence->relname, queryString);
} break;
case T_AlterSeqStmt: {
AlterSeqStmt* stmt = (AlterSeqStmt*)parsetree;
pgaudit_ddl_sequence(stmt->sequence->relname, queryString);
} break;
case T_CreateWeakPasswordDictionaryStmt: {
pgaudit_ddl_weak_password(queryString);
} break;
case T_DropWeakPasswordDictionaryStmt: {
pgaudit_ddl_weak_password(queryString);
} break;
case T_CreateClientLogicGlobal:
case T_CreateClientLogicColumn: {
pgaudit_ddl_full_encryption_key(queryString);
} break;
case T_PurgeStmt: {
PurgeStmt *stmt = (PurgeStmt *)parsetree;
if (stmt->purtype == PURGE_TABLE) {
pgaudit_ddl_table(stmt->purobj->relname, queryString);
} else if (stmt->purtype == PURGE_INDEX) {
pgaudit_ddl_index(stmt->purobj->relname, queryString);
} else {
char *dbname = get_database_name(u_sess->proc_cxt.MyDatabaseId);
pgaudit_ddl_database(dbname, queryString);
}
} break;
case T_TimeCapsuleStmt: {
TimeCapsuleStmt *stmt = (TimeCapsuleStmt *)parsetree;
pgaudit_ddl_table(stmt->relation->relname, queryString);
} break;
case T_CreateModelStmt: {
CreateModelStmt* createModelStmt = (CreateModelStmt*)(parsetree);
pgaudit_ddl_model(createModelStmt->model, queryString);
} break;
case T_CreatePublicationStmt: {
CreatePublicationStmt *stmt = (CreatePublicationStmt*)parsetree;
pgaudit_ddl_publication_subscription(stmt->pubname, queryString);
} break;
case T_AlterPublicationStmt: {
AlterPublicationStmt *stmt = (AlterPublicationStmt*)parsetree;
pgaudit_ddl_publication_subscription(stmt->pubname, queryString);
} break;
case T_CreateSubscriptionStmt: {
CreateSubscriptionStmt *stmt = (CreateSubscriptionStmt*)parsetree;
pgaudit_ddl_publication_subscription(stmt->subname, queryString);
} break;
case T_AlterSubscriptionStmt: {
AlterSubscriptionStmt *stmt = (AlterSubscriptionStmt*)parsetree;
pgaudit_ddl_publication_subscription(stmt->subname, queryString);
} break;
case T_DropSubscriptionStmt: {
DropSubscriptionStmt *stmt = (DropSubscriptionStmt*)parsetree;
pgaudit_ddl_publication_subscription(stmt->subname, queryString);
} break;
case T_CreateFdwStmt: {
CreateFdwStmt *stmt = (CreateFdwStmt*)parsetree;
pgaudit_ddl_fdw(stmt->fdwname, queryString);
} break;
case T_AlterFdwStmt: {
AlterFdwStmt *stmt = (AlterFdwStmt*)parsetree;
pgaudit_ddl_fdw(stmt->fdwname, queryString);
} break;
case T_NotifyStmt: {
NotifyStmt *stmt = (NotifyStmt*)parsetree;
PGAuditNotify(stmt->conditionname);
} break;
case T_ListenStmt: {
ListenStmt *stmt = (ListenStmt*)parsetree;
PGAuditListen(stmt->conditionname);
} break;
case T_UnlistenStmt: {
UnlistenStmt *stmt = (UnlistenStmt*)parsetree;
PGAuditUnlisten(stmt->conditionname);
} break;
default:
break;
}
}
* Brief : pgaudit_process_grant_or_revoke_roles(List* grantee_name_list,bool isgrant,const char*
* querystring) Description : process grant or revoke roles operation
*/
static void pgaudit_process_grant_or_revoke_roles(List* grantee_name_list, bool isgrant, const char* querystring)
{
ListCell* lc = NULL;
char* object_name = NULL;
foreach (lc, grantee_name_list) {
PrivGrantee* rte = (PrivGrantee*)lfirst(lc);
object_name = rte->rolname;
pgaudit_grant_or_revoke_role(isgrant, object_name, querystring);
}
}
char* pgaudit_get_relation_name(List* relation_name_list)
{
ListCell* lc = NULL;
char* object_name = NULL;
foreach (lc, relation_name_list) {
RangeTblEntry* rte = (RangeTblEntry*)lfirst(lc);
if (rte->relname != NULL) {
object_name = rte->relname;
break;
} else if (rte->eref != NULL && rte->eref->aliasname != NULL) {
object_name = rte->eref->aliasname;
break;
}
}
return object_name;
}
* Brief : pgaudit_ExecutorEnd()
* Description : ExecutorEnd hook: store results if needed
*/
static void pgaudit_ExecutorEnd(QueryDesc* queryDesc)
{
char* object_name = NULL;
if (t_thrd.audit.Audit_delete) {
pgaudit_delete_files(NULL, queryDesc->sourceText);
t_thrd.audit.Audit_delete = false;
}
switch (queryDesc->operation) {
case CMD_INSERT:
case CMD_DELETE:
case CMD_UPDATE:
case CMD_MERGE:
object_name = pgaudit_get_relation_name(queryDesc->estate->es_range_table);
pgaudit_dml_table(object_name, queryDesc->sourceText);
break;
case CMD_SELECT:
object_name = pgaudit_get_relation_name(queryDesc->estate->es_range_table);
pgaudit_dml_table_select(object_name, queryDesc->sourceText);
break;
default:
break;
}
if (prev_ExecutorEnd)
(prev_ExecutorEnd)(queryDesc);
else
standard_ExecutorEnd(queryDesc);
}
void light_pgaudit_ExecutorEnd(Query* query)
{
char* object_name = NULL;
bool is_full_audit_user = audit_check_full_audit_user();
switch (query->commandType) {
case CMD_INSERT:
case CMD_DELETE:
case CMD_UPDATE:
if (u_sess->attr.attr_security.Audit_DML != 0 || is_full_audit_user) {
object_name = pgaudit_get_relation_name(query->rtable);
pgaudit_dml_table(object_name, query->sql_statement);
}
break;
case CMD_SELECT:
if (u_sess->attr.attr_security.Audit_DML_SELECT != 0 || is_full_audit_user) {
object_name = pgaudit_get_relation_name(query->rtable);
pgaudit_dml_table_select(object_name, query->sql_statement);
}
break;
default:
break;
}
}
* Brief : check if src_str includes target_str
* Description : split src_str by delimiter and search for target_str
*/
bool audit_search_str(char* src_str, char* target_str)
{
bool is_found = false;
char* ptok = NULL;
char* sub_str = NULL;
char* src_str_tmp = NULL;
char* src_str_trim = NULL;
src_str_tmp = pstrdup(src_str);
if (src_str_tmp == NULL) {
pfree(src_str_tmp);
return is_found;
}
sub_str = (char*)strchr(src_str, ',');
if (sub_str == NULL) {
src_str_trim = trim(src_str_tmp);
if (strcmp(target_str, src_str_trim) == 0) {
pfree(src_str_tmp);
return true;
}
} else {
sub_str = strtok_s(src_str_tmp, ",", &ptok);
while (sub_str != NULL) {
src_str_trim = trim(sub_str);
if (strcmp(target_str, src_str_trim) == 0) {
is_found = true;
break;
}
sub_str = strtok_s(NULL, ",", &ptok);
}
}
pfree(src_str_tmp);
return is_found;
}
* Brief : check if the client_info is in the blackist, consists of clients
* whoes audit records should not be sent to audit pipe
* Description : search No_Audit_Client for current clientconn_info, if exists, skip audit_report
*/
bool audit_check_client_blacklist(char* client_info)
{
bool is_blacklist = false;
if (u_sess->attr.attr_security.no_audit_client == NULL || strlen(u_sess->attr.attr_security.no_audit_client) == 0) {
return is_blacklist;
}
is_blacklist = audit_search_str(u_sess->attr.attr_security.no_audit_client, client_info);
return is_blacklist;
}
* Brief : check if current user is under comprehensive audit
* Description : search Full_Audit_Users for current username, if exists, open all the audit options
*/
bool audit_check_full_audit_user()
{
bool is_full_audit = false;
char* username = NULL;
if (u_sess->attr.attr_security.full_audit_users[0] == '\0' || u_sess->proc_cxt.MyProcPort == NULL) {
return is_full_audit;
}
if (u_sess->misc_cxt.CurrentUserName != NULL) {
username = (char*)u_sess->misc_cxt.CurrentUserName;
} else {
username = u_sess->proc_cxt.MyProcPort->user_name;
}
if (username == NULL) {
return is_full_audit;
}
is_full_audit = audit_search_str(u_sess->attr.attr_security.full_audit_users, username);
return is_full_audit;
}
* Brief : check if the system function should be audited
* Description : search list g_audit_system_funcs for func_name, if exists, do audit
*/
static bool audit_is_system_func(char *func_name)
{
bool is_audit = false;
int i;
for (i = 0; g_audit_system_funcs[i] != NULL; i++) {
if (strcmp((const char*)func_name, g_audit_system_funcs[i]) == 0) {
is_audit = true;
}
}
if (!is_audit) {
List* search_path = fetch_search_path(false);
char* nspname = NULL;
if (search_path == NIL) {
list_free_ext(search_path);
return is_audit;
}
nspname = get_namespace_name(linitial_oid(search_path));
func_name = quote_qualified_identifier(nspname, func_name);
list_free_ext(search_path);
for (i = 0; g_audit_system_funcs[i] != NULL; i++) {
if (strcmp((const char*)func_name, g_audit_system_funcs[i]) == 0) {
is_audit = true;
}
}
}
return is_audit;
}
* Brief : check if the system function includes crypt information
* Description : search list g_audit_crypt_funcs for func_name
*/
static bool audit_is_crypt_func(char *func_name)
{
bool is_crypt = false;
for (int i = 0; g_audit_crypt_funcs[i] != NULL; i++) {
if (strcmp((const char*)func_name, g_audit_crypt_funcs[i]) == 0) {
is_crypt = true;
}
}
return is_crypt;
}
* Brief : generate audit record of system function in white list, and do audit_report
* Description : extract funtion name, oid and parameters of system function
*/
void audit_system_function(FunctionCallInfo fcinfo, const AuditResult result)
{
Oid fn_oid = fcinfo->flinfo->fn_oid;
char* fn_signature = format_procedure(fn_oid);
char* func_name = NULL;
char* next_token = NULL;
const char* token = "(";
func_name = strtok_s((char*)format_procedure(fn_oid), token, &next_token);
if (func_name == NULL) {
return;
}
if (fn_oid >= FirstBootstrapObjectId || !audit_is_system_func(func_name)) {
return;
}
bool is_crypt = audit_is_crypt_func(func_name);
char details[PGAUDIT_MAXLENGTH];
errno_t rcs = EOK;
if (is_crypt) {
rcs = snprintf_s(details, PGAUDIT_MAXLENGTH, PGAUDIT_MAXLENGTH - 1,
"Execute system function(oid = %u). args = %s",
fn_oid, CRYPT_FUNC_ARG);
} else {
char* fn_args = audit_get_func_args(fcinfo);
rcs = snprintf_s(details, PGAUDIT_MAXLENGTH, PGAUDIT_MAXLENGTH - 1,
"Execute system function(oid = %u). args = %s",
fn_oid, fn_args);
pfree(fn_args);
}
securec_check_ss(rcs, "\0", "\0");
audit_report(AUDIT_SYSTEM_FUNCTION_EXEC, result, fn_signature, details);
}
* Brief : generate the detail_info by extract arguments of system function
* Description : traverse fcinfo to get arguments value and form string
*/
static char* audit_get_func_args(FunctionCallInfo fcinfo)
{
char* arg;
StringInfoData buf;
initStringInfo(&buf);
appendStringInfo(&buf, "%s(", "");
for (int i = 0; i < fcinfo->nargs; i++) {
if (i > 0) {
appendStringInfoString(&buf, ",");
}
arg = audit_get_value_bytype(fcinfo, i);
appendStringInfo(&buf, "%s", arg);
}
appendStringInfoString(&buf, ")");
char* result = buf.data;
return result;
}
* Brief : extract args from the fcinfo
* Description : get value from fcinfo by different arguments type and sequence number
*/
char* audit_get_value_bytype(FunctionCallInfo fcinfo, int n_arg)
{
char* value = (char*)palloc(BUF_LENGTH);
errno_t nRet = EOK;
if (PG_ARGISNULL(n_arg)) {
nRet = strncpy_s(value, BUF_LENGTH, SYSTEM_FUNC_DEFAULT_VALUE, BUF_LENGTH - 1);
securec_check(nRet, "\0", "\0");
return value;
}
Oid typeOid = fcinfo->argTypes[n_arg];
switch (typeOid) {
case TEXTARRAYOID: {
int option_nitems;
ArrayType* option_array = PG_GETARG_ARRAYTYPE_P(n_arg);
pfree(value);
value = audit_get_text_array_value(option_array, &option_nitems);
break;
}
case BOOLOID: {
bool arg = PG_GETARG_BOOL(n_arg);
nRet = strncpy_s(value, BUF_LENGTH, (arg) ? "true" : "false", BUF_LENGTH - 1);
securec_check(nRet, "\0", "\0");
break;
}
case BYTEAOID: {
bytea* v = PG_GETARG_BYTEA_P(n_arg);
pfree(value);
value = VARDATA_ANY(v);
break;
}
case CHAROID: {
char v = PG_GETARG_CHAR(n_arg);
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%c", v);
securec_check_ss(nRet, "\0", "\0");
break;
}
case NAMEOID: {
pfree(value);
value = NameStr(*PG_GETARG_NAME(n_arg));
break;
}
case INT8OID: {
int64 v = PG_GETARG_INT64(n_arg);
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%lld", v);
securec_check_ss(nRet, "\0", "\0");
break;
}
case INT2OID: {
int2 v = PG_GETARG_INT16(n_arg);
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%d", v);
securec_check_ss(nRet, "\0", "\0");
break;
}
case INT4OID: {
int4 v = PG_GETARG_INT32(n_arg);
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%ld", v);
securec_check_ss(nRet, "\0", "\0");
break;
}
case REGPROCOID: {
RegProcedure v = PG_GETARG_OID(n_arg);
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%u", v);
securec_check_ss(nRet, "\0", "\0");
break;
}
case TEXTOID: {
pfree(value);
value = text_to_cstring(PG_GETARG_TEXT_P(n_arg));
break;
}
case OIDOID: {
Oid v = PG_GETARG_OID(n_arg);
if (v) {
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%u", v);
securec_check_ss(nRet, "\0", "\0");
}
break;
}
case TIDOID: {
ThreadId v = (unsigned long)PG_GETARG_INT64(n_arg);
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%lld", v);
securec_check_ss(nRet, "\0", "\0");
break;
}
case XIDOID: {
TransactionId v = PG_GETARG_TRANSACTIONID(n_arg);
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%llu", v);
securec_check_ss(nRet, "\0", "\0");
break;
}
case CIDOID: {
CommandId v = PG_GETARG_COMMANDID(n_arg);
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%lu", v);
securec_check_ss(nRet, "\0", "\0");
break;
}
case SHORTXIDOID: {
ShortTransactionId v = PG_GETARG_SHORTTRANSACTIONID(n_arg);
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%lu", v);
securec_check_ss(nRet, "\0", "\0");
break;
}
case FLOAT4OID: {
float4 v = PG_GETARG_FLOAT4(n_arg);
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%.4f", v);
securec_check_ss(nRet, "\0", "\0");
break;
}
case FLOAT8OID: {
float8 v = PG_GETARG_FLOAT8(n_arg);
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%.8f", v);
securec_check_ss(nRet, "\0", "\0");
break;
}
case ABSTIMEOID: {
AbsoluteTime v = PG_GETARG_ABSOLUTETIME(n_arg);
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%ld", v);
securec_check_ss(nRet, "\0", "\0");
break;
}
case RELTIMEOID: {
RelativeTime v = PG_GETARG_RELATIVETIME(n_arg);
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%ld", v);
securec_check_ss(nRet, "\0", "\0");
break;
}
case INTERVALOID: {
Interval* v = PG_GETARG_INTERVAL_P(n_arg);
TmToChar tmtc;
struct pg_tm* tm = NULL;
ZERO_tmtc(&tmtc);
tm = tmtcTm(&tmtc);
if (interval2tm(*v, tm, &tmtcFsec(&tmtc)) != 0) {
nRet = strncpy_s(value, BUF_LENGTH, SYSTEM_FUNC_DEFAULT_VALUE, BUF_LENGTH - 1);
} else {
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1,
"%d year %d mon %d day %02d:%02d:%02d", tm->tm_year,
tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
}
securec_check_ss(nRet, "\0", "\0");
break;
}
case TINTERVALOID: {
TimeInterval v = PG_GETARG_TIMEINTERVAL(n_arg);
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%d", v->data);
securec_check_ss(nRet, "\0", "\0");
break;
}
case CASHOID: {
Cash v = PG_GETARG_CASH(n_arg);
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%lld", v);
securec_check_ss(nRet, "\0", "\0");
break;
}
case INETOID:case CIDROID: {
inet* v = PG_GETARG_INET_PP(n_arg);
pfree(value);
value = (char*)VARDATA_ANY(v);
break;
}
case BPCHAROID: {
BpChar* v = PG_GETARG_BPCHAR_PP(n_arg);
pfree(value);
value = VARDATA_ANY(v);
break;
}
case DATEOID: {
DateADT v = PG_GETARG_DATEADT(n_arg);
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%ld", v);
securec_check_ss(nRet, "\0", "\0");
break;
}
case TIMEOID: {
TimeADT v = PG_GETARG_TIMEADT(n_arg);
#ifdef HAVE_INT64_TIMESTAMP
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%lld", v);
#else
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%lf", v);
#endif
securec_check_ss(nRet, "\0", "\0");
break;
}
case TIMESTAMPOID: {
Timestamp v = PG_GETARG_TIMESTAMP(n_arg);
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%lld", v);
securec_check_ss(nRet, "\0", "\0");
break;
}
case TIMESTAMPTZOID: {
TimestampTz v = PG_GETARG_TIMESTAMPTZ(n_arg);
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%lld", v);
securec_check_ss(nRet, "\0", "\0");
break;
}
case CSTRINGOID:
case NVARCHAR2OID:
case VARCHAROID:
case RAWOID:
case SMALLDATETIMEOID: {
pfree(value);
value = PG_GETARG_CSTRING(n_arg);
break;
}
case TIMETZOID: {
TimeTzADT* v = PG_GETARG_TIMETZADT_P(n_arg);
#ifdef HAVE_INT64_TIMESTAMP
int64 time = v->time;
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "time %ld zone %lu", time, v->zone);
#else
float8 time = v->time;
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "time %f zone %lu", time, v->zone);
#endif
securec_check_ss(nRet, "\0", "\0");
break;
}
case INT1OID: {
int1 v = PG_GETARG_INT8(n_arg);
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%s", v);
securec_check_ss(nRet, "\0", "\0");
break;
}
case UUIDOID: {
pg_uuid_t* v_uuid = PG_GETARG_UUID_P(n_arg);
char* v = (char*)v_uuid->data;
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%s", v);
securec_check_ss(nRet, "\0", "\0");
break;
}
case ANYENUMOID: {
uint32 v = (uint32)PG_GETARG_OID(n_arg);
nRet = snprintf_s(value, BUF_LENGTH, BUF_LENGTH - 1, "%lu", v);
securec_check_ss(nRet, "\0", "\0");
break;
}
case INT2VECTOROID: {
int2vector *key = (int2vector *)PG_GETARG_POINTER(n_arg);
pfree(value);
value = (char *)key->values;
break;
}
case OIDVECTOROID: {
oidvector *key = (oidvector *)PG_GETARG_POINTER(n_arg);
pfree(value);
value = (char *)key->values;
break;
}
default: {
ereport(LOG, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("UNKOWN PARAMETER TYPE FOR SYSTEM FUNCTION AUDIT.")));
nRet = strncpy_s(value, BUF_LENGTH, SYSTEM_FUNC_DEFAULT_VALUE, BUF_LENGTH - 1);
securec_check(nRet, "\0", "\0");
break;
}
}
return value;
}
* Brief : get values of optional arguments in form of text array
* Description : deconstruct a text[] into C-strings
*/
static char* audit_get_text_array_value(ArrayType* array, int* numitems)
{
int ndim = ARR_NDIM(array);
int* dims = ARR_DIMS(array);
int nitems;
int16 typlen;
bool typbyval = false;
char typalign;
char* ptr = NULL;
bits8* bitmap = NULL;
uint32 bitmask;
int i;
char* val = NULL;
StringInfoData buf;
initStringInfo(&buf);
Assert(ARR_ELEMTYPE(array) == TEXTOID);
*numitems = nitems = ArrayGetNItems(ndim, dims);
get_typlenbyvalalign(ARR_ELEMTYPE(array), &typlen, &typbyval, &typalign);
ptr = ARR_DATA_PTR(array);
bitmap = ARR_NULLBITMAP(array);
bitmask = 1;
for (i = 0; i < nitems; i++) {
if (i > 0)
appendStringInfo(&buf, "%s", ",");
if (bitmap && (*bitmap & bitmask) == 0) {
val = NULL;
} else {
val = TextDatumGetCString(PointerGetDatum(ptr));
ptr = att_addlength_pointer(ptr, typlen, ptr);
ptr = (char*)att_align_nominal(ptr, typalign);
}
appendStringInfo(&buf, "%s", val);
if (bitmap) {
bitmask <<= 1;
if (bitmask == 0x100) {
bitmap++;
bitmask = 1;
}
}
}
char* values = buf.data;
return values;
}