XRootD
XrdSecProtocolsss.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d S e c P r o t o c o l s s s . c c */
4 /* */
5 /* (c) 2008 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* All Rights Reserved */
7 /* Produced by Andrew Hanushevsky for Stanford University under contract */
8 /* DE-AC02-76-SFO0515 with the Department of Energy */
9 /* */
10 /* This file is part of the XRootD software suite. */
11 /* */
12 /* XRootD is free software: you can redistribute it and/or modify it under */
13 /* the terms of the GNU Lesser General Public License as published by the */
14 /* Free Software Foundation, either version 3 of the License, or (at your */
15 /* option) any later version. */
16 /* */
17 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20 /* License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25 /* */
26 /* The copyright holder's institutional names and contributor's names may not */
27 /* be used to endorse or promote products derived from this software without */
28 /* specific prior written permission of the institution or contributor. */
29 /******************************************************************************/
30 
31 #if !defined(__FreeBSD__)
32 #include <alloca.h>
33 #endif
34 #include <cctype>
35 #include <iostream>
36 #include <cstdlib>
37 #include <cstring>
38 #include <strings.h>
39 #include <cstdio>
40 #include <sys/param.h>
41 #include <unistd.h>
42 
43 #include "XrdVersion.hh"
44 
45 #include "XrdNet/XrdNetUtils.hh"
46 #include "XrdOuc/XrdOucCRC.hh"
47 #include "XrdOuc/XrdOucErrInfo.hh"
48 #include "XrdOuc/XrdOucEnv.hh"
49 #include "XrdOuc/XrdOucPup.hh"
51 #include "XrdOuc/XrdOucUtils.hh"
55 #include "XrdSys/XrdSysE2T.hh"
56 #include "XrdSys/XrdSysPlatform.hh"
57 #include "XrdSys/XrdSysPthread.hh"
58 
59 /******************************************************************************/
60 /* D e f i n e s */
61 /******************************************************************************/
62 
63 #define XrdsssPROTOIDENT "sss"
64 
65 #define CLDBG(x) if (sssDEBUG) std::cerr<<"sec_sss: "<<x<<'\n'<<std::flush
66 
67 /******************************************************************************/
68 /* L o c a l C l a s s e s */
69 /******************************************************************************/
70 
71 namespace
72 {
73 class Persona
74 {
75 public:
76 XrdSecsssKT::ktEnt *kTab;
77 char *xAuth;
78 char *xUser;
79 char *xGrup;
80 char *name;
81 char *host;
82 char *vorg;
83 char *role;
84 char *grps;
85 char *caps;
86 char *endo;
87 char *creds;
88 int credslen;
89 char *pident;
90 
91  Persona(XrdSecsssKT::ktEnt *kP)
92  {memset(this, 0, sizeof(Persona));
93  kTab = kP;
94  }
95  ~Persona() {}
96 
97 bool Clonable(const char *aTypes)
98  {char aKey[XrdSecPROTOIDSIZE+2];
99  if (!xAuth || !name || !pident
100  || !(kTab->Data.Opts & XrdSecsssKT::ktEnt::allUSR)) return false;
101  int n = strlen(xAuth);
102  if (n < 2 || n >= XrdSecPROTOIDSIZE) return false;
103  *aKey = ':';
104  strcpy(aKey+1, xAuth);
105  return strstr(aTypes, aKey) != 0;
106  }
107  };
108 
109 // Struct to manage dynamically allocated data buffer
110 //
111 struct sssRR_DataHdr
112 {
114 
115  sssRR_DataHdr() : P(0) {}
116  ~sssRR_DataHdr() {if (P) free(P);}
117 };
118 }
119 
120 /******************************************************************************/
121 /* S t a t i c D a t a */
122 /******************************************************************************/
123 
124 XrdCryptoLite *XrdSecProtocolsss::CryptObj = 0;
125 XrdSecsssKT *XrdSecProtocolsss::ktObject = 0;
126 XrdSecsssID *XrdSecProtocolsss::idMap = 0;
127 char *XrdSecProtocolsss::aProts = 0;
128 XrdSecsssEnt *XrdSecProtocolsss::staticID = 0;
129 int XrdSecProtocolsss::deltaTime =13;
130 bool XrdSecProtocolsss::isMutual = false;
131 bool XrdSecProtocolsss::isMapped = false;
132 bool XrdSecProtocolsss::ktFixed = false;
133 
135  {"bf32", XrdSecsssRR_Hdr::etBFish32},
136  {0, '0'}
137  };
138 
139 namespace
140 {
141 XrdSysMutex initMutex;
142 
143 bool sssDEBUG = false;
144 bool sssUseKN = false;
145 }
146 
147 /******************************************************************************/
148 /* A u t h e n t i c a t e */
149 /******************************************************************************/
150 
152  XrdSecParameters **parms,
153  XrdOucErrInfo *einfo)
154 {
155  static const int minLen = sizeof(XrdSecsssRR_Hdr) + XrdSecsssRR_Data_HdrLen;
156  static const int maxLen = XrdSecsssRR_Data::MaxDSz + minLen;
157  static const int Special= XrdSecsssKT::ktEnt::anyUSR
159 
160  XrdSecsssRR_Hdr *rrHdr = (XrdSecsssRR_Hdr *)(cred->buffer);
161  XrdSecsssRR_Data *rrData;
162  XrdSecsssKT::ktEnt decKey;
163  Persona myID(&decKey);
164 
165  char *idP, *dP, *eodP, *theIP = 0, *theHost = 0, *atKey = 0, eType;
166  int idNum = 0, idTLen, idSz, dLen;
167  bool badAttr = false;
168 
169 // Make sure we have atleast the header plus the data header
170 //
171  if (cred->size < minLen)
172  return Fatal(einfo, "Auth", EINVAL, "Credentials too small.");
173 
174 // Make sure the credentials are not too big (people misuse sss)
175 //
176  if (cred->size > maxLen)
177  return Fatal(einfo, "Auth", EINVAL, "Credentials too big.");
178 
179 // Allocate the buffer from the stack
180 //
181  rrData = (XrdSecsssRR_Data *)alloca(cred->size);
182 
183 // Decode the credentials
184 //
185  if ((dLen = Decode(einfo, decKey, cred->buffer, rrData, cred->size)) <= 0)
186  return -1;
187 
188 // Check if we should echo back the LID
189 //
190  if (rrData->Options == XrdSecsssRR_DataHdr::SndLID)
191  {XrdSecsssRR_DataResp rrResp;
192  char lidBuff[16];
193  rrResp.Options = 0;
194  getLID(lidBuff, sizeof(lidBuff));
195  dP = rrResp.Data;
197  XrdOucPup::Pack(&dP, lidBuff);
198  int n = dP-rrResp.Data + XrdSecsssRR_Data_HdrLen;
199  *parms = Encode(einfo, decKey, rrHdr, &rrResp, n);
200  return (*parms ? 1 : -1);
201  }
202 
203 // Extract out the entity information
204 //
205  dP = rrData->Data; eodP = dP + dLen - XrdSecsssRR_Data_HdrLen;
206  CLDBG("Processing " <<dLen <<" byes");
207  while(dP < eodP)
208  {eType = *dP++;
209  CLDBG("eType=" <<static_cast<int>(eType)
210  <<" Used " <<dP-rrData->Data <<" left " <<eodP-dP);
211  if (!XrdOucPup::Unpack(&dP, eodP, &idP, idSz) || (idP && *idP == '\0'))
212  {Fatal(einfo, "Authenticate", EINVAL, "Invalid id string.");
213  return -1;
214  }
215  idNum++;
216  switch(eType)
217  {case XrdSecsssRR_Data::theName: myID.name = idP; break;
218  case XrdSecsssRR_Data::theVorg: myID.vorg = idP; break;
219  case XrdSecsssRR_Data::theRole: myID.role = idP; break;
220  case XrdSecsssRR_Data::theGrps: myID.grps = idP; break;
221  case XrdSecsssRR_Data::theEndo: myID.endo = idP; break;
222  case XrdSecsssRR_Data::theCred: myID.creds = idP;
223  myID.credslen = idSz;break;
225  if (*idP == '[')
226  myID.host = theIP = idP;
227 
228  else theHost = idP;
229  break;
230  case XrdSecsssRR_Data::theRand: idNum--; break;
231 
232  case XrdSecsssRR_Data::theAuth: myID.xAuth = idP; break;
233 
234  case XrdSecsssRR_Data::theTID: myID.pident = idP; break;
235  case XrdSecsssRR_Data::theAKey: if (atKey) badAttr = true;
236  atKey = idP; break;
238  if (!atKey) badAttr = true;
239  else {Entity.eaAPI->Add(std::string(atKey),
240  std::string(idP), true);
241  atKey = 0;
242  }
243  break;
244  case XrdSecsssRR_Data::theUser: myID.xUser = idP; break;
245  case XrdSecsssRR_Data::theGrup: myID.xGrup = idP; break;
246  case XrdSecsssRR_Data::theCaps: myID.caps = idP; break;
247  default: break;
248  }
249  }
250 
251 // Verify that we have some kind of identification
252 //
253  if (!idNum)
254  {Fatal(einfo, "Authenticate", ENOENT, "No identification specified.");
255  return -1;
256  }
257 
258 // Make sure we didn't encounter any attribute errors
259 //
260  if (badAttr)
261  {Fatal(einfo, "Authenticate", EINVAL, "Invalid attribute specification.");
262  return -1;
263  }
264 
265 // Verify the source of the information to largely prevent packet stealing. New
266 // version of the protocol will send an IP address which we prefrentially use.
267 // Older version used a hostname. This causes problems for multi-homed machines.
268 //
269 if (!(decKey.Data.Opts & XrdSecsssKT::ktEnt::noIPCK))
270  {if (!theHost && !theIP)
271  {Fatal(einfo,"Authenticate",ENOENT,"No hostname or IP address specified.");
272  return -1;
273  }
274  CLDBG(urName <<' ' <<urIP <<" or " <<urIQ << " must match "
275  <<(theHost ? theHost : "?") <<' ' <<(theIP ? theIP : "[?]"));
276  if (theIP)
277  {if (strcmp(theIP, urIP) && strcmp(theIP, urIQ))
278  {Fatal(einfo, "Authenticate", EINVAL, "IP address mismatch.");
279  return -1;
280  }
281  } else if (strcmp(theHost, urName))
282  {Fatal(einfo, "Authenticate", EINVAL, "Hostname mismatch.");
283  return -1;
284  }
285  } else {
286  CLDBG(urName <<' ' <<urIP <<" or " <<urIQ << " forwarded token from "
287  <<(theHost ? theHost : "?") <<' ' <<(theIP ? theIP : "[?]"));
288  }
289 
290 // At this point we need to check if this identity can be passed as a clone
291 //
292  if (aProts && myID.Clonable(aProts))
293  {strlcpy(Entity.prot, myID.xAuth, sizeof(Entity.prot));
295  if (myID.xUser) XrdOucUtils::getUID(myID.xUser,Entity.uid,&Entity.gid);
296  if (myID.xGrup) XrdOucUtils::getGID(myID.xGrup,Entity.gid);
297  } else {
298  // Set correct username
299  //
300  if (decKey.Data.Opts & Special)
301  {if (!myID.name) myID.name = (char *)"nobody";}
302  else myID.name = decKey.Data.User;
303 
304  // Set correct group
305  //
306  if (decKey.Data.Opts & XrdSecsssKT::ktEnt::usrGRP) myID.grps = 0;
307  else {if (decKey.Data.Opts & XrdSecsssKT::ktEnt::anyGRP)
308  {if (!myID.grps) myID.grps = (char *)"nogroup";}
309  else myID.grps = decKey.Data.Grup;
310  }
311 
312  // Set corresponding uid and gid
313  //
314  if (myID.name) XrdOucUtils::getUID(myID.name, Entity.uid, &Entity.gid);
315  if (myID.grps) XrdOucUtils::getGID(myID.grps, Entity.gid);
316  }
317 
318 // Calculate the amount of space we will need
319 //
320  idTLen = strlen(urName)
321  + (myID.name ? strlen(myID.name)+1 : 0)
322  + (myID.vorg ? strlen(myID.vorg)+1 : 0)
323  + (myID.role ? strlen(myID.role)+1 : 0)
324  + (myID.grps ? strlen(myID.grps)+1 : 0)
325  + (myID.caps ? strlen(myID.caps)+1 : 0)
326  + (myID.endo ? strlen(myID.endo)+1 : 0)
327  + (myID.creds ? myID.credslen : 0)
328  + (myID.pident ? strlen(myID.pident)+1 : 0);
329 
330 // Complete constructing our identification
331 //
332  if (idBuff) free(idBuff);
333  idBuff = idP = (char *)malloc(idTLen);
334  Entity.host = urName;
335  Entity.name = setID(myID.name, &idP);
336  Entity.vorg = setID(myID.vorg, &idP);
337  Entity.role = setID(myID.role, &idP);
338  Entity.grps = setID(myID.grps, &idP);
339  Entity.caps = setID(myID.caps, &idP);
340  Entity.endorsements = setID(myID.endo, &idP);
341 
342  if (myID.pident)
343  {strcpy(idP, myID.pident);
344  Entity.pident = idP;
345  idP += strlen(myID.pident) + 1;
346  }
347 
348  if (myID.creds)
349  {memcpy(idP, myID.creds, myID.credslen);
350  Entity.creds = idP;
351  Entity.credslen = myID.credslen;
352  }
353 
354 // All done
355 //
356  return 0;
357 }
358 
359 /******************************************************************************/
360 /* Private: D e c o d e */
361 /******************************************************************************/
362 
363 int XrdSecProtocolsss::Decode(XrdOucErrInfo *error,
364  XrdSecsssKT::ktEnt &decKey,
365  char *iBuff,
366  XrdSecsssRR_DataHdr *rrDHdr,
367  int iSize)
368 {
369  XrdSecsssRR_Hdr *rrHdr = (XrdSecsssRR_Hdr *)iBuff;
370  char *iData = iBuff+sizeof(XrdSecsssRR_Hdr);
371  int rc, genTime, dLen = iSize - sizeof(XrdSecsssRR_Hdr);
372 
373 // Check if this is a recognized protocol
374 //
375  if (strcmp(rrHdr->ProtID, XrdsssPROTOIDENT))
376  {char emsg[256];
377  snprintf(emsg, sizeof(emsg),
378  "Authentication protocol id mismatch (%.4s != %.4s).",
379  XrdsssPROTOIDENT, rrHdr->ProtID);
380  return Fatal(error, "Decode", EINVAL, emsg);
381  }
382 
383 // Verify decryption method
384 //
385  if (rrHdr->EncType != Crypto->Type())
386  return Fatal(error, "Decode", ENOTSUP, "Crypto type not supported.");
387 
388 // Check if this is a V2 client. V2 client always supply the keyname of the
389 // key which we may or may not use. If specified, make sure it's correct.
390 //
391  if (rrHdr->knSize)
392  {int knSize = static_cast<int>(rrHdr->knSize);
393  v2EndPnt = true;
394  if (knSize > XrdSecsssKT::ktEnt::NameSZ || knSize & 0x07
395  || knSize >= dLen || iData[knSize-1])
396  return Fatal(error, "Decode", EINVAL, "Invalid keyname specified.");
397  if (sssUseKN) strcpy(decKey.Data.Name, iData);
398  else decKey.Data.Name[0] = '\0';
399  CLDBG("V2 client using keyname '" <<iData <<"' dLen=" <<dLen
400  <<(sssUseKN ? "" : " (ignored)"));
401  iData += knSize; dLen -= knSize;
402  } else decKey.Data.Name[0] = '\0';
403 
404 // Get the key ID
405 //
406  decKey.Data.ID = ntohll(rrHdr->KeyID);
407  if (keyTab->getKey(decKey, *decKey.Data.Name))
408  return Fatal(error, "Decode", ENOENT, "Decryption key not found.");
409 
410 // Decrypt
411 //
412  CLDBG("Decode keyid: " <<decKey.Data.ID <<" bytes " <<dLen);
413  if ((rc = Crypto->Decrypt(decKey.Data.Val, decKey.Data.Len, iData, dLen,
414  (char *)rrDHdr, dLen)) <= 0)
415  return Fatal(error, "Decode", -rc, "Unable to decrypt credentials.");
416 
417 // Verify that the packet has not expired (OK to do before CRC check)
418 //
419  genTime = ntohl(rrDHdr->GenTime);
420  if (genTime + deltaTime <= myClock())
421  return Fatal(error, "Decode", ESTALE,
422  "Credentials expired (check for clock skew).");
423 
424 // Return success (size of decrypted info)
425 //
426  return rc;
427 }
428 
429 /******************************************************************************/
430 /* D e l e t e */
431 /******************************************************************************/
432 
434 {
435 // Delete things that get re-allocated every time. The staticID is allocated
436 // only once so it must stick around for every instance of this object.
437 //
438  if (urName) free(urName); // Same pointer as Entity.host
439  if (idBuff) free(idBuff);
440  if (Crypto && Crypto != CryptObj) delete Crypto;
441  if (keyTab && keyTab != ktObject) delete keyTab;
442 
443  delete this;
444 }
445 
446 /******************************************************************************/
447 /* Private: e M s g */
448 /******************************************************************************/
449 
450 int XrdSecProtocolsss::eMsg(const char *epname, int rc,
451  const char *txt1, const char *txt2,
452  const char *txt3, const char *txt4)
453 {
454  std::cerr <<"Secsss (" << epname <<"): ";
455  std::cerr <<txt1;
456  if (rc>0) std::cerr <<"; " <<XrdSysE2T(rc);
457  if (txt2) std::cerr <<txt2;
458  if (txt3) std::cerr <<txt3;
459  if (txt4) {std::cerr <<txt4;}
460  std::cerr <<"\n" <<std::flush;
461 
462  return (rc ? (rc < 0 ? rc : -rc) : -1);
463 }
464 
465 /******************************************************************************/
466 /* Private: E n c o d e */
467 /******************************************************************************/
468 
469 XrdSecCredentials *XrdSecProtocolsss::Encode(XrdOucErrInfo *einfo,
470  XrdSecsssKT::ktEnt &encKey,
471  XrdSecsssRR_Hdr *rrHdr,
472  XrdSecsssRR_DataHdr *rrDHdr,
473  int dLen)
474 {
475  char *credP;
476  int knum, cLen, hdrSZ = sizeof(XrdSecsssRR_Hdr) + rrHdr->knSize;
477 
478 // Make sure we don't overrun a 1 server's buffer. V2 servers are forgiving.
479 //
480  if (!v2EndPnt && dLen > (int)sizeof(XrdSecsssRR_Data))
481  {Fatal(einfo,"Encode",ENOBUFS,"Insufficient buffer space for credentials.");
482  return (XrdSecCredentials *)0;
483  }
484 
485 // Complete the packet
486 //
487  XrdSecsssKT::genKey(rrDHdr->Rand, sizeof(rrDHdr->Rand));
488  rrDHdr->GenTime = htonl(myClock());
489  memset(rrDHdr->Pad, 0, sizeof(rrDHdr->Pad));
490 
491 // Allocate an output buffer
492 //
493  cLen = hdrSZ + dLen + Crypto->Overhead();
494  if (!(credP = (char *)malloc(cLen)))
495  {Fatal(einfo, "Encode", ENOMEM, "Insufficient memory for credentials.");
496  return (XrdSecCredentials *)0;
497  }
498 
499 // Copy the header and encrypt the data
500 //
501  memcpy(credP, (const void *)rrHdr, hdrSZ);
502  CLDBG("Encode keyid: " <<encKey.Data.ID <<" bytes " <<cLen-hdrSZ);
503  if ((dLen = Crypto->Encrypt(encKey.Data.Val, encKey.Data.Len, (char *)rrDHdr,
504  dLen, credP+hdrSZ, cLen-hdrSZ)) <= 0)
505  {Fatal(einfo, "Encode", -dLen, "Unable to encrypt credentials.");
506  return (XrdSecCredentials *)0;
507  }
508 
509 // Return new credentials
510 //
511  dLen += hdrSZ; knum = encKey.Data.ID&0x7fffffff;
512  CLDBG("Ret " <<dLen <<" bytes of credentials; k=" <<knum);
513  return new XrdSecCredentials(credP, dLen);
514 }
515 
516 /******************************************************************************/
517 /* Private: F a t a l */
518 /******************************************************************************/
519 
520 int XrdSecProtocolsss::Fatal(XrdOucErrInfo *erP, const char *epn, int rc,
521  const char *etxt)
522 {
523  if (erP) {erP->setErrInfo(rc, etxt);
524  CLDBG(epn <<": " <<etxt);
525  }
526  else eMsg(epn, rc, etxt);
527  return 0;
528 }
529 
530 /******************************************************************************/
531 /* Private: g e t C r e d */
532 /******************************************************************************/
533 
534 int XrdSecProtocolsss::getCred(XrdOucErrInfo *einfo, XrdSecsssRR_DataHdr *&dP,
535  const char *myUrlID, const char *myIP)
536 {
537  int dLen;
538 
539 // Indicate we have been here
540 //
541  Sequence = 1;
542 
543 // For mutual authentication, the server needs to first send back a handshake.
544 //
545  if (isMutual)
549  }
550 
551 // Otherwise we use a static ID or a mapped id. Note that we disallow sending
552 // credentials unless mutual authentication occurs.
553 //
554  if (myUrlID && idMap)
555  {if ((dLen = idMap->Find(myUrlID, (char *&)dP, myIP, dataOpts)) <= 0)
556  return Fatal(einfo, "getCred", ESRCH, "No loginid mapping.");
557  } else {
558  int theOpts = dataOpts & ~XrdSecsssEnt::addCreds;
559  dLen = staticID->RR_Data((char *&)dP, myIP, theOpts);
560  }
561 
562 // Return response length
563 //
564  dP->Options = XrdSecsssRR_DataHdr::UseData;
565  return dLen;
566 }
567 
568 /******************************************************************************/
569 
570 int XrdSecProtocolsss::getCred(XrdOucErrInfo *einfo,
571  XrdSecsssRR_DataHdr *&dP,
572  const char *myUrlID,
573  const char *myIP,
574  XrdSecParameters *parm)
575 {
576  XrdSecsssKT::ktEnt decKey;
577  XrdSecsssRR_Data prData;
578  char *lidP = 0, *bP, *idP, *eodP, idType;
579  int idSz, dLen, theOpts;
580 
581 // Make sure we can decode this and not overrun our buffer
582 //
583  if (parm->size > (int)sizeof(prData.Data))
584  return Fatal(einfo, "getCred", EINVAL, "Invalid server response size.");
585 
586 // Decode the credentials
587 //
588  if ((dLen = Decode(einfo, decKey, parm->buffer, &prData, parm->size)) <= 0)
589  return Fatal(einfo, "getCred", EINVAL, "Unable to decode server response.");
590 
591 // Extract out the loginid. This messy code is for backwards compatibility.
592 //
593  bP = prData.Data; eodP = dLen + (char *)&prData;
594  while(bP < eodP)
595  {idType = *bP++;
596  if (!XrdOucPup::Unpack(&bP, eodP, &idP, idSz) || !idP || *idP == 0)
597  return Fatal(einfo, "getCred", EINVAL, "Invalid id string.");
598  switch(idType)
599  {case XrdSecsssRR_Data::theLgid: lidP = idP; break;
600  case XrdSecsssRR_Data::theHost: break;
601  case XrdSecsssRR_Data::theRand: break;
602  default: return Fatal(einfo,"getCred",EINVAL,"Invalid id type.");
603  }
604  }
605 
606 // Verify that we have the loginid
607 //
608  if (!lidP) return Fatal(einfo, "getCred", ENOENT, "No loginid returned.");
609 
610 // Try to map the id appropriately
611 //
612  if (!idMap) return staticID->RR_Data((char *&)dP, myIP, dataOpts);
613 
614 // Map the loginid. We disallow sending credentials unless the key allows it.
615 //
616  if (!myUrlID) myUrlID = lidP;
617  if (!(decKey.Data.Opts & XrdSecsssKT::ktEnt::allUSR))
618  theOpts = dataOpts & ~XrdSecsssEnt::addCreds;
619  else theOpts = dataOpts;
620  if ((dLen = idMap->Find(lidP, (char *&)dP, myIP, theOpts)) <= 0)
621  return Fatal(einfo, "getCred", ESRCH, "No loginid mapping.");
622 
623 // All done
624 //
625  dP->Options = XrdSecsssRR_DataHdr::UseData;
626  return dLen;
627 }
628 
629 /******************************************************************************/
630 /* g e t C r e d e n t i a l s */
631 /******************************************************************************/
632 
634  XrdOucErrInfo *einfo)
635 {
636  static const int nOpts = XrdNetUtils::oldFmt;
637  XrdSecsssRR_Hdr2 rrHdr;
638  sssRR_DataHdr rrDataHdr;
639  XrdSecsssKT::ktEnt encKey;
640  XrdOucEnv *errEnv;
641 
642  const char *myIP = 0, *myUD = 0;
643  char ipBuff[64];
644  int dLen;
645 
646 // Make sure we can extract out required information and get it as needed
647 //
648  if (einfo && (errEnv=einfo->getEnv()))
649  {if (isMapped) myUD = errEnv->Get("username");
650  if (!(myIP=errEnv->Get("sockname")))
651  {int fd = epAddr->SockFD();
652  if (fd > 0 && XrdNetUtils::IPFormat(-fd,ipBuff,sizeof(ipBuff),nOpts))
653  myIP = ipBuff;
654  else myIP = 0;
655  }
656  }
657 
658 // Do some debugging here
659 //
660  CLDBG("getCreds: " <<static_cast<int>(Sequence)
661  << " ud: '" <<(myUD ? myUD : "")
662  <<"' ip: '" <<(myIP ? myIP : "") <<"'");
663 
664 // Get the actual data portion
665 //
666  if (Sequence) dLen = getCred(einfo, rrDataHdr.P, myUD, myIP, parms);
667  else dLen = getCred(einfo, rrDataHdr.P, myUD, myIP);
668  if (!dLen) return (XrdSecCredentials *)0;
669 
670 // Get an encryption key
671 //
672  if (keyTab->getKey(encKey))
673  {Fatal(einfo, "getCredentials", ENOENT, "Encryption key not found.");
674  return (XrdSecCredentials *)0;
675  }
676 
677 // Fill out the header
678 //
679  strcpy(rrHdr.ProtID, XrdsssPROTOIDENT);
680  memset(rrHdr.Pad, 0, sizeof(rrHdr.Pad));
681  rrHdr.KeyID = htonll(encKey.Data.ID);
682  rrHdr.EncType = Crypto->Type();
683 
684 // Determine if we should send the keyname (v2 servers only)
685 //
686  if (v2EndPnt)
687  {int k = strlen(encKey.Data.Name), n = (k + 8) & ~7;
688  strcpy(rrHdr.keyName, encKey.Data.Name);
689  if (n - k > 1) memset(rrHdr.keyName + k, 0, n - k);
690  rrHdr.knSize = static_cast<uint8_t>(n);
691  } else rrHdr.knSize = 0;
692 
693 // Now simply encode the data and return the result
694 //
695  return Encode(einfo, encKey, &rrHdr, rrDataHdr.P, dLen);
696 }
697 
698 /******************************************************************************/
699 /* Private: g e t L I D */
700 /******************************************************************************/
701 
702 char *XrdSecProtocolsss::getLID(char *buff, int blen)
703 {
704  const char *dot;
705 
706 // Extract out the loginid from the trace id
707 //
708  if (!Entity.tident
709  || !(dot = index(Entity.tident,'.'))
710  || dot == Entity.tident
711  || dot >= (Entity.tident+blen)) strcpy(buff,"nobody");
712  else {int idsz = dot - Entity.tident;
713  strncpy(buff, Entity.tident, idsz);
714  *(buff+idsz) = '\0';
715  }
716 
717 // All done
718 //
719  return buff;
720 }
721 
722 /******************************************************************************/
723 /* I n i t _ C l i e n t */
724 /******************************************************************************/
725 
727 {
728  XrdSysMutexHelper initMon(&initMutex);
729  XrdSecsssKT *ktP;
730  struct stat buf;
731  char *Colon;
732  int lifeTime;
733 
734 // We must have <enccode>.[+]<lifetime>:<keytab>
735 //
736  if (!pP || !*pP) return Fatal(erp, "Init_Client", EINVAL,
737  "Client parameters missing.");
738 
739 // Get encryption object
740 //
741  if (!*pP || *(pP+1) != '.') return Fatal(erp, "Init_Client", EINVAL,
742  "Encryption type missing.");
743  if (!(Crypto = Load_Crypto(erp, *pP))) return 0;
744  pP += 2;
745 
746 // Check if this is a v2 server and if credentials are to be sent
747 //
748  if (*pP == '+')
749  {v2EndPnt = true;
750  dataOpts |= XrdSecsssEnt::addExtra;
751  if (*(pP+1) == '0') dataOpts |= XrdSecsssEnt::addCreds;
752  }
753 
754 // The next item is the cred lifetime
755 //
756  lifeTime = strtol(pP, &Colon, 10);
757  if (!lifeTime || *Colon != ':') return Fatal(erp, "Init_Client", EINVAL,
758  "Credential lifetime missing.");
759  deltaTime = lifeTime; pP = Colon+1;
760 
761 // Get the correct keytab
762 //
763  if (ktFixed || (ktObject && ktObject->Same(pP))) keyTab = ktObject;
764  else if (*pP == '/' && !stat(pP, &buf))
765  {if (!(ktP=new XrdSecsssKT(erp,pP,XrdSecsssKT::isClient,3600)))
766  return Fatal(erp, "Init_Client", ENOMEM,
767  "Unable to create keytab object.");
768  if (erp->getErrInfo()) {delete ktP; return 0;}
769  if (!ktObject) ktObject = ktP;
770  keyTab = ktP;
771  CLDBG("Client keytab='" <<pP <<"'");
772  } else keyTab = ktObject;
773 
774  if (!keyTab)
775  return Fatal(erp, "Init_Client", ENOENT,
776  "Unable to determine keytab location.");
777 
778 // All done
779 //
780  return 1;
781 }
782 
783 /******************************************************************************/
784 /* I n i t _ S e r v e r */
785 /******************************************************************************/
786 
788 {
789 
790 // This is a trivial init
791 //
792  keyTab = ktObject;
793  Crypto = CryptObj;
794  return 1;
795 }
796 
797 /******************************************************************************/
798 /* L o a d _ C l i e n t */
799 /******************************************************************************/
800 
801 char *XrdSecProtocolsss::Load_Client(XrdOucErrInfo *erp, const char *parms)
802 {
803  static const char *KTPath = XrdSecsssKT::genFN();
804  static const int rfrHR = 60*60;
805  struct stat buf;
807  const char *kP = 0;
808  char *myName;
809 
810 // Get our full host name
811 //
812  if (!(myName = XrdNetUtils::MyHostName(0)))
813  {Fatal(erp, "Load_Client", ENOENT, "Unable to obtain local hostname.");
814  return (char *)0;
815  }
816 
817 // Tell the entity serialization object who we are
818 //
820  free(myName);
821 
822 // Check for the presence of a registry object
823 //
824  idMap = XrdSecsssID::getObj(aType, staticID);
825  switch(aType)
826  {case XrdSecsssID::idDynamic: isMutual = true; break;
827  case XrdSecsssID::idStaticM: isMutual = true;
828  idMap = 0; break;
829  case XrdSecsssID::idStatic: idMap = 0; break;
830  case XrdSecsssID::idMapped: isMapped = true; break;
831  case XrdSecsssID::idMappedM: isMapped = true; break;
832  default: idMap = 0; break;
833  }
834 
835 // We want to establish the default location of the keytable. First check
836 // the environment passed from the client then the envar. We support two
837 // version of the envar for backward compatibility due to an early mistake.
838 //
839  if( erp && erp->getEnv() && ( kP = erp->getEnv()->Get( "xrd.sss" ) ) )
840  ktFixed = true;
841  else if ( ( (kP = getenv("XrdSecSSSKT")) || (kP = getenv("XrdSecsssKT")) )
842  && *kP && !stat(kP, &buf))
843  ktFixed = true;
844  else kP = 0;
845 
846  if (!kP && !stat(KTPath, &buf)) kP = KTPath;
847 
848 // Build the keytable if we actual have a path (if none, then the server
849 // will have to supply the path)
850 //
851  if (kP)
852  {if (!(ktObject=new XrdSecsssKT(erp,kP,XrdSecsssKT::isClient,rfrHR)))
853  {Fatal(erp, "Load_Client", ENOMEM, "Unable to create keytab object.");
854  return (char *)0;
855  }
856  if (erp->getErrInfo())
857  {delete ktObject, ktObject = 0; return (char *)0;}
858  CLDBG("Client keytab='" <<kP <<"'");
859  }
860 
861 // All done
862 //
863  return (char *)"";
864 }
865 
866 /******************************************************************************/
867 /* Private: L o a d _ C r y p t o */
868 /******************************************************************************/
869 
870 XrdCryptoLite *XrdSecProtocolsss::Load_Crypto(XrdOucErrInfo *erp,
871  const char *eN)
872 {
873  XrdCryptoLite *cP;
874  char buff[128];
875  int rc, i = 0;
876 
877 // Find correct crypto object
878 //
879  while(CryptoTab[i].cName && strcmp(CryptoTab[i].cName, eN)) i++;
880 
881 // If we didn't find it, complain
882 //
883  if (!CryptoTab[i].cName)
884  {sprintf(buff, "Secsss: %s cryptography not supported.", eN);
885  Fatal(erp, "Load_Crypto", EINVAL, buff);
886  return (XrdCryptoLite *)0;
887  }
888 
889 // Return load result
890 //
891  if ((cP = XrdCryptoLite::Create(rc, eN, CryptoTab[i].cType))) return cP;
892  sprintf(buff,"Secsss: %s cryptography load failed; %s",eN,XrdSysE2T(rc));
893  Fatal(erp, "Load_Crypto", EINVAL, buff);
894  return (XrdCryptoLite *)0;
895 }
896 
897 /******************************************************************************/
898 
899 XrdCryptoLite *XrdSecProtocolsss::Load_Crypto(XrdOucErrInfo *erp,
900  const char eT)
901 {
902  XrdCryptoLite *cP;
903  char buff[128];
904  int rc, i = 0;
905 
906 // Check if we can use the satic object
907 //
908  if (CryptObj && eT == CryptObj->Type()) return CryptObj;
909 
910 // Find correct crypto object
911 //
912  while(CryptoTab[i].cName && CryptoTab[i].cType != eT) i++;
913 
914 // If we didn't find it, complain
915 //
916  if (!CryptoTab[i].cName)
917  {sprintf(buff, "Secsss: 0x%hhx cryptography not supported.", eT);
918  Fatal(erp, "Load_Crypto", EINVAL, buff);
919  return (XrdCryptoLite *)0;
920  }
921 
922 // Return load result
923 //
924  if ((cP = XrdCryptoLite::Create(rc, CryptoTab[i].cName, eT))) return cP;
925  sprintf(buff,"Secsss: 0x%hhx cryptography load failed; %s",eT,XrdSysE2T(rc));
926  Fatal(erp, "Load_Crypto", EINVAL, buff);
927  return (XrdCryptoLite *)0;
928 }
929 
930 /******************************************************************************/
931 /* L o a d _ S e r v e r */
932 /******************************************************************************/
933 
934 char *XrdSecProtocolsss::Load_Server(XrdOucErrInfo *erp, const char *parms)
935 {
936  const char *msg = 0;
937  const char *encName = "bf32", *ktClient = "", *ktServer = 0;
938  char buff[2048], parmbuff[2048], *op, *od, *eP;
939  int lifeTime = 13, rfrTime = 60*60;
940  XrdOucTokenizer inParms(parmbuff);
941  const char *ask4Creds = "";
942 
943 // Duplicate the parms
944 //
945  if (parms) strlcpy(parmbuff, parms, sizeof(parmbuff));
946 
947 // Expected parameters: [{-c | --clientkt} <ckt_path>]
948 // [{-e | --encrypt} <enctype>]
949 // [{-g | --getcreds}]
950 // [{-k | --keyname}]
951 // [{-l | --lifetime} <seconds>]
952 // [{-p | --proxy} <prots>]
953 // [{-r | --refresh} <minutes>]
954 // [{-s | --serverkt} <skt_path>]
955 //
956  if (parms && inParms.GetLine())
957  while((op = inParms.GetToken()))
958  {if (!strcmp("-k", op) || !strcmp("--keyname", op))
959  {sssUseKN = true;
960  continue;
961  }
962  if (!strcmp("-g", op) || !strcmp("--getcreds", op))
963  {ask4Creds = "0";
964  continue;
965  }
966  if (!(od = inParms.GetToken()))
967  {sprintf(buff,"Secsss: Missing %s parameter argument",op);
968  msg = buff; break;
969  }
970  if (!strcmp("-c", op) || !strcmp("--clientkt", op))
971  ktClient = od;
972  else if (!strcmp("-e", op) || !strcmp("--encrypt", op))
973  encName = od;
974  else if (!strcmp("-l", op) || !strcmp("--lifetime", op))
975  {lifeTime = strtol(od, &eP, 10) * 60;
976  if (errno || *eP || lifeTime < 1)
977  {msg = "Secsss: Invalid life time"; break;}
978  }
979  else if (!strcmp("-p", op) || !strcmp("--proxy", op))
980  {int n = strlen(od) + 2;
981  aProts = (char *)malloc(n);
982  *aProts = ':';
983  strcpy(aProts+1, od);
984  }
985  else if (!strcmp("-r", op) || !strcmp("--rfresh", op))
986  {rfrTime = strtol(od, &eP, 10) * 60;
987  if (errno || *eP || rfrTime < 600)
988  {msg = "Secsss: Invalid refresh time"; break;}
989  }
990  else if (!strcmp("-s", op) || !strcmp("-serverkt", op))
991  ktServer = od;
992  else {sprintf(buff,"Secsss: Invalid parameter - %s",op);
993  msg = buff; break;
994  }
995  }
996 
997 // Check for errors
998 //
999  if (msg) {Fatal(erp, "Load_Server", EINVAL, msg); return (char *)0;}
1000 
1001 // Load the right crypto object
1002 //
1003  if (!(CryptObj = Load_Crypto(erp, encName))) return (char *)0;
1004 
1005 // Supply default keytab location if not specified
1006 //
1007  if (!ktServer) ktServer = XrdSecsssKT::genFN();
1008 
1009 // Set the delta time used to expire credentials
1010 //
1011  deltaTime = lifeTime;
1012 
1013 // Create a keytab object (only one for the server)
1014 //
1015  if (!(ktObject = new XrdSecsssKT(erp, ktServer, XrdSecsssKT::isServer,
1016  rfrTime)))
1017  {Fatal(erp, "Load_Server", ENOMEM, "Unable to create keytab object.");
1018  return (char *)0;
1019  }
1020  if (erp->getErrInfo()) return (char *)0;
1021  ktFixed = true;
1022  CLDBG("Server keytab='" <<ktServer <<"'");
1023 
1024 // Construct client parameter <enccode>.+<lifetime>:<keytab>
1025 // Note: The plus preceding the <lifetime> indicates that we are a V2 server.
1026 // V1 clients will simply ignore this and treat us as a V1 server.
1027 //
1028  sprintf(buff, "%c.+%s%d:%s", CryptObj->Type(),ask4Creds,lifeTime,ktClient);
1029  CLDBG("client parms='" <<buff <<"'");
1030  return strdup(buff);
1031 }
1032 
1033 /******************************************************************************/
1034 /* m y C l o c k */
1035 /******************************************************************************/
1036 
1037 int XrdSecProtocolsss::myClock()
1038 {
1039  static const time_t baseTime = 1222183880;
1040 
1041  return static_cast<int>(time(0)-baseTime);
1042 }
1043 
1044 /******************************************************************************/
1045 /* s e t I D */
1046 /******************************************************************************/
1047 
1048 char *XrdSecProtocolsss::setID(char *id, char **idP)
1049 {
1050  if (id)
1051  {int n = strlen(id);
1052  strcpy(*idP, id); id = *idP; *idP = *idP + n + 1;
1053  }
1054  return id;
1055 }
1056 
1057 /******************************************************************************/
1058 /* s e t I P */
1059 /******************************************************************************/
1060 
1061 void XrdSecProtocolsss::setIP(XrdNetAddrInfo &endPoint)
1062 {
1063  if (!endPoint.Format(urIP, sizeof(urIP), XrdNetAddrInfo::fmtAdv6)) *urIP=0;
1064  if (!endPoint.Format(urIQ, sizeof(urIQ), XrdNetAddrInfo::fmtAdv6,
1065  XrdNetAddrInfo::old6Map4)) *urIQ=0;
1066  Entity.addrInfo = epAddr = &endPoint;
1067 }
1068 
1069 /******************************************************************************/
1070 /* X r d S e c P r o t o c o l s s s I n i t */
1071 /******************************************************************************/
1072 
1073 extern "C"
1074 {
1075 char *XrdSecProtocolsssInit(const char mode,
1076  const char *parms,
1077  XrdOucErrInfo *erp)
1078 {
1079 
1080 // Set debug option
1081 //
1082  if (getenv("XrdSecDEBUG")) sssDEBUG = true;
1083 
1084 // Perform load-time initialization
1085 //
1086  return (mode == 'c' ? XrdSecProtocolsss::Load_Client(erp, parms)
1087  : XrdSecProtocolsss::Load_Server(erp, parms));
1088 }
1089 }
1090 
1091 /******************************************************************************/
1092 /* X r d S e c P r o t o c o l s s s O b j e c t */
1093 /******************************************************************************/
1094 
1096 
1097 extern "C"
1098 {
1100  const char *hostname,
1101  XrdNetAddrInfo &endPoint,
1102  const char *parms,
1103  XrdOucErrInfo *erp)
1104 {
1105  XrdSecProtocolsss *prot;
1106  int Ok;
1107 
1108 // Get a new protocol object
1109 //
1110  if (!(prot = new XrdSecProtocolsss(endPoint.Name(hostname), endPoint)))
1111  XrdSecProtocolsss::Fatal(erp, "sss_Object", ENOMEM,
1112  "Secsss: Insufficient memory for protocol.");
1113  else {Ok = (mode == 'c' ? prot->Init_Client(erp, parms)
1114  : prot->Init_Server(erp, parms));
1115 
1116  if (!Ok) {prot->Delete(); prot = 0;}
1117  }
1118 
1119 // All done
1120 //
1121  return (XrdSecProtocol *)prot;
1122 }
1123 }
int stat(const char *path, struct stat *buf)
#define XrdSecPROTOIDSIZE
Definition: XrdSecEntity.hh:47
XrdSecBuffer XrdSecCredentials
#define XrdsssPROTOIDENT
#define CLDBG(x)
XrdVERSIONINFO(XrdSecProtocolsssObject, secsss)
XrdSecProtocol * XrdSecProtocolsssObject(const char mode, const char *hostname, XrdNetAddrInfo &endPoint, const char *parms, XrdOucErrInfo *erp)
char * XrdSecProtocolsssInit(const char mode, const char *parms, XrdOucErrInfo *erp)
static const int XrdSecsssRR_Data_HdrLen
Definition: XrdSecsssRR.hh:77
int emsg(int rc, char *msg)
const char * XrdSysE2T(int errcode)
Definition: XrdSysE2T.cc:104
if(Avsz)
size_t strlcpy(char *dst, const char *src, size_t sz)
virtual int Encrypt(const char *key, int keyLen, const char *src, int srcLen, char *dst, int dstLen)=0
virtual int Overhead()
virtual int Decrypt(const char *key, int keyLen, const char *src, int srcLen, char *dst, int dstLen)=0
virtual char Type()
static XrdCryptoLite * Create(int &rc, const char *Name, const char Type='\0')
static const int old6Map4
Use deprecated IPV6 mapped format.
int Format(char *bAddr, int bLen, fmtUse fmtType=fmtAuto, int fmtOpts=0)
const char * Name(const char *eName=0, const char **eText=0)
static char * MyHostName(const char *eName="*unknown*", const char **eText=0)
Definition: XrdNetUtils.cc:667
static int IPFormat(const struct sockaddr *sAddr, char *bP, int bL, int opts=0)
Definition: XrdNetUtils.cc:584
static const int oldFmt
Definition: XrdNetUtils.hh:256
char * Get(const char *varname)
Definition: XrdOucEnv.hh:69
int setErrInfo(int code, const char *emsg)
XrdOucEnv * getEnv()
static int Unpack(char **buff, const char *bend, char **data, int &dlen)
Definition: XrdOucPup.cc:250
static int Pack(struct iovec **, const char *, unsigned short &buff)
Definition: XrdOucPup.cc:52
char * GetToken(char **rest=0, int lowcase=0)
static bool getGID(const char *gName, gid_t &gID)
Definition: XrdOucUtils.cc:513
static bool getUID(const char *uName, uid_t &uID, gid_t *gID=0)
Definition: XrdOucUtils.cc:529
bool Add(XrdSecAttr &attr)
char * vorg
Entity's virtual organization(s)
Definition: XrdSecEntity.hh:71
const char * pident
Trace identifier (originator)
Definition: XrdSecEntity.hh:82
int credslen
Length of the 'creds' data.
Definition: XrdSecEntity.hh:78
XrdNetAddrInfo * addrInfo
Entity's connection details.
Definition: XrdSecEntity.hh:80
XrdSecEntityAttr * eaAPI
non-const API to attributes
Definition: XrdSecEntity.hh:92
const char * tident
Trace identifier always preset.
Definition: XrdSecEntity.hh:81
char prot[XrdSecPROTOIDSIZE]
Auth protocol used (e.g. krb5)
Definition: XrdSecEntity.hh:67
char * caps
Entity's capabilities.
Definition: XrdSecEntity.hh:74
char * creds
Raw entity credentials or cert.
Definition: XrdSecEntity.hh:77
gid_t gid
Unix gid or 0 if none.
Definition: XrdSecEntity.hh:87
char * grps
Entity's group name(s)
Definition: XrdSecEntity.hh:73
uid_t uid
Unix uid or 0 if none.
Definition: XrdSecEntity.hh:86
char * name
Entity's name.
Definition: XrdSecEntity.hh:69
char * role
Entity's role(s)
Definition: XrdSecEntity.hh:72
char * endorsements
Protocol specific endorsements.
Definition: XrdSecEntity.hh:75
char * host
Entity's host name dnr dependent.
Definition: XrdSecEntity.hh:70
XrdSecEntity Entity
static void setHostName(const char *hnP)
static const int addExtra
Add v2 data.
Definition: XrdSecsssEnt.hh:77
static const int addCreds
Add v2 data plus creds.
Definition: XrdSecsssEnt.hh:78
int RR_Data(char *&dP, const char *hostIP, int dataOpts)
static const int anyUSR
Definition: XrdSecsssKT.hh:67
struct XrdSecsssKT::ktEnt::ktData Data
static const int noIPCK
Definition: XrdSecsssKT.hh:70
static const int anyGRP
Definition: XrdSecsssKT.hh:68
static const int allUSR
Definition: XrdSecsssKT.hh:66
static const int usrGRP
Definition: XrdSecsssKT.hh:69
static const int NameSZ
Definition: XrdSecsssKT.hh:49
int Same(const char *path)
Definition: XrdSecsssKT.hh:109
static char * genFN()
Definition: XrdSecsssKT.cc:249
int getKey(ktEnt &ktEql, bool andKeyID=false)
Definition: XrdSecsssKT.cc:207
static void genKey(char *Buff, int blen)
Definition: XrdSecsssKT.cc:268
Generic structure to pass security information back and forth.
char * buffer
Pointer to the buffer.
int size
Size of the buffer or length of data in the buffer.
static int eMsg(const char *epn, int rc, const char *txt1, const char *txt2=0, const char *txt3=0, const char *txt4=0)
static char * Load_Client(XrdOucErrInfo *erp, const char *Parms)
int Init_Server(XrdOucErrInfo *erp, const char *Parms)
XrdSecCredentials * getCredentials(XrdSecParameters *parms=0, XrdOucErrInfo *einfo=0)
static char * Load_Server(XrdOucErrInfo *erp, const char *Parms)
int Authenticate(XrdSecCredentials *cred, XrdSecParameters **parms, XrdOucErrInfo *einfo=0)
static int Fatal(XrdOucErrInfo *erP, const char *epn, int rc, const char *etxt)
void Delete()
Delete the protocol object. DO NOT use C++ delete() on this object.
int Init_Client(XrdOucErrInfo *erp, const char *Parms)
static const char SndLID
Definition: XrdSecsssRR.hh:72
static const char UseData
Definition: XrdSecsssRR.hh:71
char Data[XrdSecsssRR_Data::MinDSz+16]
Definition: XrdSecsssRR.hh:113
static const char theHost
Definition: XrdSecsssRR.hh:106
static const char theUser
Definition: XrdSecsssRR.hh:101
static const char theAKey
Definition: XrdSecsssRR.hh:99
static const char theCaps
Definition: XrdSecsssRR.hh:103
char Data[DataSz]
Definition: XrdSecsssRR.hh:85
static const char theAuth
Definition: XrdSecsssRR.hh:97
static const char theRole
Definition: XrdSecsssRR.hh:91
static const char theName
Definition: XrdSecsssRR.hh:89
static const char theLgid
Definition: XrdSecsssRR.hh:105
static const char theGrps
Definition: XrdSecsssRR.hh:92
static const char theRand
Definition: XrdSecsssRR.hh:95
static const char theEndo
Definition: XrdSecsssRR.hh:93
static const char theAVal
Definition: XrdSecsssRR.hh:100
static const char theVorg
Definition: XrdSecsssRR.hh:90
static const char theGrup
Definition: XrdSecsssRR.hh:102
static const char theTID
Definition: XrdSecsssRR.hh:98
static const int MaxDSz
Definition: XrdSecsssRR.hh:82
static const char theCred
Definition: XrdSecsssRR.hh:94
char keyName[XrdSecsssKT::ktEnt::NameSZ]
Definition: XrdSecsssRR.hh:59
long long KeyID
Definition: XrdSecsssRR.hh:49
static const char etBFish32
Definition: XrdSecsssRR.hh:47