/* 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 */ // Entity.h: interface for the Entity class. // ////////////////////////////////////////////////////////////////////// #ifndef ENTITY_H #define ENTITY_H #include #include #include #include "Conf.h" #include #include #include #include #include #include "SQL/SQL_Conn.h" #include "SQL/SQL.h" #include #include "AuthModule.h" #include "EntityLog.h" #include #include #include #include "UserHandle.h" #include "X509_ACL_Validator.h" #include "SmtpClient.h" #include "Entity_ASN1.h" #include #include "AsynchJobs.h" #include "NewPKIStore.h" #include #include #include using namespace std; /*! This class represents an Entity's conf */ class LocalEntityConf : public NewPKISignCryptObject { public: /*! \brief This is the constructor. * \exception ExceptionNewPKI An error occured. */ LocalEntityConf():NewPKISignCryptObject(){} /*! \brief This is the destructor. */ virtual ~LocalEntityConf(){} /*! \brief This function returns the conf. * \return The conf. */ virtual const EntityConf & get_conf() const =0; /*! \brief This function returns the conf. * \return The conf. */ virtual EntityConf & get_conf()=0; /*! \brief This function sets the conf. * \param c_conf [IN] The conf. * \return true on success, false on failure. */ virtual bool set_conf(const EntityConf & c_conf)=0; /*! \brief This function sets the PKI's CAs info. * \param c_cas [IN] The CAs' info. * \return true on success, false on failure. */ virtual bool set_cas(const InternalPkiCa & c_cas)=0; /*! \brief This function returns the CA's info. * \return The CA's info. */ virtual const InternalPkiCa & get_cas() const =0; /*! \brief This function returns the CA's info. * \return The CA's info. */ virtual InternalPkiCa & get_cas()=0; }; #define ENTITY_CONSTRUCTOR_PARAMETERS const Config & Conf, const mString & EntityName, ENGINE * e, AuthModule * authModule, int Type #define ENTITY_CONSTRUCTOR_PARAM_PASSTHRU Conf, EntityName, e, authModule, Type /*! This class represents a generic Entity */ class Entity : public AsynchJobsEvent { public: /*! \brief This is the constructor. * \exception ExceptionNewPKI An error occured. */ Entity(ENTITY_CONSTRUCTOR_PARAMETERS, LocalEntityConf * PersonnalConf, NewPKIStore * EntityStore); /*! \brief This is the destructor. */ virtual ~Entity(); /*! \brief This function returns the type of the entity. * \return The type of the entity. */ int GetType(); /*! \brief This function will lock until there are no more clients using the class. */ void WaitForNoClients(); /*! \brief This function must be called before calling any public function of this class. */ void ClientEnter(); /*! \brief This function must be called after calling any public function of this class. */ void ClientLeave(); /*! \brief This function destroys the entity. * \return true on success, false on failure. */ bool Destroy(); /*! \brief This function returns the name of the entity. * \return The name of the entity. */ mString & GetName(); /*! \brief Verifies if an entity doesn't already exists. * \param Exists [IN] true when exists, false when doesn't exist. * \return true on success, false on failure. */ bool EntityExists(bool & Exists); /*! \brief This function allows to get the certificate of the entity. * \param cEntityCert [OUT] The certificate. */ virtual void GetEntityCertificate(PKI_CERT & cEntityCert); /*! \brief This function creates the entity. * \param Params [IN] The creation parameters. * \param response [OUT] The creation response. * \return true on success, false on failure. */ virtual bool Create(const EntityCreationDatas & Params, AdminResponseBody & response)=0; /*! \brief This function intializes the entity. * \param init_datas [IN] The intialization parameters. * \return true on success, false on failure. */ virtual bool Init(const EntitySignatureResp & init_datas)=0; /*! \brief This function loads the entity. * \return true on success, false on failure. */ virtual bool Load()=0; /*! \brief This function upgrades the entity. * \param Version [IN] The current version. * \return true on success, false on failure. */ virtual bool Upgrade(const char * Version)=0; /*! \brief This function signs an response using the entity's certificate. * \param response [IN/OUT] The response. * \return true on success, false on failure. */ bool SignResponse(AdminResponse & response); /*! \brief This function is called when a new request is received. * \param response [OUT] The response. * \param ClientCert [IN] The end user certificate. * \param AdminRequest [IN] The request. * \return true on success, false on failure. */ virtual bool ParseAdminCommand(AdminResponseBody & response, const PKI_CERT & ClientCert, const AdminRequest & AdminRequest)=0; /*! \brief This function is called when the connection to a user is closed. */ void OnUserLogout(); /*! \brief This function checks if the entity has been fully intialized. * \return true when initialized, false when not initialized. */ bool IsFullyInit(); bool OnNewConf(const EntityConfCrypted & newConf); protected: #define COMMAND_PARAMETERS AdminResponseBody & response, int command, const PKI_CERT & UserCert, const AdminRequestBody & body, UserHandle & hUser #define DECLARE_COMMAND_PARSER(clname) \ typedef bool (clname::*FUNCTION_COMMAND_##clname)(AdminResponseBody & response, int command, const PKI_CERT & UserCert, const AdminRequestBody & body, UserHandle & hUser); \ class internal_##clname \ { \ public: \ internal_##clname(): \ m_ObjectName() \ { \ m_LogType = (LOG_MESSAGE_TYPE)0; \ m_ObjectName = ""; \ m_ObjectId = LOG_NO_OBJECTID; \ m_CommandId = 0; \ m_Function = NULL; \ } \ ~internal_##clname() \ { \ } \ LOG_MESSAGE_TYPE m_LogType; \ mString m_ObjectName; \ unsigned long m_ObjectId; \ int m_CommandId; \ FUNCTION_COMMAND_##clname m_Function; \ }; #define PARSER_COMMAND_BEGIN(clname, resp, userid, streq, usercert, clparam, execcmd, thisptr, cldstlogstype) \ internal_##clname CommandEntry; \ const AdminRequestBody & body = streq.get_body(); \ const PKI_CERT & m_UserCert = (usercert); \ AdminResponseBody & internal_resp = (resp); \ unsigned long cl_user_id = (userid); \ UserHandle & cccchUser = (clparam); \ bool func_ret; \ mString err; \ ERR_clear_error(); \ mVector & dstLogsType = cldstlogstype; \ clname * cl_me_this = (clname*)(thisptr); \ bool clExecCmd = (execcmd); \ size_t numLogs = dstLogsType.size(); \ #define PARSER_ADD_LOG_ENTRY(logtype) \ if(!numLogs && logtype) \ { \ dstLogsType.push_back(logtype); \ } #define PARSER_COMMAND_ENTRY_LOG(cmdid, cmdfunc, logtype, objectname, objectid) \ if( clExecCmd && body.get_type() == cmdid ) \ { \ CommandEntry.m_LogType = logtype; \ CommandEntry.m_ObjectName = objectname; \ CommandEntry.m_ObjectId = objectid; \ CommandEntry.m_CommandId = cmdid; \ CommandEntry.m_Function = & cmdfunc; \ } \ PARSER_ADD_LOG_ENTRY(logtype) #define PARSER_COMMAND_ENTRY(cmdid, cmdfunc) \ PARSER_COMMAND_ENTRY_LOG(cmdid, cmdfunc, (LOG_MESSAGE_TYPE)0, "", 0) #define PARSER_COMMAND_END(clname) \ if(!clExecCmd) return true; \ if(!CommandEntry.m_Function) \ { \ NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_PKI_COMMAND); \ cl_me_this->ERR_to_ADMIN_RESPONSE(internal_resp); \ return false; \ } \ if(CommandEntry.m_LogType) \ { \ if(!CommandEntry.m_ObjectName.size() && CommandEntry.m_ObjectId == LOG_NO_OBJECTID) \ { \ NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_PKI_COMMAND); \ cl_me_this->ERR_to_ADMIN_RESPONSE(internal_resp); \ return false; \ } \ cl_me_this->m_Logging->LogMessage(LOG_STATUS_TYPE_REQUEST, CommandEntry.m_LogType, cl_user_id, ((m_UserCert)?m_UserCert.GetStringName():NULL), CommandEntry.m_ObjectId, CommandEntry.m_ObjectName.c_str()); \ } \ func_ret = (cl_me_this->*((FUNCTION_COMMAND_##clname) (CommandEntry.m_Function)))( internal_resp, CommandEntry.m_CommandId, m_UserCert, body, cccchUser); \ if(CommandEntry.m_LogType) \ { \ if(!func_ret) \ { \ ERR_to_mstring(err); \ cl_me_this->m_Logging->LogMessage(LOG_STATUS_TYPE_FAILURE, CommandEntry.m_LogType, cl_user_id, ((m_UserCert)?m_UserCert.GetStringName():NULL), CommandEntry.m_ObjectId, CommandEntry.m_ObjectName.c_str(), err.c_str()); \ } \ else \ cl_me_this->m_Logging->LogMessage(LOG_STATUS_TYPE_SUCCESS, CommandEntry.m_LogType, cl_user_id, ((m_UserCert)?m_UserCert.GetStringName():NULL), CommandEntry.m_ObjectId, CommandEntry.m_ObjectName.c_str()); \ } \ if(!func_ret) \ { \ cl_me_this->ERR_to_ADMIN_RESPONSE(internal_resp); \ return false; \ } \ else \ return true; bool Common_Create(const GenPrivateKey & genkey, const char ** InitialCreates); bool Common_Init(const PKI_CERT & Cert, const EntitySignatureResp & init_datas); bool Common_Load(); bool WritePersonnalConf(); void ERR_to_ADMIN_RESPONSE(AdminResponseBody & response); void ResourceUnlock(const mString & ResourceName); bool ResourceLock(const mString & ResourceName); bool ResourceOwnerIsMe(const mString & ResourceName); UserHandle & GetUserHandle(); bool GetMyACL(COMMAND_PARAMETERS); bool AdminSendMail(COMMAND_PARAMETERS); bool CheckLogsIntegrity(COMMAND_PARAMETERS); bool EnumLogs(COMMAND_PARAMETERS); bool GetLogsCount(COMMAND_PARAMETERS); bool GetLogsType(COMMAND_PARAMETERS); bool Private_GetMyACL(COMMAND_PARAMETERS); bool UserLogin(COMMAND_PARAMETERS); X509_ACL_Validator AclValidator; ENGINE * m_Engine; mString m_EntityName; mString m_EntityMail; SQL_Connection * m_DbConn; Config m_Conf; AuthModule * m_AuthModule; EntityLog * m_Logging; PKI_CERT m_EntityCert; PKI_RSA m_EntityKey; ReadersWriter ConfAccessLock; mVector LogsType; AsynchJobs m_Jobs; private: #define SELECT_DATABASE "SHOW DATABASES;" #define SELECT_DATABASE_RES "Database" #define COMMON_CREATE_1 "create table logs (log_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, log_status INT NOT NULL, log_type INT NOT NULL, user TEXT NOT NULL, object_name TEXT NOT NULL, error TEXT NOT NULL, log_date INT UNSIGNED NOT NULL, signature BLOB NOT NULL, INDEX (log_id));" #define COMMON_CREATE_2 "create table logs_hash (hash_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, hash TEXT NOT NULL);" #define COMMON_CREATE_3 "create table entity_cert (id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, entity_cert TEXT NOT NULL, entity_key TEXT NOT NULL);" #define COMMON_CREATE_4 "create table conf (id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, conf LONGBLOB NOT NULL);" #define ENTITY_INSERT_CONF "REPLACE INTO conf (id, conf) VALUES (1, '%s');" #define ENTITY_GET_CONF "SELECT * FROM conf;" #define ENTITY_SET_CERT "REPLACE INTO entity_cert (id, entity_cert, entity_key) VALUES (1, '%s', '%s');" #define ENTITY_GET_CERT "SELECT * FROM entity_cert;" bool fullInit; virtual bool LoginUser(UserHandle & hUser, int & UserType)=0; virtual void LogoutUser(const UserHandle & hUser)=0; virtual bool PrepareConfToWrite()=0; virtual bool ParseNewConf()=0; bool InitDatas(); bool ExtractMyConf(const EntityConfCrypted & c_conf); NewPKIStore * m_EntityStore; LocalEntityConf * m_PersonnalConf; bool isStopped; CriticalSection ClientsReadLock; //!< The clients ctr MUTEX unsigned long entered_client; //!< The number of active client void ResourcesClearUser(); map ResourcesList; CriticalSection ResourcesListLock; static void OnAudit(void *Param, LOG_MESSAGE_STATUS Status, LOG_MESSAGE_TYPE Message, const mString & User, const mString & Object, time_t log_timegmt, const mString & Error); map AuthenticatedUsers; CriticalSection AuthUsersLock; int m_Type; }; #endif