#ifndef __XRDSECPROTECT_H__ #define __XRDSECPROTECT_H__ /******************************************************************************/ /* */ /* X r d S e c P r o t e c t . h h */ /* */ /* (c) 2016 by the Board of Trustees of the Leland Stanford, Jr., University */ /* Produced by Andrew Hanushevsky for Stanford University under contract */ /* DE-AC02-76-SFO0515 with the Department of Energy */ /* */ /* This file is part of the XRootD software suite. */ /* */ /* XRootD is free software: you can redistribute it and/or modify it under */ /* the terms of the GNU Lesser General Public License as published by the */ /* Free Software Foundation, either version 3 of the License, or (at your */ /* option) any later version. */ /* */ /* XRootD 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 Lesser General Public */ /* License for more details. */ /* */ /* You should have received a copy of the GNU Lesser General Public License */ /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ /* COPYING (GPL license). If not, see . */ /* */ /* The copyright holder's institutional names and contributor's names may not */ /* be used to endorse or promote products derived from this software without */ /* specific prior written permission of the institution or contributor. */ /******************************************************************************/ #include "XProtocol/XProtocol.hh" //------------------------------------------------------------------------------ //! This class implements the XRootD protocol security protection. //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ //! Provide a replacement for the std::invoke() function available in C++17 to //! invoke the Need2Secure member function without a vtable lookup. The //! calling convention is: if (NEED2SECURE())() and where: //! is a pointer to the relevant XrdSecProtect object (may be nil). //! is a reference to the ClientRequest object to be inspected. //------------------------------------------------------------------------------ #define NEED2SECURE(protP) protP && ((*protP).*(protP->Need2Secure)) /******************************************************************************/ /* X r d S e c P r o t e c t */ /******************************************************************************/ struct iovec; class XrdSecProtectParms; class XrdSecProtocol; class XrdSecProtect { public: friend class XrdSecProtector; //------------------------------------------------------------------------------ //! Delete this object. Use this method as opposed to operator delete. //------------------------------------------------------------------------------ virtual void Delete() {delete this;} //------------------------------------------------------------------------------ //! Test whether or not a request needs to be secured. This method pointer //! should only be invoked via the NEED2SECURE macro (see above). //! //! @param thereq Reference to the request header/body in network byte order. //! //! @return false - request need not be secured (equals false). //! @return true - request needs to be secured. //------------------------------------------------------------------------------ bool (XrdSecProtect::*Need2Secure)(ClientRequest &thereq); //------------------------------------------------------------------------------ //! Secure a request. //! //! Request securement is optional and this call should be gaurded by an if //! statement to avoid securing requests that need not be secured as follows: //! //! if (NEED2SECURE()(thereq)) result = ->Secure(....); //! else result = 0; //! //! Modify the above to your particuar needs but gaurd the call! //! //! @param newreq A reference to a pointer where the new request, if needed, //! will be placed. The new request will consist of a either a //! kXR_sigver or kXR_decrypt request followed by hash if the //! request is kXR_sigver. The request buffer must be freed //! using free() when it is no longer needed. //! @param thereq Reference to the client request header/body that needs to //! be secured. The request must be in network byte order. //! @aparam thedata The request data whose length resides in theReq.dlen. If //! thedata is nil but thereq.dlen is not zero then the request //! data must follow the request header in the thereq buffer. //! //! @return <0 An error occurred and the return value is -errno. //! @return >0 The length of the new request whose pointer is in newreq. //! This is the nuber of bytes that must be sent. //------------------------------------------------------------------------------ virtual int Secure(SecurityRequest *&newreq, ClientRequest &thereq, const char *thedata ); //------------------------------------------------------------------------------ //! Verify that a request was properly secured. //! //! @param secreq A reference to the security request (kxr_sigver or //! kXR_decrypt) followed by whatever data was sent (normally //! an encrypted verification hash for kXR_sigver). All but //! the request code must be in network byte order. //! @param thereq Reference to the client request header/body that needs to //! be verified. The request must be in network byte order. //! @aparam thedata The request data whose length resides in theReq.dlen. //! //! @return Upon success zero is returned. Otherwise a pointer to a null //! delimited string describing the problem is returned. //------------------------------------------------------------------------------ virtual const char *Verify(SecurityRequest &secreq, ClientRequest &thereq, const char *thedata ); //------------------------------------------------------------------------------ //! Destructor //------------------------------------------------------------------------------ virtual ~XrdSecProtect() {} protected: XrdSecProtect(XrdSecProtocol *aprot=0, bool edok=true) // Client! : Need2Secure(&XrdSecProtect::Screen), authProt(aprot), secVec(0), lastSeqno(1), edOK(edok), secVerData(false) {} XrdSecProtect(XrdSecProtocol *aprot, XrdSecProtect &pRef, // Server! bool edok=true) : Need2Secure(&XrdSecProtect::Screen), authProt(aprot), secVec(pRef.secVec), lastSeqno(0), edOK(edok), secVerData(pRef.secVerData) {} void SetProtection(const ServerResponseReqs_Protocol &inReqs); private: bool GetSHA2(unsigned char *hBuff, struct iovec *iovP, int iovN); bool Screen(ClientRequest &thereq); XrdSecProtocol *authProt; const char *secVec; ServerResponseReqs_Protocol myReqs; union {kXR_unt64 lastSeqno; // Used by Secure() kXR_unt64 nextSeqno; // Used by Verify() }; bool edOK; bool secVerData; static const unsigned int maxRIX = kXR_REQFENCE-kXR_auth; char myVec[maxRIX]; }; #endif