31#if !defined(__FreeBSD__)
43#include "XrdVersion.hh"
63#define XrdsssPROTOIDENT "sss"
65#define CLDBG(x) if (sssDEBUG) std::cerr<<"sec_sss: "<<x<<'\n'<<std::flush
108bool Clonable(
const char *aTypes)
110 if (!xAuth || !name || !pident
112 int n = strlen(xAuth);
115 strcpy(aKey+1, xAuth);
116 return strstr(aTypes, aKey) != 0;
126 sssRR_DataHdr() : P(0) {}
127 ~sssRR_DataHdr() {
if (P) free(P);}
138char *XrdSecProtocolsss::aProts = 0;
140int XrdSecProtocolsss::deltaTime =13;
141bool XrdSecProtocolsss::isMutual =
false;
142bool XrdSecProtocolsss::isMapped =
false;
143bool XrdSecProtocolsss::ktFixed =
false;
154bool sssDEBUG =
false;
155bool sssUseKN =
false;
174 Persona myID(&decKey);
176 char *idP = 0, *dP = 0, *eodP = 0, *theIP = 0, *theHost = 0, *atKey = 0, eType =
'\0';
177 int idNum = 0, idTLen, idSz, dLen;
178 bool badAttr =
false;
182 if (cred->
size < minLen)
183 return Fatal(einfo,
"Auth", EINVAL,
"Credentials too small.");
187 if (cred->
size > maxLen)
188 return Fatal(einfo,
"Auth", EINVAL,
"Credentials too big.");
196 if ((dLen = Decode(einfo, decKey, cred->
buffer, rrData, cred->
size)) <= 0)
205 getLID(lidBuff,
sizeof(lidBuff));
210 *parms = Encode(einfo, decKey, rrHdr, &rrResp, n);
211 return (*parms ? 1 : -1);
217 CLDBG(
"Processing " <<dLen <<
" byes");
220 CLDBG(
"eType=" <<
static_cast<int>(eType)
221 <<
" Used " <<dP-rrData->
Data <<
" left " <<eodP-dP);
223 {
Fatal(einfo,
"Authenticate", EINVAL,
"Invalid id string.");
234 myID.credslen = idSz;
break;
236 if (idP && *idP ==
'[')
237 myID.host = theIP = idP;
249 if (!atKey) badAttr =
true;
251 std::string(idP),
true);
265 {
Fatal(einfo,
"Authenticate", ENOENT,
"No identification specified.");
272 {
Fatal(einfo,
"Authenticate", EINVAL,
"Invalid attribute specification.");
281 {
if (!theHost && !theIP)
282 {
Fatal(einfo,
"Authenticate",ENOENT,
"No hostname or IP address specified.");
285 CLDBG(urName <<
' ' <<urIP <<
" or " <<urIQ <<
" must match "
286 <<(theHost ? theHost :
"?") <<
' ' <<(theIP ? theIP :
"[?]"));
288 {
if (strcmp(theIP, urIP) && strcmp(theIP, urIQ))
289 {
Fatal(einfo,
"Authenticate", EINVAL,
"IP address mismatch.");
292 }
else if (strcmp(theHost, urName))
293 {
Fatal(einfo,
"Authenticate", EINVAL,
"Hostname mismatch.");
297 CLDBG(urName <<
' ' <<urIP <<
" or " <<urIQ <<
" forwarded token from "
298 <<(theHost ? theHost :
"?") <<
' ' <<(theIP ? theIP :
"[?]"));
303 if (aProts && myID.Clonable(aProts))
312 {
if (!myID.name) myID.name = (
char *)
"nobody";}
319 {
if (!myID.grps) myID.grps = (
char *)
"nogroup";}
331 idTLen = strlen(urName)
332 + (myID.name ? strlen(myID.name)+1 : 0)
333 + (myID.vorg ? strlen(myID.vorg)+1 : 0)
334 + (myID.role ? strlen(myID.role)+1 : 0)
335 + (myID.grps ? strlen(myID.grps)+1 : 0)
336 + (myID.caps ? strlen(myID.caps)+1 : 0)
337 + (myID.endo ? strlen(myID.endo)+1 : 0)
338 + (myID.creds ? myID.credslen : 0)
339 + (myID.pident ? strlen(myID.pident)+1 : 0);
343 if (idBuff) free(idBuff);
344 idBuff = idP = (
char *)malloc(idTLen);
354 {strcpy(idP, myID.pident);
356 idP += strlen(myID.pident) + 1;
360 {memcpy(idP, myID.creds, myID.credslen);
389 "Authentication protocol id mismatch (%.4s != %.4s).",
391 return Fatal(error,
"Decode", EINVAL,
emsg);
397 return Fatal(error,
"Decode", ENOTSUP,
"Crypto type not supported.");
403 {
int knSize =
static_cast<int>(rrHdr->
knSize);
406 || knSize >= dLen || iData[knSize-1])
407 return Fatal(error,
"Decode", EINVAL,
"Invalid keyname specified.");
408 if (sssUseKN) strcpy(decKey.
Data.
Name, iData);
410 CLDBG(
"V2 client using keyname '" <<iData <<
"' dLen=" <<dLen
411 <<(sssUseKN ?
"" :
" (ignored)"));
412 iData += knSize; dLen -= knSize;
419 return Fatal(error,
"Decode", ENOENT,
"Decryption key not found.");
423 CLDBG(
"Decode keyid: " <<decKey.
Data.
ID <<
" bytes " <<dLen);
425 (
char *)rrDHdr, dLen)) <= 0)
426 return Fatal(error,
"Decode", -rc,
"Unable to decrypt credentials.");
430 genTime = ntohl(rrDHdr->GenTime);
431 if (genTime + deltaTime <= myClock())
432 return Fatal(error,
"Decode", ESTALE,
433 "Credentials expired (check for clock skew).");
449 if (urName) free(urName);
450 if (idBuff) free(idBuff);
452 if (keyTab && keyTab != ktObject)
delete keyTab;
462 const char *txt1,
const char *txt2,
463 const char *txt3,
const char *txt4)
465 std::cerr <<
"Secsss (" << epname <<
"): ";
467 if (rc>0) std::cerr <<
"; " <<
XrdSysE2T(rc);
468 if (txt2) std::cerr <<txt2;
469 if (txt3) std::cerr <<txt3;
470 if (txt4) {std::cerr <<txt4;}
471 std::cerr <<
"\n" <<std::flush;
473 return (rc ? (rc < 0 ? rc : -rc) : -1);
492 {
Fatal(einfo,
"Encode",ENOBUFS,
"Insufficient buffer space for credentials.");
499 rrDHdr->GenTime = htonl(myClock());
500 memset(rrDHdr->Pad, 0,
sizeof(rrDHdr->Pad));
504 cLen = hdrSZ + dLen + Crypto->
Overhead();
505 if (!(credP = (
char *)malloc(cLen)))
506 {
Fatal(einfo,
"Encode", ENOMEM,
"Insufficient memory for credentials.");
512 memcpy(credP, (
const void *)rrHdr, hdrSZ);
513 CLDBG(
"Encode keyid: " <<encKey.Data.ID <<
" bytes " <<cLen-hdrSZ);
514 if ((dLen = Crypto->
Encrypt(encKey.Data.Val, encKey.Data.Len, (
char *)rrDHdr,
515 dLen, credP+hdrSZ, cLen-hdrSZ)) <= 0)
516 {
Fatal(einfo,
"Encode", -dLen,
"Unable to encrypt credentials.");
522 dLen += hdrSZ; knum = encKey.Data.ID&0x7fffffff;
523 CLDBG(
"Ret " <<dLen <<
" bytes of credentials; k=" <<knum);
535 CLDBG(epn <<
": " <<etxt);
537 else eMsg(epn, rc, etxt);
546 const char *myUrlID,
const char *myIP)
565 if (myUrlID && idMap)
566 {
if ((dLen = idMap->Find(myUrlID, (
char *&)dP, myIP, dataOpts)) <= 0)
567 return Fatal(einfo,
"getCred", ESRCH,
"No loginid mapping.");
570 dLen = staticID->
RR_Data((
char *&)dP, myIP, theOpts);
589 char *lidP = 0, *bP, *idP, *eodP, idType;
590 int idSz, dLen, theOpts;
594 if (parm->
size > (
int)
sizeof(prData.
Data))
595 return Fatal(einfo,
"getCred", EINVAL,
"Invalid server response size.");
599 if ((dLen = Decode(einfo, decKey, parm->
buffer, &prData, parm->
size)) <= 0)
600 return Fatal(einfo,
"getCred", EINVAL,
"Unable to decode server response.");
604 bP = prData.
Data; eodP = dLen + (
char *)&prData;
608 return Fatal(einfo,
"getCred", EINVAL,
"Invalid id string.");
613 default:
return Fatal(einfo,
"getCred",EINVAL,
"Invalid id type.");
619 if (!lidP)
return Fatal(einfo,
"getCred", ENOENT,
"No loginid returned.");
623 if (!idMap)
return staticID->
RR_Data((
char *&)dP, myIP, dataOpts);
627 if (!myUrlID) myUrlID = lidP;
630 else theOpts = dataOpts;
631 if ((dLen = idMap->Find(lidP, (
char *&)dP, myIP, theOpts)) <= 0)
632 return Fatal(einfo,
"getCred", ESRCH,
"No loginid mapping.");
649 sssRR_DataHdr rrDataHdr;
653 const char *myIP = 0, *myUD = 0;
659 if (einfo && (errEnv=einfo->
getEnv()))
660 {
if (isMapped) myUD = errEnv->
Get(
"username");
661 if (!(myIP=errEnv->
Get(
"sockname")))
662 {
int fd = epAddr->
SockFD();
671 CLDBG(
"getCreds: " <<
static_cast<int>(Sequence)
672 <<
" ud: '" <<(myUD ? myUD :
"")
673 <<
"' ip: '" <<(myIP ? myIP :
"") <<
"'");
677 if (Sequence) dLen = getCred(einfo, rrDataHdr.P, myUD, myIP, parms);
678 else dLen = getCred(einfo, rrDataHdr.P, myUD, myIP);
683 if (keyTab->
getKey(encKey))
684 {
Fatal(einfo,
"getCredentials", ENOENT,
"Encryption key not found.");
691 memset(rrHdr.
Pad, 0,
sizeof(rrHdr.
Pad));
698 {
int k = strlen(encKey.
Data.
Name), n = (k + 8) & ~7;
700 {
Fatal(einfo,
"getCredentials", EINVAL,
"Encryption key name is too long.");
703 if (n - k > 1) memset(rrHdr.
keyName + k, 0, n - k);
704 rrHdr.
knSize =
static_cast<uint8_t
>(n);
709 return Encode(einfo, encKey, &rrHdr, rrDataHdr.P, dLen);
716char *XrdSecProtocolsss::getLID(
char *buff,
int blen)
750 if (!pP || !*pP)
return Fatal(erp,
"Init_Client", EINVAL,
751 "Client parameters missing.");
755 if (!*pP || *(pP+1) !=
'.')
return Fatal(erp,
"Init_Client", EINVAL,
756 "Encryption type missing.");
757 if (!(
Crypto = Load_Crypto(erp, *pP)))
return 0;
770 lifeTime = strtol(pP, &Colon, 10);
771 if (!lifeTime || *Colon !=
':')
return Fatal(erp,
"Init_Client", EINVAL,
772 "Credential lifetime missing.");
773 deltaTime = lifeTime; pP = Colon+1;
777 if (ktFixed || (ktObject && ktObject->
Same(pP))) keyTab = ktObject;
778 else if (*pP ==
'/' && !
stat(pP, &buf))
780 return Fatal(erp,
"Init_Client", ENOMEM,
781 "Unable to create keytab object.");
782 if (erp->
getErrInfo()) {
delete ktP;
return 0;}
783 if (!ktObject) ktObject = ktP;
785 CLDBG(
"Client keytab='" <<pP <<
"'");
786 }
else keyTab = ktObject;
789 return Fatal(erp,
"Init_Client", ENOENT,
790 "Unable to determine keytab location.");
818 static const int rfrHR = 60*60;
827 {
Fatal(erp,
"Load_Client", ENOENT,
"Unable to obtain local hostname.");
838 idMap = XrdSecsssID::getObj(aType, staticID);
846 default: idMap = 0;
break;
855 else if ( ( (kP = getenv(
"XrdSecSSSKT")) || (kP = getenv(
"XrdSecsssKT")) )
856 && *kP && !
stat(kP, &buf))
860 if (!kP && !
stat(KTPath, &buf)) kP = KTPath;
867 {
Fatal(erp,
"Load_Client", ENOMEM,
"Unable to create keytab object.");
871 {
delete ktObject, ktObject = 0;
return (
char *)0;}
872 CLDBG(
"Client keytab='" <<kP <<
"'");
893 while(CryptoTab[i].cName && strcmp(CryptoTab[i].cName, eN)) i++;
897 if (!CryptoTab[i].cName)
898 {sprintf(buff,
"Secsss: %s cryptography not supported.", eN);
899 Fatal(erp,
"Load_Crypto", EINVAL, buff);
906 sprintf(buff,
"Secsss: %s cryptography load failed; %s",eN,
XrdSysE2T(rc));
907 Fatal(erp,
"Load_Crypto", EINVAL, buff);
922 if (CryptObj && eT == CryptObj->
Type())
return CryptObj;
926 while(CryptoTab[i].cName && CryptoTab[i].cType != eT) i++;
930 if (!CryptoTab[i].cName)
931 {sprintf(buff,
"Secsss: 0x%hhx cryptography not supported.", eT);
932 Fatal(erp,
"Load_Crypto", EINVAL, buff);
939 sprintf(buff,
"Secsss: 0x%hhx cryptography load failed; %s",eT,
XrdSysE2T(rc));
940 Fatal(erp,
"Load_Crypto", EINVAL, buff);
951 const char *encName =
"bf32", *ktClient =
"", *ktServer = 0;
952 char buff[2048], parmbuff[2048], *op, *od, *eP;
953 int lifeTime = 13, rfrTime = 60*60;
955 const char *ask4Creds =
"";
959 if (parms)
strlcpy(parmbuff, parms,
sizeof(parmbuff));
970 if (parms && inParms.
GetLine())
972 {
if (!strcmp(
"-k", op) || !strcmp(
"--keyname", op))
976 if (!strcmp(
"-g", op) || !strcmp(
"--getcreds", op))
981 {sprintf(buff,
"Secsss: Missing %s parameter argument",op);
984 if (!strcmp(
"-c", op) || !strcmp(
"--clientkt", op))
986 else if (!strcmp(
"-e", op) || !strcmp(
"--encrypt", op))
988 else if (!strcmp(
"-l", op) || !strcmp(
"--lifetime", op))
989 {lifeTime = strtol(od, &eP, 10) * 60;
990 if (errno || *eP || lifeTime < 1)
991 {msg =
"Secsss: Invalid life time";
break;}
993 else if (!strcmp(
"-p", op) || !strcmp(
"--proxy", op))
994 {
int n = strlen(od) + 2;
995 aProts = (
char *)malloc(n);
997 strcpy(aProts+1, od);
999 else if (!strcmp(
"-r", op) || !strcmp(
"--rfresh", op))
1000 {rfrTime = strtol(od, &eP, 10) * 60;
1001 if (errno || *eP || rfrTime < 600)
1002 {msg =
"Secsss: Invalid refresh time";
break;}
1004 else if (!strcmp(
"-s", op) || !strcmp(
"-serverkt", op))
1006 else {sprintf(buff,
"Secsss: Invalid parameter - %s",op);
1013 if (msg) {
Fatal(erp,
"Load_Server", EINVAL, msg);
return (
char *)0;}
1017 if (!(CryptObj = Load_Crypto(erp, encName)))
return (
char *)0;
1025 deltaTime = lifeTime;
1031 {
Fatal(erp,
"Load_Server", ENOMEM,
"Unable to create keytab object.");
1036 CLDBG(
"Server keytab='" <<ktServer <<
"'");
1042 sprintf(buff,
"%c.+%s%d:%s", CryptObj->
Type(),ask4Creds,lifeTime,ktClient);
1043 CLDBG(
"client parms='" <<buff <<
"'");
1044 return strdup(buff);
1051int XrdSecProtocolsss::myClock()
1053 static const time_t baseTime = 1222183880;
1055 return static_cast<int>(time(0)-baseTime);
1062char *XrdSecProtocolsss::setID(
char *
id,
char **idP)
1065 {
int n = strlen(
id);
1066 strcpy(*idP,
id);
id = *idP; *idP = *idP + n + 1;
1096 if (getenv(
"XrdSecDEBUG")) sssDEBUG =
true;
1114 const char *hostname,
1126 "Secsss: Insufficient memory for protocol.");
1127 else {Ok = (mode ==
'c' ? prot->
Init_Client(erp, parms)
1130 if (!Ok) {prot->
Delete(); prot = 0;}
#define XrdSecPROTOIDSIZE
XrdSecBuffer XrdSecCredentials
XrdSecProtocol * XrdSecProtocolsssObject(const char mode, const char *hostname, XrdNetAddrInfo &endPoint, const char *parms, XrdOucErrInfo *erp)
XrdVERSIONINFO(XrdSecProtocolsssObject, secsss)
char * XrdSecProtocolsssInit(const char mode, const char *parms, XrdOucErrInfo *erp)
static const int XrdSecsssRR_Data_HdrLen
int emsg(int rc, char *msg)
const char * XrdSysE2T(int errcode)
virtual int Encrypt(const char *key, int keyLen, const char *src, int srcLen, char *dst, int dstLen)=0
virtual int Decrypt(const char *key, int keyLen, const char *src, int srcLen, char *dst, int dstLen)=0
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)
static int IPFormat(const struct sockaddr *sAddr, char *bP, int bL, int opts=0)
char * Get(const char *varname)
int setErrInfo(int code, const char *emsg)
static int Unpack(char **buff, const char *bend, char **data, int &dlen)
static int Pack(struct iovec **, const char *, unsigned short &buff)
char * GetToken(char **rest=0, int lowcase=0)
static bool getGID(const char *gName, gid_t &gID)
static bool getUID(const char *uName, uid_t &uID, gid_t *gID=0)
bool Add(XrdSecAttr &attr)
char * vorg
Entity's virtual organization(s)
const char * pident
Trace identifier (originator)
int credslen
Length of the 'creds' data.
XrdNetAddrInfo * addrInfo
Entity's connection details.
XrdSecEntityAttr * eaAPI
non-const API to attributes
const char * tident
Trace identifier always preset.
char prot[XrdSecPROTOIDSIZE]
Auth protocol used (e.g. krb5)
char * caps
Entity's capabilities.
char * creds
Raw entity credentials or cert.
gid_t gid
Unix gid or 0 if none.
char * grps
Entity's group name(s)
uid_t uid
Unix uid or 0 if none.
char * name
Entity's name.
char * role
Entity's role(s)
char * endorsements
Protocol specific endorsements.
char * host
Entity's host name dnr dependent.
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 void setHostName(const char *hnP)
static const int addExtra
Add v2 data.
static const int addCreds
Add v2 data plus creds.
int RR_Data(char *&dP, const char *hostIP, int dataOpts)
struct XrdSecsssKT::ktEnt::ktData Data
int Same(const char *path)
int getKey(ktEnt &ktEql, bool andKeyID=false)
static void genKey(char *Buff, int blen)
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 const char UseData
char Data[XrdSecsssRR_Data::MinDSz+16]
static const char theHost
static const char theUser
static const char theAKey
static const char theCaps
static const char theAuth
static const char theRole
static const char theName
static const char theLgid
static const char theGrps
static const char theRand
static const char theEndo
static const char theAVal
static const char theVorg
static const char theGrup
static const char theCred
char keyName[XrdSecsssKT::ktEnt::NameSZ]
static const char etBFish32