// ---------------------------------------------------------------------- // File: XrdMqMessage.hh // Author: Andreas-Joachim Peters - CERN // ---------------------------------------------------------------------- /************************************************************************ * EOS - the CERN Disk Storage System * * Copyright (C) 2011 CERN/Switzerland * * * * 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 3 of the License, or * * (at your option) any later version. * * * * 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, see .* ************************************************************************/ #ifndef __XMQMESSAGE_H__ #define __XMQMESSAGE_H__ #include #include #include #include #include #include #include "common/StringConversion.hh" #define XMQHEADER "xrdmqmessage.header" #define XMQBODY "xrdmqmessage.body" #define XMQMONITOR "xrdmqmessage.mon" #define XMQADVISORYHOST "xrdmqmessage.advisoryhost" #define XMQADVISORYSTATE "xrdmqmessage.advisorystate" #define XMQCADVISORYSTATUS "xmqclient.advisory.status" #define XMQCADVISORYQUERY "xmqclient.advisory.query" #define XMQCADVISORYFLUSHBACKLOG "xmqclient.advisory.flushbacklog" //------------------------------------------------------------------------------ //! Class KeyWrapper //------------------------------------------------------------------------------ class KeyWrapper { public: //---------------------------------------------------------------------------- //! Constructor //! //! By constructing this object, you give up ownership of the pointer! //---------------------------------------------------------------------------- KeyWrapper(EVP_PKEY* key) : pkey(key) { } KeyWrapper() {} //---------------------------------------------------------------------------- //! Destructor //---------------------------------------------------------------------------- ~KeyWrapper() { if (pkey) { EVP_PKEY_free(pkey); pkey = nullptr; } } EVP_PKEY* get() { return pkey; } private: EVP_PKEY* pkey = nullptr; }; //------------------------------------------------------------------------------ //! Class XrdMqMessageHeader //------------------------------------------------------------------------------ class XrdMqMessageHeader { public: //---------------------------------------------------------------------------- //! Constructor //---------------------------------------------------------------------------- XrdMqMessageHeader(); //---------------------------------------------------------------------------- //! Destructor //---------------------------------------------------------------------------- virtual ~XrdMqMessageHeader() {}; //---------------------------------------------------------------------------- //! Message type //---------------------------------------------------------------------------- enum { kMessage = 0, kStatusMessage = 1, kQueryMessage = 2 }; //---------------------------------------------------------------------------- //! Get header buffer //---------------------------------------------------------------------------- const char* GetHeaderBuffer() const; //---------------------------------------------------------------------------- //! Encode the message header //---------------------------------------------------------------------------- void Encode(); //---------------------------------------------------------------------------- //! Decode //! //! @param str_header header in string format //! //! @return true if successfully decoded, otherwise false //---------------------------------------------------------------------------- bool Decode(const char* str_header = 0); //---------------------------------------------------------------------------- //! Print message header //---------------------------------------------------------------------------- void Print(); //---------------------------------------------------------------------------- //! Get the current time and set the two values //! //! @param sec current time in seconds //! @param nsec current time in nanoseconds //! //! @todo This should be moved in a common place //---------------------------------------------------------------------------- static void GetTime(time_t& sec, long& nsec); XrdOucString kMessageId; ///< filled by sender XrdOucString kReplyId; ///< filled by sender XrdOucString kSenderId; ///< filled by sender XrdOucString kBrokerId; ///< filled by broker XrdOucString kReceiverId; ///< filled by receiver XrdOucString kReceiverQueue; ///< filled by sender XrdOucString kDescription; ///< filled by sender time_t kSenderTime_sec; ///< filled by sender long kSenderTime_nsec; ///< filled by sender time_t kBrokerTime_sec; ///< filled by broker long kBrokerTime_nsec; ///< filled by broker time_t kReceiverTime_sec; ///< filled by receiver long kReceiverTime_nsec; ///< filled by receiver XrdOucString kMessageSignature; ///< signature of the message body hash XrdOucString kMessageDigest; ///< hash of the message body bool kEncrypted;///< encrypted with private key or not int kType; ///< type of message private: XrdOucString mMsgHdrBuffer; ///< message header buffer XrdOucString kCertificateHash; ///< certificate hash used to verify sender }; //------------------------------------------------------------------------------ //! Class XrdMqMessage //------------------------------------------------------------------------------ class XrdMqMessage { public: //---------------------------------------------------------------------------- //! Constructor for empty message //---------------------------------------------------------------------------- XrdMqMessage(const char* description = "XrdMqMessage", int type = XrdMqMessageHeader::kMessage); //---------------------------------------------------------------------------- //! Constructor for message based on raw(wire) format //! //! @param rawmessage raw messsage format //---------------------------------------------------------------------------- XrdMqMessage(XrdOucString& rawmessage); //---------------------------------------------------------------------------- //! Destructor //---------------------------------------------------------------------------- virtual ~XrdMqMessage() {}; //---------------------------------------------------------------------------- //! Factory method to create a message from raw format //! //! @param rawmessage raw message data //! //! @return message object or 0 //---------------------------------------------------------------------------- static XrdMqMessage* Create(const char* rawmessage); //---------------------------------------------------------------------------- //! Generate a new message id //---------------------------------------------------------------------------- void NewId(); //---------------------------------------------------------------------------- //! Read in configuration from file //! //! @param configfile path to configuration file //! //! @return true if successful, otherwise false //---------------------------------------------------------------------------- static bool Configure(const char* configfile = 0); //---------------------------------------------------------------------------- //! Encode full message //---------------------------------------------------------------------------- virtual void Encode(); //---------------------------------------------------------------------------- //! Decode //! //! @return true if successful, othersie false //---------------------------------------------------------------------------- virtual bool Decode(); //---------------------------------------------------------------------------- //! RSA encrypt using private key //! //! @param data input data //! @param data_length input data length //! @param encrypted_data output encrypted data. It's not necessarily null //! terminated and could contain embedded nulls. //! @param encrypted_length output data length //! //! @return true if encryption successful, otherwise false //---------------------------------------------------------------------------- static bool RSAEncrypt(char* data, ssize_t data_length, char*& encrypted_data, ssize_t& encrypted_length); //---------------------------------------------------------------------------- //! RSA decrypt using public key //! //! @param encrypted_data input encrypted data //! @param encrypted_length input data length //! @param data decrypted data pointer for which the caller takes ownership //! @param data_length length of the decrypted data //! @param key_hash hash of the key to be used //! //! @return true if decryption successful, otherwise false //---------------------------------------------------------------------------- static bool RSADecrypt(char* encrypted_data, ssize_t encrypted_length, char*& data, ssize_t& data_length, XrdOucString& key_hash); //---------------------------------------------------------------------------- //! Sign message object //! //! @param encrypt if true //! //! @return true if signing successful, otherwise false //---------------------------------------------------------------------------- bool Sign(bool encrypt = false); //---------------------------------------------------------------------------- //! Verify message object //---------------------------------------------------------------------------- bool Verify(); //---------------------------------------------------------------------------- //! Print contents of the message object //---------------------------------------------------------------------------- virtual void Print(); //---------------------------------------------------------------------------- //! Get message buffer //---------------------------------------------------------------------------- inline const char* GetMessageBuffer() { return kMessageBuffer.c_str(); } //---------------------------------------------------------------------------- //! Set reply ID in the header of the message //! //! @param message message holding the reply ID //---------------------------------------------------------------------------- void SetReply(XrdMqMessage& message); //---------------------------------------------------------------------------- //! Set message body //! //! @param body raw data //---------------------------------------------------------------------------- void SetBody(const char* body) { kMessageBody = body; eos::common::StringConversion::Seal(kMessageBody); } //---------------------------------------------------------------------------- //! Get message body //! //! @return raw data //---------------------------------------------------------------------------- const char* GetBody() { eos::common::StringConversion::UnSeal(kMessageBody); return kMessageBody.c_str(); } //---------------------------------------------------------------------------- //! Mark as monitor message //---------------------------------------------------------------------------- inline void MarkAsMonitor() { kMonitor = true; } //! @todo These two should be review as they are used only for printing info static bool kCanSign; static bool kCanVerify; // Static settings and configuration static EVP_PKEY* PrivateKey; ///< private key for signatures static XrdOucString PublicKeyDirectory; ///< containing public keys names with hashval static XrdOucString PrivateKeyFile; ///< name of private key file static XrdOucString PublicKeyFileHash; ///< hash value of corresponding public key static XrdOucHash PublicKeyHash; ///< hash with public keys static XrdSysLogger* Logger; ///< logger object for error/debug info static XrdSysError Eroute; ///< error object for error/debug info XrdMqMessageHeader kMessageHeader; ///< message header protected: XrdOucString kMessageBuffer; XrdOucString kMessageBody; bool kMonitor; int errc; }; //------------------------------------------------------------------------------ // Class XrdAdvisoryMqMessage //------------------------------------------------------------------------------ class XrdAdvisoryMqMessage : public XrdMqMessage { public: //---------------------------------------------------------------------------- //! Constructor //---------------------------------------------------------------------------- XrdAdvisoryMqMessage(): XrdMqMessage(), kQueue(""), kOnline(false) { } //---------------------------------------------------------------------------- //! Constructor //---------------------------------------------------------------------------- XrdAdvisoryMqMessage(const char* description , const char* queue, bool online, int type): XrdMqMessage(description, type), kQueue(queue), kOnline(online) { } //---------------------------------------------------------------------------- //! Destructor //---------------------------------------------------------------------------- virtual ~XrdAdvisoryMqMessage() {}; //---------------------------------------------------------------------------- //! Factory method to create advisory object from raw format //! //! @param rawmessage raw message data //! //! @return advisory mq message object or 0 //---------------------------------------------------------------------------- static XrdAdvisoryMqMessage* Create(const char* rawmessage); //---------------------------------------------------------------------------- //! Encode message - encodes the header only, the message encoding has to be //! implemented in the derived class and the derived class has FIRST to call //! the base class. Encode function and append to kMessageBuffer the tag //! "xrdmqmessage.body=<....>" [ defined as XMQBODY ] //---------------------------------------------------------------------------- void Encode(); //---------------------------------------------------------------------------- //! Decode message //---------------------------------------------------------------------------- bool Decode(); //---------------------------------------------------------------------------- //! Print contents of the message object //---------------------------------------------------------------------------- void Print(); XrdOucString kQueue; ///< queue that changed bool kOnline; ///< mark online status }; #endif