/* 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 */ // AsynchJobs.h: interface for the AsynchJobs class. // ////////////////////////////////////////////////////////////////////// #ifndef ASYNCHJOBS_H #define ASYNCHJOBS_H #include #include "EntityLog.h" #include #include "SmtpClient.h" #include #include "X509_ACL_Validator.h" #include "MailInfo.h" #include "NewPKIStore.h" #include "AsynchJobs_ASN1.h" class NewPKIStore; class StackRequest; /*! This class is the declaration of an event handler for asynch jobs */ class AsynchJobsEvent { public: /*! \brief Event triggered when a new conf has been seeked from a repository. * \param newConf [IN] The new conf. * \return true on success, false on failure. */ virtual bool OnNewConf(const EntityConfCrypted & newConf)=0; /*! \brief Event triggered when new request has been seeked from a repository. The event handler must validate the sender, to make sure the sender is allowed to request on us. * \param Request [IN] The request. * \param Requester [IN] The requester. * \param SenderName [OUT] The name of the entity. * \return true when the requester is allowed, false the requester is not allowed. */ virtual bool Responder_ValidateRequest(const NewpkiRequest & Request, const X509_PUBKEY * Requester, mString & SenderName)=0; /*! \brief Event triggered when a new request is ready to be processed by the responder. Requests are treated asynchronously. * \param Request [IN] The request. * \param SenderName [IN] The name of the sender, previously returned by Responder_ValidateRequester. * \param Response [OUT] The response. * \return true on success, false on failure. */ virtual bool Responder_TreatRequest(const NewpkiRequest & Request, const mString & SenderName, NewpkiResponse & Response)=0; /*! \brief Event triggered when new response has been seeked from a repository. Responses are treated synchronously. * \param transactionID [IN] The transaction ID of the new response. * \param sender [IN] The response sender. * \param Response [IN] The new response. * \return true on success, false on failure. */ virtual bool Requester_OnNewResponse(const Asn1OctetString & transactionID, const X509_PUBKEY * sender, const NewpkiResponse & Response)=0; }; #ifndef ASYNCH_JOBS_INTERVAL #define ASYNCH_JOBS_INTERVAL 60 //!< The time to wait after a job is done, to restart it #endif #ifndef MAILS_DB_RELOAD #define MAILS_DB_RELOAD 1800 //!< The time to wait before reloading all the mails from the DB #endif /*! This class holds the jobs that need to be done asynchronously */ class AsynchJobs { public: /*! \brief This is the constructor. */ AsynchJobs(); /*! \brief This is the destructor. */ virtual ~AsynchJobs(); /*! \brief This function stops all the asynchron jobs. */ void StopAll(); /*! \brief This function creates the tables needed to work. * \param DbConn [IN] A SQL connection. * \return true on success, false on failure. */ bool CreateTables(SQL_Connection * DbConn); /*! \brief This function sets the SQL connection. * \param DbConn [IN] A SQL connection. * \return true on success, false on failure. */ bool SetDbConn(SQL_Connection * DbConn); /*! \brief This function starts the configuration push job. * \param PushToAllRep [IN] When a new conf is declared, should it be sent to all known repositories? * \return true on success, false on failure. */ bool StartConfPush(bool PushToAllRep); /*! \brief This function stops the configuration push job. */ void StopConfPush(); /*! \brief This function starts the mailer job. * \return true on success, false on failure. */ bool StartMailer(); /*! \brief This function stops the mailer job. */ void StopMailer(); /*! \brief This function starts the configuration retrieval job. * \return true on success, false on failure. */ bool StartConfSync(); /*! \brief This function stops the configuration retrieval job. */ void StopConfSync(); /*! \brief This function sets the name of the entity using this class. * \param EntityName [IN] The name of the entity. */ void SetEntityName(const mString & EntityName); /*! \brief This function sets the certificate of the entity using this class. * \param cert [IN] The certificate of the entity. */ void SetEntityCert(const PKI_CERT & cert); /*! \brief This function sets the list of parents' certificate. * \param EntityParentCerts [IN] The list. * \return true on success, false on failure. */ bool SetEntityParentsCert(const mVector & EntityParentCerts); /*! \brief This function sets the instance that should receive the events. * \param event [IN] The event instance. */ void SetEventHandler(AsynchJobsEvent * event); /*! \brief This function sets the store. * \param store [IN] The store. */ void SetStore(NewPKIStore * store); /*! \brief This function sets the logging class. * \param log [IN] The logging class. */ void SetLogger(EntityLog * log); /*! \brief This function sets the mailer's info. * \param MailFrom [IN] The mail from. * \param conf [IN] The server configuration. * \return true on success, false on failure. */ bool SetMailerInfo(mString MailFrom, const EmailConf & conf); /*! \brief This function sets the list of admin mails. * \param Admins [IN] The list. * \return true on success, false on failure. */ bool SetAdminMails(const mVector & Admins); /*! \brief This function sets the list of repositories. * \param Repositories [IN] The list. * \return true on success, false on failure. */ bool SetRepositories(const mVector & Repositories); /*! \brief This function sets the validator. * \param AclValidator [IN] The validator. */ void SetX509_ACL_Validator(const X509_ACL_Validator * AclValidator); /*! \brief Checks if the mailer is up and running. * \return true on success, false on failure. */ bool MailerIsUp(); /*! \brief This function returns the mailer. * \return The mailer. */ const SmtpClient & GetMailer() const; /*! \brief This function is called to declare a new PKI conf, it will sent it to the repositories. * \param PkiConf [IN] The PKI conf. * \return true on success, false on failure. */ bool SetPkiConf(const ExportedPkiConf & PkiConf); /*! \brief This function is used to send a inter-entity-request, it will sent it to the repositories. * \param priv_attr [IN] A private value used by children. * \param Request [IN] The request. * \param Recipient [IN] The recipient for the request. * \return true on success, false on failure. */ bool InsertRequest(unsigned long priv_attr, const NewpkiRequest & Request, const X509_PUBKEY * Recipient) const; /*! \brief This function is used to send an email. * \param Author [IN] The author. * \param Mail [IN] The email. * \param AdminMail [IN] Is it an admin mail? * \return true on success, false on failure. */ bool SendMail(const mString & Author, const MailInfo & Mail, bool AdminMail) const; /*! \brief This function is used to connect to a Repository. * \param currRep [IN] The repository info. * \param ClientPki [IN] The instance of PkiClient to use. * \param TimeOut [IN] TimeOut>0: the connection timeout. * \param err [OUT] The error. * \return true on success, false on failure. */ bool ConnectToRepository(const RepEntryInfo & currRep, PkiClient * ClientPki, int TimeOut, mString & err) const; /*! \brief This function is used to connect to a Repository. * \param RepName [IN] The name of the repository. * \param RepAddress [IN] The address of the repository. * \param RepPort [IN] The port of the repository. * \param RepCert [IN] The certificate of the repository. * \param ClientPki [IN] The instance of PkiClient to use. * \param TimeOut [IN] TimeOut>0: the connection timeout. * \param err [OUT] The error. * \return true on success, false on failure. */ bool ConnectToRepository(const mString & RepName, const mString & RepAddress, unsigned int RepPort, const PKI_CERT & RepCert, PkiClient * ClientPki, int TimeOut, mString & err) const; /*! \brief This function converts the errors into a inter-entity response. * \param transactionID [IN] The transaction ID. * \param recipient [IN] The recipient. */ void ERR_to_STORED_NEWPKI_RESPONSE(const Asn1OctetString & transactionID, const X509_PUBKEY * recipient); /*! \brief This function verifies if the public key of a certificate is in rep_path. * \param rep_path [IN] The list of public keys. * \param Cert [IN] The certificate to verifiy. * \return true if Cert is in the list, false is Cert is not known. */ static bool RepositoryKnowsObject(const STACK_OF(X509_PUBKEY) * rep_path, const PKI_CERT & Cert); /*! \brief This function adds the public key of a certificate to rep_path. * \param rep_path [IN/OUT] The list of public keys. * \param Cert [IN] The certificate to add. * \return true on success, false on failure. */ static bool AddRepositoryToObjectsPath(STACK_OF(X509_PUBKEY) * rep_path, const PKI_CERT & Cert); private: #define MAIL_JOBS_STACK "create table mails (mail_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, mail LONGBLOB NOT NULL);" #define MAIL_INSERT "insert into mails (mail) values ('%s');" #define MAIL_DELETE "delete from mails where mail_id=%ld;" #define MAIL_SELECT "select * from mails;" unsigned long m_StoreType; AsynchJobsEvent * m_event; NewPKIStore * m_store; PKI_CERT m_EntityCert; mString m_EntityName; EntityLog * m_Logging; ReadersWriter m_RepositoriesLock; mVector m_Repositories; CryptedNewpkiResponses m_waitingResps; mVector m_waitingReqs; TransactionIds m_waitingDelResps; CriticalSection m_waitingDelRespsLock; #define SYNCH_CONF 1 #define SYNCH_REQS 2 #define SYNCH_RESPS 4 #define SYNCH_ALL (SYNCH_CONF | SYNCH_REQS | SYNCH_RESPS) ExportedPkiConf m_PkiConf; CriticalSection ConfPushLock; NewpkiThread hThreadConfigurationPush; bool m_PushToAllRep; static void ThreadConfigurationPush(const NewpkiThread * Thread, void * param); bool Private_PushConfiguration(const NewpkiThread * Thread); /*! \brief This function is used to send a inter-entity-response, it will sent it to the repositories. * \param transactionID [IN] The transaction ID. * \param Response [IN] The response. * \param Recipient [IN] The recipient. * \return true on success, false on failure. */ bool InsertResponse(const Asn1OctetString & transactionID, const NewpkiResponse & Response, const X509_PUBKEY * Recipient) const; /*! \brief This function is to request the deletion of a response. * \param transationID [IN] The transaction ID to delete. * \return true on success, false on failure. */ bool DeleteResponse(const Asn1OctetString & transationID) const; static void ThreadRepositoriesSynchro(const NewpkiThread * Thread, void *param); bool SynchronizeWithRepositories(const NewpkiThread * Thread, EntityConfCrypted & myConf, CryptedNewpkiRequests & reqs, CryptedNewpkiResponses & resps, int what); bool SynchronizeWithRepository(const NewpkiThread * Thread, EntityConfCrypted & myConf, CryptedNewpkiRequests & reqs, CryptedNewpkiResponses & resps, const mString & RepName, const mString & RepAddress, unsigned int RepPort, const PKI_CERT & RepCert, PkiClient * ClientPki, mString & Err, int what); bool DoRepositoriesSynchro(const NewpkiThread * Thread, int what); static void ThreadResponderWorker(const NewpkiThread * Thread, void *param); bool OnNewResponse(CryptedNewpkiResponse & response); bool OnNewRequest(const CryptedNewpkiRequest & request, mString & SenderName); NewpkiThread hThreadRepositoriesSynchro; NewpkiThread hThreadResponderWorker; EmailConf m_MailerConf; SmtpClient m_Mailer; mVector m_AdminMailQueue; CriticalSection m_AdminMailQueueLock; NewpkiThread hThreadMailQueue; static void ThreadMailQueue(const NewpkiThread * Thread, void * param); void LoadMails(); void RemoveMail(unsigned long id); bool InsertMail(MailQueueEntry & q) const; mVector m_AdminMails; const X509_ACL_Validator * m_AclValidator; SQL_Connection * m_DbConn; mVector m_EntityParentCerts; }; #endif