diff --git a/include/audit_handler.h b/include/audit_handler.h index 813bc9e..05188ca 100755 --- a/include/audit_handler.h +++ b/include/audit_handler.h @@ -79,14 +79,35 @@ public: class ThdSesData { public: + + //enum indicating from where the object list came from + enum ObjectIterType {OBJ_NONE, OBJ_DB, OBJ_QUERY_CACHE, OBJ_TABLE_LIST}; ThdSesData(THD *pTHD); THD* getTHD () { return m_pThd;} const char * getCmdName () { return m_CmdName; } const char * getUserName () { return m_UserName; } + /** + * Start fetching objects. Return true if there are objects available. + */ + bool startGetObjects(); + /** + * Get next object. Return true if populated. False if there isn't an object available. + * Will point the passed pointers to point to db, name and type. + * obj_type is optional and may be null. + */ + bool getNextObject(const char ** db_name, const char ** obj_name, const char ** obj_type); private: THD *m_pThd; const char *m_CmdName; const char *m_UserName; + enum ObjectIterType m_objIterType; + //pointer for iterating tables + TABLE_LIST * m_tables; + //indicator if we are at the first table + bool m_firstTable; + //used for query cache iter + QueryTableInf * m_tableInf; + int m_index; protected: ThdSesData (const ThdSesData& ); ThdSesData &operator =(const ThdSesData& ); diff --git a/src/audit_handler.cc b/src/audit_handler.cc index c3df90e..89017c1 100755 --- a/src/audit_handler.cc +++ b/src/audit_handler.cc @@ -414,71 +414,25 @@ ssize_t Audit_json_formatter::event_format(ThdSesData* pThdData, IWriter * write yajl_add_string_val(gen, "host", sctx->host); yajl_add_string_val(gen, "ip", sctx->ip); const char *cmd = pThdData->getCmdName(); - //only print tables if lex is not null and it is not a quit command - LEX * pLex = Audit_formatter::thd_lex(pThdData->getTHD()); - QueryTableInf *pQuery_cache_table_list = getQueryCacheTableList1 (pThdData->getTHD()); - if (pLex && command != COM_QUIT && pLex->query_tables == NULL && pQuery_cache_table_list) - { - yajl_add_string_val(gen, "cmd", "select"); - yajl_add_string(gen, "objects"); - yajl_gen_array_open(gen); - for (int i=0;inum_of_elem && i < MAX_NUM_QUERY_TABLE_ELEM && pQuery_cache_table_list->num_of_elem >=0;i++) - { - yajl_gen_map_open(gen); - yajl_add_obj (gen, pQuery_cache_table_list->db[i],pQuery_cache_table_list->object_type[i],pQuery_cache_table_list->table_name[i] ); - yajl_gen_map_close(gen); - - } - yajl_gen_array_close(gen); - - } - else - { - - yajl_add_string_val(gen, "cmd", cmd); - } - - - if (strcmp (cmd,"Init DB") ==0 || strcmp (cmd, "SHOW TABLES")== 0 || strcmp (cmd, "SHOW TABLE")==0) - { - if ((pThdData->getTHD())->db !=0) - { - yajl_add_string(gen, "objects"); - yajl_gen_array_open(gen); - yajl_add_obj (gen,(pThdData->getTHD())->db,"database", NULL); - yajl_gen_array_close(gen); - } - } - - - if (pLex && command != COM_QUIT && pLex->query_tables) + yajl_add_string_val(gen, "cmd", cmd); + //get objects + if(pThdData->startGetObjects()) { yajl_add_string(gen, "objects"); yajl_gen_array_open(gen); - TABLE_LIST * table = pLex->query_tables; - bool isFirstElementInView = true; - - while (table) + const char * db_name = NULL; + const char * obj_name = NULL; + const char * obj_type = NULL; + while(pThdData->getNextObject(&db_name, &obj_name, &obj_type)) { yajl_gen_map_open(gen); - if (isFirstElementInView && strstr (cmd,"_view")!=NULL ) - { - yajl_add_obj (gen,table->get_db_name(), "view",table->get_table_name()); - isFirstElementInView = false; - } - else - { - yajl_add_obj (gen,table->get_db_name(), retrive_object_type(table),table->get_table_name()); - } + yajl_add_obj (gen, db_name, obj_type, obj_name ); yajl_gen_map_close(gen); - table = table->next_global; } yajl_gen_array_close(gen); } - size_t qlen = 0; - const char * query = thd_query_str(pThdData->getTHD(), &qlen); if (query && qlen > 0) { @@ -527,9 +481,116 @@ ssize_t Audit_json_formatter::event_format(ThdSesData* pThdData, IWriter * write - -ThdSesData::ThdSesData (THD *pTHD) : m_pThd (pTHD), m_CmdName(NULL), m_UserName(NULL) +ThdSesData::ThdSesData (THD *pTHD) : + m_pThd (pTHD), m_CmdName(NULL), m_UserName(NULL), + m_objIterType(OBJ_NONE), m_tables(NULL), m_firstTable(true), + m_tableInf(NULL), m_index(0) { m_CmdName = retrieve_command (m_pThd); m_UserName = retrieve_user (m_pThd); } + +bool ThdSesData::startGetObjects() +{ + //reset vars as this may be called multiple times + m_objIterType = OBJ_NONE; + m_tables = NULL; + m_firstTable = true; + m_index = 0; + m_tableInf = Audit_formatter::getQueryCacheTableList1(getTHD()); + int command = Audit_formatter::thd_inst_command(getTHD()); + LEX * pLex = Audit_formatter::thd_lex(getTHD()); + //query cache case + if(pLex && command == COM_QUERY && m_tableInf && m_tableInf->num_of_elem > 0) + { + m_objIterType = OBJ_QUERY_CACHE; + return true; + } + const char *cmd = getCmdName(); + //commands which have single database object + if (strcmp (cmd,"Init DB") ==0 || strcmp (cmd, "SHOW TABLES")== 0 || strcmp (cmd, "SHOW TABLE")==0) + { + if(getTHD()->db) + { + m_objIterType = OBJ_DB; + return true; + } + return false; + } + //only return query tabls if command is COM_QUERY + //TODO: check if other commands can also generate query tables such as "show fields" + if (pLex && command == COM_QUERY && pLex->query_tables) + { + m_tables = pLex->query_tables; + m_objIterType = OBJ_TABLE_LIST; + return true; + } + //no objects + return false; +} + +bool ThdSesData::getNextObject(const char ** db_name, const char ** obj_name, const char ** obj_type) +{ + switch(m_objIterType) + { + case OBJ_DB: + { + if(m_firstTable) + { + *db_name = getTHD()->db; + *obj_name = NULL; + if(obj_type) + { + *obj_type = "DATABASE"; + } + m_firstTable = false; + return true; + } + return false; + } + case OBJ_QUERY_CACHE: + { + if(m_index < m_tableInf->num_of_elem && + m_index< MAX_NUM_QUERY_TABLE_ELEM) + { + *db_name = m_tableInf->db[m_index]; + *obj_name = m_tableInf->table_name[m_index]; + if(obj_type) + { + *obj_type = m_tableInf->object_type[m_index]; + } + m_index++; + return true; + } + return false; + } + case OBJ_TABLE_LIST: + { + if(m_tables) + { + *db_name = m_tables->get_db_name(); + *obj_name = m_tables->get_table_name(); + if(obj_type) + { + //object is a view if it view command (alter_view, drop_view ..) + //and first object or view field is populated + if((m_firstTable && strstr(getCmdName(), "_view") != NULL) || + m_tables->view) + { + *obj_type = "VIEW"; + m_firstTable = false; + } + else + { + *obj_type = "TABLE"; + } + } + m_tables = m_tables->next_global; + return true; + } + return false; + } + default : + return false; + } +} diff --git a/src/audit_plugin.cc b/src/audit_plugin.cc index d60370a..57e1691 100755 --- a/src/audit_plugin.cc +++ b/src/audit_plugin.cc @@ -680,35 +680,22 @@ static void audit(ThdSesData *pThdData) } } if (num_record_objs > 0) { - LEX *pLex = Audit_formatter::thd_lex(pThdData->getTHD()); - TABLE_LIST * table = pLex->query_tables; - //when statement is returned from query cache, objects will be included in pQueryTableInf - QueryTableInf * pQueryTableInf = (QueryTableInf*)THDVAR(pThdData->getTHD(), query_cache_table_list); - int matched = 0; - if(strcmp(pThdData->getCmdName(),"Quit") == 0 || (!table && (!pQueryTableInf || pQueryTableInf->num_of_elem <= 0))) //empty list of objects + bool matched = false; + if(pThdData->startGetObjects()) { - matched = record_empty_objs_set; - } - else - { - if(pQueryTableInf) //query cache case + const char * db_name = NULL; + const char * obj_name = NULL; + while(!matched && pThdData->getNextObject(&db_name, &obj_name, NULL)) { - for (int i=0; i < pQueryTableInf->num_of_elem && i < MAX_NUM_QUERY_TABLE_ELEM && !matched ; i++) - { - matched = check_db_obj(pQueryTableInf->db[i], pQueryTableInf->table_name[i]); - } - } - else - { - while (table && !matched) - { - matched = check_db_obj(table->get_db_name(), table->get_table_name()); - table = table->next_global; - } - } + matched = check_db_obj(db_name, obj_name); + } } + else //no objects + { + matched = record_empty_objs_set; + } if (!matched) { - return; + return; } } if (pThdPrintedList && pThdPrintedList->cur_index < MAX_NUM_QUEUE_ELEM) @@ -1327,6 +1314,11 @@ const char * retrieve_command (THD * thd) { command = COM_END; } + //check if from query cache. If so set to select and return + if(THDVAR(thd, query_cache_table_list) != 0) + { + return "select"; + } const int sql_command = thd_sql_command(thd); if (sql_command >=0 && sql_command <= (MAX_COM_STATUS_VARS_RECORDS -1) ) { @@ -1337,9 +1329,9 @@ const char * retrieve_command (THD * thd) cmd = command_name[command].str; } Security_context * sctx = Audit_formatter::thd_inst_main_security_ctx(thd); - if (strcmp (cmd, "Connect") ==0 && (sctx->priv_user == NULL || *sctx->priv_user == 0x0)) + if (strcmp (cmd, "Connect") ==0 && ((sctx->user && strcmp(sctx->user, "event_scheduler") != 0) && (sctx->priv_user == NULL || *sctx->priv_user == 0x0))) { - cmd = "Failed Login"; + cmd = "Failed Login"; } return cmd; }