31 #if !defined(__FreeBSD__)
40 #include <sys/param.h>
43 #include "XrdVersion.hh"
63 #define XrdsssPROTOIDENT "sss"
65 #define CLDBG(x) if (sssDEBUG) std::cerr<<"sec_sss: "<<x<<'\n'<<std::flush
92 {memset(
this, 0,
sizeof(Persona));
97 bool Clonable(
const char *aTypes)
99 if (!xAuth || !name || !pident
101 int n = strlen(xAuth);
104 strcpy(aKey+1, xAuth);
105 return strstr(aTypes, aKey) != 0;
115 sssRR_DataHdr() : P(0) {}
116 ~sssRR_DataHdr() {
if (P) free(P);}
127 char *XrdSecProtocolsss::aProts = 0;
129 int XrdSecProtocolsss::deltaTime =13;
130 bool XrdSecProtocolsss::isMutual =
false;
131 bool XrdSecProtocolsss::isMapped =
false;
132 bool XrdSecProtocolsss::ktFixed =
false;
143 bool sssDEBUG =
false;
144 bool sssUseKN =
false;
163 Persona myID(&decKey);
165 char *idP, *dP, *eodP, *theIP = 0, *theHost = 0, *atKey = 0, eType;
166 int idNum = 0, idTLen, idSz, dLen;
167 bool badAttr =
false;
171 if (cred->
size < minLen)
172 return Fatal(einfo,
"Auth", EINVAL,
"Credentials too small.");
176 if (cred->
size > maxLen)
177 return Fatal(einfo,
"Auth", EINVAL,
"Credentials too big.");
185 if ((dLen = Decode(einfo, decKey, cred->
buffer, rrData, cred->
size)) <= 0)
194 getLID(lidBuff,
sizeof(lidBuff));
199 *parms = Encode(einfo, decKey, rrHdr, &rrResp, n);
200 return (*parms ? 1 : -1);
206 CLDBG(
"Processing " <<dLen <<
" byes");
209 CLDBG(
"eType=" <<
static_cast<int>(eType)
210 <<
" Used " <<dP-rrData->
Data <<
" left " <<eodP-dP);
212 {
Fatal(einfo,
"Authenticate", EINVAL,
"Invalid id string.");
223 myID.credslen = idSz;
break;
226 myID.host = theIP = idP;
238 if (!atKey) badAttr =
true;
240 std::string(idP),
true);
254 {
Fatal(einfo,
"Authenticate", ENOENT,
"No identification specified.");
261 {
Fatal(einfo,
"Authenticate", EINVAL,
"Invalid attribute specification.");
270 {
if (!theHost && !theIP)
271 {
Fatal(einfo,
"Authenticate",ENOENT,
"No hostname or IP address specified.");
274 CLDBG(urName <<
' ' <<urIP <<
" or " <<urIQ <<
" must match "
275 <<(theHost ? theHost :
"?") <<
' ' <<(theIP ? theIP :
"[?]"));
277 {
if (strcmp(theIP, urIP) && strcmp(theIP, urIQ))
278 {
Fatal(einfo,
"Authenticate", EINVAL,
"IP address mismatch.");
281 }
else if (strcmp(theHost, urName))
282 {
Fatal(einfo,
"Authenticate", EINVAL,
"Hostname mismatch.");
286 CLDBG(urName <<
' ' <<urIP <<
" or " <<urIQ <<
" forwarded token from "
287 <<(theHost ? theHost :
"?") <<
' ' <<(theIP ? theIP :
"[?]"));
292 if (aProts && myID.Clonable(aProts))
301 {
if (!myID.name) myID.name = (
char *)
"nobody";}
308 {
if (!myID.grps) myID.grps = (
char *)
"nogroup";}
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);
332 if (idBuff) free(idBuff);
333 idBuff = idP = (
char *)malloc(idTLen);
343 {strcpy(idP, myID.pident);
345 idP += strlen(myID.pident) + 1;
349 {memcpy(idP, myID.creds, myID.credslen);
378 "Authentication protocol id mismatch (%.4s != %.4s).",
380 return Fatal(error,
"Decode", EINVAL,
emsg);
386 return Fatal(error,
"Decode", ENOTSUP,
"Crypto type not supported.");
392 {
int knSize =
static_cast<int>(rrHdr->
knSize);
395 || knSize >= dLen || iData[knSize-1])
396 return Fatal(error,
"Decode", EINVAL,
"Invalid keyname specified.");
397 if (sssUseKN) strcpy(decKey.
Data.
Name, iData);
399 CLDBG(
"V2 client using keyname '" <<iData <<
"' dLen=" <<dLen
400 <<(sssUseKN ?
"" :
" (ignored)"));
401 iData += knSize; dLen -= knSize;
408 return Fatal(error,
"Decode", ENOENT,
"Decryption key not found.");
412 CLDBG(
"Decode keyid: " <<decKey.
Data.
ID <<
" bytes " <<dLen);
414 (
char *)rrDHdr, dLen)) <= 0)
415 return Fatal(error,
"Decode", -rc,
"Unable to decrypt credentials.");
419 genTime = ntohl(rrDHdr->GenTime);
420 if (genTime + deltaTime <= myClock())
421 return Fatal(error,
"Decode", ESTALE,
422 "Credentials expired (check for clock skew).");
438 if (urName) free(urName);
439 if (idBuff) free(idBuff);
441 if (keyTab && keyTab != ktObject)
delete keyTab;
451 const char *txt1,
const char *txt2,
452 const char *txt3,
const char *txt4)
454 std::cerr <<
"Secsss (" << epname <<
"): ";
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;
462 return (rc ? (rc < 0 ? rc : -rc) : -1);
481 {
Fatal(einfo,
"Encode",ENOBUFS,
"Insufficient buffer space for credentials.");
488 rrDHdr->
GenTime = htonl(myClock());
489 memset(rrDHdr->
Pad, 0,
sizeof(rrDHdr->
Pad));
493 cLen = hdrSZ + dLen + Crypto->
Overhead();
494 if (!(credP = (
char *)malloc(cLen)))
495 {
Fatal(einfo,
"Encode", ENOMEM,
"Insufficient memory for credentials.");
501 memcpy(credP, (
const void *)rrHdr, hdrSZ);
502 CLDBG(
"Encode keyid: " <<encKey.
Data.
ID <<
" bytes " <<cLen-hdrSZ);
504 dLen, credP+hdrSZ, cLen-hdrSZ)) <= 0)
505 {
Fatal(einfo,
"Encode", -dLen,
"Unable to encrypt credentials.");
511 dLen += hdrSZ; knum = encKey.
Data.
ID&0x7fffffff;
512 CLDBG(
"Ret " <<dLen <<
" bytes of credentials; k=" <<knum);
524 CLDBG(epn <<
": " <<etxt);
526 else eMsg(epn, rc, etxt);
535 const char *myUrlID,
const char *myIP)
554 if (myUrlID && idMap)
555 {
if ((dLen = idMap->Find(myUrlID, (
char *&)dP, myIP, dataOpts)) <= 0)
556 return Fatal(einfo,
"getCred", ESRCH,
"No loginid mapping.");
559 dLen = staticID->
RR_Data((
char *&)dP, myIP, theOpts);
578 char *lidP = 0, *bP, *idP, *eodP, idType;
579 int idSz, dLen, theOpts;
583 if (parm->
size > (
int)
sizeof(prData.
Data))
584 return Fatal(einfo,
"getCred", EINVAL,
"Invalid server response size.");
588 if ((dLen = Decode(einfo, decKey, parm->
buffer, &prData, parm->
size)) <= 0)
589 return Fatal(einfo,
"getCred", EINVAL,
"Unable to decode server response.");
593 bP = prData.
Data; eodP = dLen + (
char *)&prData;
597 return Fatal(einfo,
"getCred", EINVAL,
"Invalid id string.");
602 default:
return Fatal(einfo,
"getCred",EINVAL,
"Invalid id type.");
608 if (!lidP)
return Fatal(einfo,
"getCred", ENOENT,
"No loginid returned.");
612 if (!idMap)
return staticID->
RR_Data((
char *&)dP, myIP, dataOpts);
616 if (!myUrlID) myUrlID = lidP;
619 else theOpts = dataOpts;
620 if ((dLen = idMap->Find(lidP, (
char *&)dP, myIP, theOpts)) <= 0)
621 return Fatal(einfo,
"getCred", ESRCH,
"No loginid mapping.");
638 sssRR_DataHdr rrDataHdr;
642 const char *myIP = 0, *myUD = 0;
648 if (einfo && (errEnv=einfo->
getEnv()))
649 {
if (isMapped) myUD = errEnv->
Get(
"username");
650 if (!(myIP=errEnv->
Get(
"sockname")))
651 {
int fd = epAddr->
SockFD();
660 CLDBG(
"getCreds: " <<
static_cast<int>(Sequence)
661 <<
" ud: '" <<(myUD ? myUD :
"")
662 <<
"' ip: '" <<(myIP ? myIP :
"") <<
"'");
666 if (Sequence) dLen = getCred(einfo, rrDataHdr.P, myUD, myIP, parms);
667 else dLen = getCred(einfo, rrDataHdr.P, myUD, myIP);
672 if (keyTab->
getKey(encKey))
673 {
Fatal(einfo,
"getCredentials", ENOENT,
"Encryption key not found.");
680 memset(rrHdr.
Pad, 0,
sizeof(rrHdr.
Pad));
687 {
int k = strlen(encKey.
Data.
Name), n = (k + 8) & ~7;
689 if (n - k > 1) memset(rrHdr.
keyName + k, 0, n - k);
690 rrHdr.
knSize =
static_cast<uint8_t
>(n);
695 return Encode(einfo, encKey, &rrHdr, rrDataHdr.P, dLen);
702 char *XrdSecProtocolsss::getLID(
char *buff,
int blen)
736 if (!pP || !*pP)
return Fatal(erp,
"Init_Client", EINVAL,
737 "Client parameters missing.");
741 if (!*pP || *(pP+1) !=
'.')
return Fatal(erp,
"Init_Client", EINVAL,
742 "Encryption type missing.");
743 if (!(
Crypto = Load_Crypto(erp, *pP)))
return 0;
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;
763 if (ktFixed || (ktObject && ktObject->
Same(pP))) keyTab = ktObject;
764 else if (*pP ==
'/' && !
stat(pP, &buf))
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;
771 CLDBG(
"Client keytab='" <<pP <<
"'");
772 }
else keyTab = ktObject;
775 return Fatal(erp,
"Init_Client", ENOENT,
776 "Unable to determine keytab location.");
804 static const int rfrHR = 60*60;
813 {
Fatal(erp,
"Load_Client", ENOENT,
"Unable to obtain local hostname.");
824 idMap = XrdSecsssID::getObj(aType, staticID);
832 default: idMap = 0;
break;
841 else if ( ( (kP = getenv(
"XrdSecSSSKT")) || (kP = getenv(
"XrdSecsssKT")) )
842 && *kP && !
stat(kP, &buf))
846 if (!kP && !
stat(KTPath, &buf)) kP = KTPath;
853 {
Fatal(erp,
"Load_Client", ENOMEM,
"Unable to create keytab object.");
857 {
delete ktObject, ktObject = 0;
return (
char *)0;}
858 CLDBG(
"Client keytab='" <<kP <<
"'");
879 while(CryptoTab[i].cName && strcmp(CryptoTab[i].cName, eN)) i++;
883 if (!CryptoTab[i].cName)
884 {sprintf(buff,
"Secsss: %s cryptography not supported.", eN);
885 Fatal(erp,
"Load_Crypto", EINVAL, buff);
892 sprintf(buff,
"Secsss: %s cryptography load failed; %s",eN,
XrdSysE2T(rc));
893 Fatal(erp,
"Load_Crypto", EINVAL, buff);
908 if (CryptObj && eT == CryptObj->
Type())
return CryptObj;
912 while(CryptoTab[i].cName && CryptoTab[i].cType != eT) i++;
916 if (!CryptoTab[i].cName)
917 {sprintf(buff,
"Secsss: 0x%hhx cryptography not supported.", eT);
918 Fatal(erp,
"Load_Crypto", EINVAL, buff);
925 sprintf(buff,
"Secsss: 0x%hhx cryptography load failed; %s",eT,
XrdSysE2T(rc));
926 Fatal(erp,
"Load_Crypto", EINVAL, buff);
937 const char *encName =
"bf32", *ktClient =
"", *ktServer = 0;
938 char buff[2048], parmbuff[2048], *op, *od, *eP;
939 int lifeTime = 13, rfrTime = 60*60;
941 const char *ask4Creds =
"";
945 if (parms)
strlcpy(parmbuff, parms,
sizeof(parmbuff));
956 if (parms && inParms.
GetLine())
958 {
if (!strcmp(
"-k", op) || !strcmp(
"--keyname", op))
962 if (!strcmp(
"-g", op) || !strcmp(
"--getcreds", op))
967 {sprintf(buff,
"Secsss: Missing %s parameter argument",op);
970 if (!strcmp(
"-c", op) || !strcmp(
"--clientkt", op))
972 else if (!strcmp(
"-e", op) || !strcmp(
"--encrypt", op))
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;}
979 else if (!strcmp(
"-p", op) || !strcmp(
"--proxy", op))
980 {
int n = strlen(od) + 2;
981 aProts = (
char *)malloc(n);
983 strcpy(aProts+1, od);
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;}
990 else if (!strcmp(
"-s", op) || !strcmp(
"-serverkt", op))
992 else {sprintf(buff,
"Secsss: Invalid parameter - %s",op);
999 if (msg) {
Fatal(erp,
"Load_Server", EINVAL, msg);
return (
char *)0;}
1003 if (!(CryptObj = Load_Crypto(erp, encName)))
return (
char *)0;
1011 deltaTime = lifeTime;
1017 {
Fatal(erp,
"Load_Server", ENOMEM,
"Unable to create keytab object.");
1022 CLDBG(
"Server keytab='" <<ktServer <<
"'");
1028 sprintf(buff,
"%c.+%s%d:%s", CryptObj->
Type(),ask4Creds,lifeTime,ktClient);
1029 CLDBG(
"client parms='" <<buff <<
"'");
1030 return strdup(buff);
1037 int XrdSecProtocolsss::myClock()
1039 static const time_t baseTime = 1222183880;
1041 return static_cast<int>(time(0)-baseTime);
1048 char *XrdSecProtocolsss::setID(
char *
id,
char **idP)
1051 {
int n = strlen(
id);
1052 strcpy(*idP,
id);
id = *idP; *idP = *idP + n + 1;
1082 if (getenv(
"XrdSecDEBUG")) sssDEBUG =
true;
1100 const char *hostname,
1112 "Secsss: Insufficient memory for protocol.");
1113 else {Ok = (mode ==
'c' ? prot->
Init_Client(erp, parms)
1116 if (!Ok) {prot->
Delete(); prot = 0;}
int stat(const char *path, struct stat *buf)
#define XrdSecPROTOIDSIZE
XrdSecBuffer XrdSecCredentials
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
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 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 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 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