/* Copyright (C) 2003 Frédéric Giudicelli (contact_nos@yahoo.com). All rights reserved. This product includes cryptographic software written by Eric Young (eay@cryptsoft.com) This program is released under the GPL with the additional exemption that compiling, linking, and/or using OpenSSL is allowed. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // EntityLog.cpp: implementation of the EntityLog class. // ////////////////////////////////////////////////////////////////////// #include #include "EntityLog.h" #include "svintl.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// EntityLog::EntityLog(const SQL_Connection * DbConn, const PKI_CERT * EntityCert) { DB_Conn = NULL; try { DB_Conn = DbConn->Clone(); } catch(ExceptionNewPKI e) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); throw ExceptionNewPKI(); } if(!DB_Conn) { NEWPKIerr(PKI_ERROR_TXT, ERROR_MALLOC); throw ExceptionNewPKI(); } if(EntityCert) m_EntityCert = *EntityCert; // We load the HashCorrelation LogsHash.SetCert(m_EntityCert); mString CurrentHash; SQL sql(DB_Conn); long NumRows; if(!sql.Execute(LOG_SELECT_HASH)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); throw ExceptionNewPKI(); } if(!sql.NumRows(&NumRows)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); throw ExceptionNewPKI(); } if(NumRows) { if(!sql.Value(0, "hash", CurrentHash)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); throw ExceptionNewPKI(); } if(CurrentHash.size()) { if(!LogsHash.SetCurrentHash(CurrentHash)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); throw ExceptionNewPKI(); } } } } EntityLog::~EntityLog() { if(DB_Conn) delete DB_Conn; } void EntityLog::LogMessage(LOG_MESSAGE_STATUS Status, LOG_MESSAGE_TYPE Message, unsigned long UserId, const char * UserDN, unsigned long ObjectId, const char * ObjectName, const char * Error) const { size_t i; LogEntry log; LOG_ENTRY * lLog; mString object; mString user; mString error; time_t tim; const EVP_PKEY * privateKey; mString req; mString signature; if(!DB_Conn) return; if(m_EntityCert.GetPrivateKey()) privateKey = m_EntityCert.GetPrivateKey().GetRsaKey(); else privateKey = NULL; if(ObjectId != LOG_NO_OBJECTID) object = ObjectId; else object = ObjectName; if(UserDN) user = UserDN; else user = UserId; error = Error; time_gmt(&tim); //Check if the entry correspond to an audit AuditLock.LockRead(); if(m_Audit.size() && m_OnAudit) { for(i=0; i 0) { if(log.get_sig().load_Datas(lLog->sig)) { log.get_sig().to_PEM(signature); } } ASN1_item_free((ASN1_VALUE*)lLog, LogEntry::get_ASN1_ITEM()); } else { if(lLog) ASN1_item_free((ASN1_VALUE*)lLog, LogEntry::get_ASN1_ITEM()); } } SQL sql(DB_Conn); object = sql.FormatString(object); user = sql.FormatString(user); error = sql.FormatString(error); if(req.sprintf(LOG_INSERT, (int)log.get_body().get_logStatus(), (int)log.get_body().get_logType(), user.c_str(), object.c_str(), error.c_str(), log.get_body().get_logDate(), signature.c_str()) <= 0) { return; } // We know insert it in the data base if(!sql.Execute(req)) { return; } HashLock.EnterCS(); if(signature.size()) { // Compute the new hash for logs if(!LogsHash.AddEntry(sql.GetLastID(), (char*)log.get_sig().get_signature()->data, log.get_sig().get_signature()->length)) { //We don't want the hash to be broken we remove the log entry req.sprintf(LOG_DELETE, sql.GetLastID()); sql.Execute(req); } else { //Calculate the new hash if(!LogsHash.GetHash(object)) { //We don't want the hash to be broken we remove the log entry req.sprintf(LOG_DELETE, sql.GetLastID()); sql.Execute(req); } else { //Insert the new hash in db req.sprintf(LOG_INSERT_HASH, object.c_str()); sql.Execute(req); } } } HashLock.LeaveCS(); } bool EntityLog::GetLogs(mVector< LogEntry > & Logs, const AdminReqEnumLogs & Filters) const { SQL sql(DB_Conn); mString req; long NumRows; long i; LogEntry Value; mString where; int Offset; int Max; if(!DB_Conn) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_PARAM); return false; } where = FormatFiltersSQL(Filters); Offset=Filters.get_index(); Max=Filters.get_max(); if(req.sprintf(LOG_SELECT, where.c_str(), Offset, Max) <= 0) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_DATAS); return false; } //We execute the request if(!sql.Execute(req)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!sql.NumRows(&NumRows)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } for(i=0; i", Filters.get_dateFrom()); } if( Filters.get_dateTo() ) { ADD_FILTER("log_date", "<", Filters.get_dateTo()); } if( Filters.get_status() ) { ADD_FILTER("log_status", "=", Filters.get_status()); } if( Filters.get_user().size() ) { tt_user = "%%"; tt_user += Filters.get_user(); tt_user += "%%"; ADD_FILTER("LOWER(user)", "LIKE", tt_user); } if(!entries_count) return ""; else return where; } void EntityLog::SetAuditCalllBack(PROC_ON_AUDIT_CALLBACK *OnAudit, void *Param) { AuditLock.LockWrite(); m_OnAudit = OnAudit; m_Param = Param; AuditLock.UnlockWrite(); } bool EntityLog::SetAudit(const mVector & Audit) { AuditLock.LockWrite(); m_Audit = Audit; AuditLock.UnlockWrite(); return true; } bool EntityLog::CheckLogsIntegrity() const { SQL sql(DB_Conn); mString req; long NumRows; unsigned Offset = 0; int i; LogEntry Value; HashCorrelation LogsCorrelation; LOG_ENTRY * lValue; LogsCorrelation.SetCert(m_EntityCert); do { if(req.sprintf(LOG_GET_LOGS_LIST, Offset*200, 200) <= 0) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_DATAS); return false; } if(!sql.Execute(req)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!sql.NumRows(&NumRows)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(NumRows) { for(i=0; idata, Value.get_sig().get_signature()->length)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } } } Offset++; } while(NumRows); //We now compare the two logs hash to make sure they're identical if(LogsCorrelation == LogsHash) return true; NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_ENTRY_SIGNATURE); ERR_set_error_data(_sv("Unknown"), ERR_TXT_STRING); return false; } bool EntityLog::SqlToLOG_ENTRY(SQL &sql, long i, LogEntry & Value) const { mString str_enum; if(!sql.Value(i, "log_id", str_enum)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } Value.set_logId(str_enum.c_ulng()); if(!sql.Value(i, "log_status", str_enum)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } Value.get_body().set_logStatus(str_enum.c_ulng()); if(!sql.Value(i, "log_type", str_enum)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } Value.get_body().set_logType(str_enum.c_ulng()); if(!sql.Value(i, "user", Value.get_body().get_user())) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!sql.Value(i, "object_name", Value.get_body().get_objectName())) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!sql.Value(i, "error", Value.get_body().get_error())) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!sql.Value(i, "log_date", str_enum)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } Value.get_body().set_logDate(str_enum.c_ulng()); if(!sql.Value(i, "signature", str_enum)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!Value.get_sig().from_PEM(str_enum)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_DATAS); return false; } return true; } bool EntityLog::GetLogsCount(unsigned long & Count, const AdminReqEnumLogs & Filters) const { SQL sql(DB_Conn); mString req; mString where; if(!DB_Conn) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_PARAM); return false; } where = FormatFiltersSQL(Filters); if(req.sprintf(LOG_SELECT_COUNT, where.c_str()) <= 0) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_DATAS); return false; } //We execute the request if(!sql.Execute(req)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!sql.Value(0, "ctr", req)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } Count = req.c_ulng(); return true; }