XRootD
Loading...
Searching...
No Matches
XrdSecProtect Class Reference

#include <XrdSecProtect.hh>

Collaboration diagram for XrdSecProtect:

Public Member Functions

virtual ~XrdSecProtect ()
 Destructor.
virtual void Delete ()
 Delete this object. Use this method as opposed to operator delete.
virtual int Secure (SecurityRequest *&newreq, ClientRequest &thereq, const char *thedata)
virtual const char * Verify (SecurityRequest &secreq, ClientRequest &thereq, const char *thedata)

Public Attributes

bool(XrdSecProtect::* Need2Secure )(ClientRequest &thereq)

Protected Member Functions

 XrdSecProtect (XrdSecProtocol *aprot, XrdSecProtect &pRef, bool edok=true)
 XrdSecProtect (XrdSecProtocol *aprot=0, bool edok=true)
void SetProtection (const ServerResponseReqs_Protocol &inReqs)

Friends

class XrdSecProtector

Detailed Description

Definition at line 55 of file XrdSecProtect.hh.

Constructor & Destructor Documentation

◆ ~XrdSecProtect()

virtual XrdSecProtect::~XrdSecProtect ( )
inlinevirtual

Destructor.

Definition at line 132 of file XrdSecProtect.hh.

132{}

◆ XrdSecProtect() [1/2]

XrdSecProtect::XrdSecProtect ( XrdSecProtocol * aprot = 0,
bool edok = true )
inlineprotected

Definition at line 136 of file XrdSecProtect.hh.

137 : Need2Secure(&XrdSecProtect::Screen),
138 authProt(aprot), secVec(0), lastSeqno(1),
139 edOK(edok), secVerData(false)
140 {}
bool(XrdSecProtect::* Need2Secure)(ClientRequest &thereq)

References XrdSecProtect(), and Need2Secure.

Referenced by XrdSecProtect(), and XrdSecProtect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ XrdSecProtect() [2/2]

XrdSecProtect::XrdSecProtect ( XrdSecProtocol * aprot,
XrdSecProtect & pRef,
bool edok = true )
inlineprotected

Definition at line 142 of file XrdSecProtect.hh.

144 : Need2Secure(&XrdSecProtect::Screen),
145 authProt(aprot), secVec(pRef.secVec),
146 lastSeqno(0), edOK(edok),
147 secVerData(pRef.secVerData) {}

References XrdSecProtect(), and Need2Secure.

Here is the call graph for this function:

Member Function Documentation

◆ Delete()

virtual void XrdSecProtect::Delete ( )
inlinevirtual

Delete this object. Use this method as opposed to operator delete.

Definition at line 64 of file XrdSecProtect.hh.

64{delete this;}

◆ Secure()

int XrdSecProtect::Secure ( SecurityRequest *& newreq,
ClientRequest & thereq,
const char * thedata )
virtual

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(<protP>)(thereq)) result = <protP>->Secure(....); else result = 0;

Modify the above to your particuar needs but gaurd the call!

Parameters
newreqA reference to a pointer where the new request, if needed, will be placed. The new request will consist of a kXR_sigver request followed by hash. The request buffer must be freed using free() when it is no longer needed.
thereqReference to the client request header/body that needs to be secured. The request must be in network byte order.
thedataThe 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.
Returns
<0 An error occurred and the return value is -errno.
>0 The length of the new request whose pointer is in newreq. This is the nuber of bytes that must be sent.

Definition at line 239 of file XrdSecProtect.cc.

242{
243 static const ClientSigverRequest initSigVer = {{0,0}, htons(kXR_sigver),
244 0, kXR_secver_0, 0, 0,
245 kXR_SHA256, {0, 0, 0}, 0
246 };
247 struct buffHold {XrdSecReq *P;
248 XrdSecBuffer *bP;
249 buffHold() : P(0), bP(0) {}
250 ~buffHold() {if (P) free(P); if (bP) delete bP;}
251 };
252 static const int iovNum = 3;
253 struct iovec iov[iovNum];
254 buffHold myReq;
255 kXR_unt64 mySeq;
256 const char *sigBuff, *payload = thedata;
257 unsigned char secHash[SHA256_DIGEST_LENGTH];
258 int sigSize, n, newSize, rc, paysize = 0;
259 bool nodata = false;
260
261// Generate a new sequence number
262//
263 mySeq = nextSeqno++;
264 mySeq = htonll(mySeq);
265
266// Determine if we are going to sign the payload and its location
267//
268 if (thereq.header.dlen)
269 {kXR_unt16 reqid = htons(thereq.header.requestid);
270 paysize = ntohl(thereq.header.dlen);
271 if (!payload) payload = ((char *)&thereq) + sizeof(ClientRequest);
272 if (reqid == kXR_write || reqid == kXR_pgwrite) n = (secVerData ? 3 : 2);
273 else n = 3;
274 } else n = 2;
275
276// Fill out the iovec
277//
278 iov[0].iov_base = (char *)&mySeq;
279 iov[0].iov_len = sizeof(mySeq);
280 iov[1].iov_base = (char *)&thereq;
281 iov[1].iov_len = sizeof(ClientRequest);
282 if (n < 3) nodata = true;
283 else {iov[2].iov_base = (char *)payload;
284 iov[2].iov_len = paysize;
285 }
286
287// Compute the hash
288//
289 if (!GetSHA2(secHash, iov, n)) return -EDOM;
290
291// Now encrypt the hash
292//
293 if (edOK)
294 {rc = authProt->Encrypt((const char *)secHash,sizeof(secHash),&myReq.bP);
295 if (rc < 0) return rc;
296 sigSize = myReq.bP->size;
297 sigBuff = myReq.bP->buffer;
298 } else {
299 sigSize = sizeof(secHash);
300 sigBuff = (char *)secHash;
301 }
302
303// Allocate a new request object
304//
305 newSize = sizeof(SecurityRequest) + sigSize;
306 myReq.P = (XrdSecReq *)malloc(newSize);
307 if (!myReq.P) return -ENOMEM;
308
309// Setup the security request (we only support signing)
310//
311 memcpy(&(myReq.P->secReq), &initSigVer, sizeof(ClientSigverRequest));
312 memcpy(&(myReq.P->secReq.header.streamid ), thereq.header.streamid,
313 sizeof(myReq.P->secReq.header.streamid));
314 memcpy(&(myReq.P->secReq.sigver.expectrid),&thereq.header.requestid,
315 sizeof(myReq.P->secReq.sigver.expectrid));
316 myReq.P->secReq.sigver.seqno = mySeq;
317 if (nodata) myReq.P->secReq.sigver.flags |= kXR_nodata;
318 myReq.P->secReq.sigver.dlen = htonl(sigSize);
319
320// Append the signature to the request
321//
322 memcpy(&(myReq.P->secSig), sigBuff, sigSize);
323
324// Return pointer to he security request and its size
325//
326 newreq = &(myReq.P->secReq); myReq.P = 0;
327 return newSize;
328}
kXR_char streamid[2]
Definition XProtocol.hh:158
struct ClientRequestHdr header
Definition XProtocol.hh:887
kXR_unt16 requestid
Definition XProtocol.hh:159
@ kXR_sigver
Definition XProtocol.hh:142
@ kXR_write
Definition XProtocol.hh:132
@ kXR_pgwrite
Definition XProtocol.hh:139
@ kXR_nodata
Definition XProtocol.hh:774
#define kXR_secver_0
@ kXR_SHA256
Definition XProtocol.hh:767
unsigned long long kXR_unt64
Definition XPtypes.hh:99
unsigned short kXR_unt16
Definition XPtypes.hh:67

References ClientRequestHdr::dlen, ClientRequest::header, kXR_nodata, kXR_pgwrite, kXR_secver_0, kXR_SHA256, kXR_sigver, kXR_write, ClientRequestHdr::requestid, and ClientRequestHdr::streamid.

Referenced by XrdCl::XRootDTransport::GetSignature().

Here is the caller graph for this function:

◆ SetProtection()

void XrdSecProtect::SetProtection ( const ServerResponseReqs_Protocol & inReqs)
protected

Definition at line 334 of file XrdSecProtect.cc.

335{
336 unsigned int lvl, vsz;
337
338// Check for no security, the simlplest case
339//
340 if (inReqs.secvsz == 0 && inReqs.seclvl == 0)
341 {memset(&myReqs, 0, sizeof(myReqs));
342 secVec = 0;
343 secVerData = false;
344 return;
345 }
346
347// Precheck the security level
348//
349 lvl = inReqs.seclvl;
350 if (lvl > kXR_secPedantic) lvl = kXR_secPedantic;
351
352// Perform the default setup (the usual case)
353//
354 secVec = secTable.Vec[lvl-1];
355 myReqs.seclvl = lvl;
356 myReqs.secvsz = 0;
357 myReqs.secver = kXR_secver_0;
358 myReqs.secopt = inReqs.secopt;
359
360// Set options
361//
362 secVerData = (inReqs.secopt & kXR_secOData) != 0;
363
364// Create a modified vectr if there are overrides
365//
366 if (inReqs.secvsz != 0)
367 {const ServerResponseSVec_Protocol *urVec = &inReqs.secvec;
368 memcpy(myVec, secVec, maxRIX);
369 vsz = inReqs.secvsz;
370 for (unsigned int i = 0; i < vsz; i++, urVec++)
371 {if (urVec->reqindx < maxRIX)
372 {if (urVec->reqsreq > kXR_signNeeded)
373 myVec[urVec->reqindx] = kXR_signNeeded;
374 else myVec[urVec->reqindx] = urVec->reqsreq;
375 }
376 }
377 secVec = myVec;
378 }
379}
ServerResponseSVec_Protocol secvec
#define kXR_secOData
#define kXR_secPedantic
#define kXR_signNeeded

References kXR_secOData, kXR_secPedantic, kXR_secver_0, kXR_signNeeded, ServerResponseSVec_Protocol::reqindx, ServerResponseSVec_Protocol::reqsreq, ServerResponseReqs_Protocol::seclvl, ServerResponseReqs_Protocol::secopt, ServerResponseReqs_Protocol::secvec, and ServerResponseReqs_Protocol::secvsz.

Referenced by XrdSecProtector::Config(), and XrdSecProtector::New4Client().

Here is the caller graph for this function:

◆ Verify()

const char * XrdSecProtect::Verify ( SecurityRequest & secreq,
ClientRequest & thereq,
const char * thedata )
virtual

Verify that a request was properly secured.

Parameters
secreqA reference to the kXR_sigver request followed by whatever data was sent (normally an encrypted verification hash). All but the request code must be in network byte order.
thereqReference to the client request header/body that needs to be verified. The request must be in network byte order.
thedataThe request data whose length resides in theReq.dlen.
Returns
Upon success zero is returned. Otherwise a pointer to a null delimited string describing the problem is returned.

Definition at line 385 of file XrdSecProtect.cc.

389{
390 struct buffHold {XrdSecBuffer *bP;
391 buffHold() : bP(0) {}
392 ~buffHold() {if (bP) delete bP;}
393 };
394 static const int iovNum = 3;
395 struct iovec iov[iovNum];
396 buffHold myReq;
397 unsigned char *inHash, secHash[SHA256_DIGEST_LENGTH];
398 int dlen, n, rc;
399
400// First check for replay attacks. The incoming sequence number must be greater
401// the previous one we have seen. Since it is in network byte order we can use
402// a simple byte for byte compare (no need for byte swapping).
403//
404 if (memcmp(&lastSeqno, &secreq.sigver.seqno, sizeof(lastSeqno)) >= 0)
405 return "Incorrect signature sequence";
406
407// Do basic verification for this request
408//
409 if (memcmp(secreq.header.streamid, thereq.header.streamid,
410 sizeof(secreq.header.streamid)))
411 return "Signature streamid mismatch";
412 if (secreq.sigver.expectrid != thereq.header.requestid)
413 return "Signature requestid mismatch";
414 if (secreq.sigver.version != kXR_secver_0)
415 return "Unsupported signature version";
416 if ((secreq.sigver.crypto & kXR_HashMask) != kXR_SHA256)
417 return "Unsupported signature hash";
418 if (secreq.sigver.crypto & kXR_rsaKey)
419 return "Unsupported signature key";
420
421// Now get the hash information
422//
423 dlen = ntohl(secreq.header.dlen);
424 inHash = ((unsigned char *)&secreq)+sizeof(SecurityRequest);
425
426// Now decrypt the hash
427//
428 if (edOK)
429 {rc = authProt->Decrypt((const char *)inHash, dlen, &myReq.bP);
430 if (rc < 0) return XrdSysE2T(-rc);
431 if (myReq.bP->size != (int)sizeof(secHash))
432 return "Invalid signature hash length";
433 inHash = (unsigned char *)myReq.bP->buffer;
434 } else {
435 if (dlen != (int)sizeof(secHash))
436 return "Invalid signature hash length";
437 }
438
439// Fill out the iovec to recompute the hash
440//
441 iov[0].iov_base = (char *)&secreq.sigver.seqno;
442 iov[0].iov_len = sizeof(secreq.sigver.seqno);
443 iov[1].iov_base = (char *)&thereq;
444 iov[1].iov_len = sizeof(ClientRequest);
445 if (thereq.header.dlen == 0 || secreq.sigver.flags & kXR_nodata) n = 2;
446 else {iov[2].iov_base = (char *)thedata;
447 iov[2].iov_len = ntohl(thereq.header.dlen);
448 n = 3;
449 }
450
451// Compute the hash
452//
453 if (!GetSHA2(secHash, iov, n))
454 return "Signature hash computation failed";
455
456// Compare this hash with the hash we were given
457//
458 if (memcmp(secHash, inHash, sizeof(secHash)))
459 return "Signature hash mismatch";
460
461// This request has been verified (update the seqno)
462//
463 lastSeqno = secreq.sigver.seqno;
464 return 0;
465}
struct ClientRequestHdr header
Definition XProtocol.hh:923
struct ClientSigverRequest sigver
Definition XProtocol.hh:924
@ kXR_HashMask
Definition XProtocol.hh:768
@ kXR_rsaKey
Definition XProtocol.hh:769
const char * XrdSysE2T(int errcode)
Definition XrdSysE2T.cc:104

References ClientSigverRequest::crypto, ClientRequestHdr::dlen, ClientSigverRequest::expectrid, ClientSigverRequest::flags, ClientRequest::header, SecurityRequest::header, kXR_HashMask, kXR_nodata, kXR_rsaKey, kXR_secver_0, kXR_SHA256, ClientRequestHdr::requestid, ClientSigverRequest::seqno, SecurityRequest::sigver, ClientRequestHdr::streamid, ClientSigverRequest::version, and XrdSysE2T().

Here is the call graph for this function:

◆ XrdSecProtector

friend class XrdSecProtector
friend

Definition at line 58 of file XrdSecProtect.hh.

References XrdSecProtector.

Referenced by XrdSecProtector.

Member Data Documentation

◆ Need2Secure

bool(XrdSecProtect::* XrdSecProtect::Need2Secure) (ClientRequest &thereq)

Test whether or not a request needs to be secured. This method pointer should only be invoked via the NEED2SECURE macro (see above).

Parameters
thereqReference to the request header/body in network byte order.
Returns
false - request need not be secured (equals false).
true - request needs to be secured.

Definition at line 76 of file XrdSecProtect.hh.

Referenced by XrdSecProtect(), and XrdSecProtect().


The documentation for this class was generated from the following files: