31 #define __STDC_FORMAT_MACROS 1
49 #include <arpa/inet.h>
51 #include <sys/types.h>
56 #include "XrdVersion.hh"
90 if (!erp) std::cerr <<
"Secztn: " <<
eMsg <<
"\n" <<std::flush;
91 else {
const char *eVec[2] = {(hdr ?
"Secztn: " :
""),
eMsg};
101 inline uint64_t monotonic_time() {
103 #ifdef CLOCK_MONOTONIC_COARSE
104 clock_gettime(CLOCK_MONOTONIC_COARSE, &tp);
106 clock_gettime(CLOCK_MONOTONIC, &tp);
108 return tp.tv_sec + (tp.tv_nsec >= 500000000);
116 bool tokenlib =
true;
126 char *sth_piName = 0;
133 "ztn.tokenlib", piName);
142 {sth_piName = strdup(piName);
159 int MaxTokSize = 4096;
163 static const uint64_t srvVNum = 0x00000000000000ffULL;
164 static const uint64_t useFirst = 0x0000000000000100ULL;
165 static const uint64_t useLast = 0x0000000000000200ULL;
166 static const uint64_t srvRTOK = 0x0000000000000800ULL;
175 extern bool isJWT(
const char *);
207 maxTSize(MaxTokSize), cont(false),
208 rtGet(false), verJWT(false)
230 static const char SndAI =
'S';
231 static const char IsTkn =
'T';
233 void Fill(
char opc) {strcpy(
id,
"ztn"); ver =
ztnVersion;
234 opr = opc; rsvd[0] = rsvd[1] = 0;
245 std::vector<XrdOucString> &Vec,
bool &isbad);
251 const char *Strip(
const char *bTok,
int &sz);
272 tokName(
""), ztnInfo(0), maxTSize(0),
273 cont(false), rtGet(false), verJWT(false)
283 if (!parms || !(*parms))
284 {
Fatal(erp,
"Client parameters not specified.", EINVAL);
292 ztnInfo = strtoll(parms, &endP, 10);
294 {
Fatal(erp,
"Malformed client parameters.", EINVAL);
301 maxTSize = strtol(parms, &endP, 10);
302 if (maxTSize <= 0 || *endP !=
':')
303 {
Fatal(erp,
"Invalid or missing maxtsz parameter.", EINVAL);
318 std::vector<XrdOucString> &Vec,
322 const char *aTok, *bTok;
327 for (
int i = 0; i < (int)Vec.size(); i++)
328 {tokName = Vec[i].c_str();
330 if (Vec[i].beginswith(
'/') == 1)
331 {
char tokPath[MAXPATHLEN+8];
332 snprintf(tokPath,
sizeof(tokPath), tokName,
int(geteuid()));
333 resp = readToken(erp, tokPath, isbad);
334 if (resp || isbad)
return resp;
338 if (!(aTok = getenv(Vec[i].c_str())) || !*(aTok))
continue;
340 if (Vec[i].endswith(
"_DIR"))
341 {
char tokPath[MAXPATHLEN+8];
342 snprintf(tokPath,
sizeof(tokPath),
"%s/bt_u%d",aTok,
int(geteuid()));
343 resp = readToken(erp, tokPath, isbad);
344 if (resp || isbad)
return resp;
348 if (Vec[i].endswith(
"_FILE"))
349 {
if ((resp = readToken(erp, aTok, isbad)) || isbad)
return resp;
353 if ((bTok = Strip(aTok, sz)))
return retToken(erp, bTok, sz);
358 char *ccn = (erp && erp->
getEnv()) ? erp->
getEnv()->
Get(
"xrd.ztn") : 0;
361 resp = readToken(erp, ccn, isbad);
362 if (resp || isbad)
return resp;
379 static const char *dfltLoc[] = {
"BEARER_TOKEN",
"BEARER_TOKEN_FILE",
380 "XDG_RUNTIME_DIR",
"/tmp/bt_u%d"};
381 static const char **dfltLocEnd = dfltLoc +
sizeof(dfltLoc)/
sizeof(
char*);
382 static std::vector<XrdOucString> dfltVec(dfltLoc, dfltLocEnd);
389 if (cont)
return getToken(error, parms);
393 resp = findToken(error, dfltVec, isbad);
394 if (resp || isbad)
return resp;
400 {TokenHdr *tHdr = (TokenHdr *)malloc(
sizeof(TokenHdr));
401 tHdr->Fill(TokenHdr::SndAI);
405 Fatal(error,
"No token found; runtime fetch disallowed.", ENOPROTOOPT);
418 return Fatal(erp,
"Realtime token creation not supported.", ENOTSUP);
426 const char *path,
int rc)
431 mVec[0] =
"Secztn: Unable to find token via ";
437 if (rc == EPERM) mVec[k++] =
" because of excessive permissions";
441 else {
for (
int k = 0; k < 6; k++) std::cerr <<mVec[k];
442 std::cerr <<
"\n" <<std::flush;
453 const char *path,
bool &isbad)
458 int rdLen, sz, tokFD;
467 {
if (errno != ENOENT)
return readFail(erp, path, errno);
474 if (
Stat.st_size > maxTSize)
return readFail(erp, path, EMSGSIZE);
475 buff = (
char *)alloca(
Stat.st_size+1);
479 if ((tokFD =
open(path, O_RDONLY)) < 0)
480 return readFail(erp, path, errno);
484 if ((rdLen =
read(tokFD, buff,
Stat.st_size)) !=
Stat.st_size)
485 {
int rc = (rdLen < 0 ? errno : EIO);
487 return readFail(erp, path, rc);
493 buff[
Stat.st_size] = 0;
497 if (!(bTok = Strip(buff, sz)))
504 if (
Stat.st_mode & (S_IRWXG | S_IRWXO))
return readFail(erp, path, EPERM);
508 return retToken(erp, bTok, sz);
516 const char *tkn,
int tsz)
519 int rspLen =
sizeof(TokenResp) + tsz + 1;
523 if (tsz >= maxTSize)
return Fatal(erp,
"Token is too big", EMSGSIZE);
531 tResp = (TokenResp *)malloc(rspLen);
533 {
Fatal(erp,
"Insufficient memory.", ENOMEM);
539 tResp->hdr.Fill(TokenHdr::IsTkn);
540 tResp->len = htons(tsz+1);
541 memcpy(tResp->tkn, tkn, tsz);
542 *((tResp->tkn)+tsz) = 0;
553 const char *XrdSecProtocolztn::Strip(
const char *bTok,
int &sz)
555 int j, k, n = strlen(bTok);
563 for (j = 0; j < n; j++) if (!isspace(static_cast<int>(bTok[j])))
break;
567 if (j >= n)
return 0;
571 for (k = n-1; k > j; k--)
if (!isspace(
static_cast<int>(bTok[k])))
break;
575 if (k <= j)
return 0;
594 static const int pfxLen =
sizeof(TokenHdr) +
sizeof(uint16_t);
600 if (cred->
size < (
int)
sizeof(TokenHdr) || !cred->
buffer)
601 {
Fatal(erp,
"Invalid ztn credentials", EINVAL,
false);
604 tResp = (TokenResp *)cred->
buffer;
608 if (strcmp(tResp->hdr.id,
"ztn"))
610 snprintf(msg,
sizeof(msg),
611 "Authentication protocol id mismatch ('ztn' != '%.4s').",
613 Fatal(erp, msg, EINVAL,
false);
619 if (tResp->hdr.opr == TokenHdr::SndAI)
return SendAI(erp, parms);
623 if (tResp->hdr.opr != TokenHdr::IsTkn)
624 {
Fatal(erp,
"Invalid ztn response code", EINVAL,
false);
630 const char *isBad = 0;
631 int tLen = ntohs(tResp->len);
633 if (tResp->hdr.ver !=
ztnVersion) isBad =
"version mismatch";
634 else if (tLen < 1) isBad =
"token length < 1";
635 else if (pfxLen + tLen > cred->
size) isBad =
"respdata > credsize";
636 else if (!(tResp->tkn[0])) isBad =
"null token";
637 else if (*(tResp->tkn+(tLen-1))) isBad =
"missing null byte";
641 snprintf(eText,
sizeof(eText),
"'ztn' token malformed; %s", isBad);
642 Fatal(erp, eText, EINVAL,
false);
650 bool validated =
false;
652 if (tokenlib && sthP->
Validate(tResp->tkn, msgRC, (expiry ? &eTime : 0), &
Entity))
654 {
if (eTime < 0 && expiry > 0)
655 {
Fatal(erp,
"'ztn' token expiry missing", EINVAL,
false);
658 if ((monotonic_time() - eTime) <= 0)
659 {
Fatal(erp,
"'ztn' token expired", EINVAL,
false);
665 if (!tokenlib || validated)
673 Fatal(erp,
"'ztn' bad alloc", ENOMEM,
false);
691 Fatal(erp,
"Authorized issuer request not supported", ENOTSUP);
708 static char nilstr = 0;
714 if (mode ==
'c')
return &nilstr;
718 if (!parms || !(*parms))
720 if (!getLinkage(erp, accPlugin.
c_str()))
return 0;
721 snprintf(buff,
sizeof(buff),
"TLS:%" PRIu64
":%d:",
opts, MaxTokSize);
727 std::vector<XrdOucString> useVec;
740 {
if (!strcmp(val,
"-maxsz"))
742 {
Fatal(erp,
"-maxsz argument missing", EINVAL);
745 MaxTokSize = strtol(val, &endP, 10);
746 if (*endP ==
'k' || *endP ==
'K')
747 {MaxTokSize *= 1024; endP++;}
748 if (MaxTokSize <= 0 || MaxTokSize > 524288 || *endP)
749 {
Fatal(erp,
"-maxsz argument is invalid", EINVAL);
753 else if (!strcmp(val,
"-expiry"))
755 {
Fatal(erp,
"-expiry argument missing", EINVAL);
758 if (strcmp(val,
"ignore")) expiry = 0;
759 else if (strcmp(val,
"optional")) expiry = -1;
760 else if (strcmp(val,
"required")) expiry = 1;
761 else {
Fatal(erp,
"-expiry argument invalid", EINVAL);
766 else if (!strcmp(val,
"-tokenlib"))
768 {
Fatal(erp,
"-acclib plugin path missing", EINVAL);
771 if (strcmp(val,
"none"))
779 else {
XrdOucString eTxt(
"Invalid parameter - "); eTxt += val;
790 if (tokenlib && !getLinkage(erp, accPlugin.
c_str()))
return 0;
795 snprintf(buff,
sizeof(buff),
"TLS:%" PRIu64
":%d:",
opts, MaxTokSize);
807 const char *hostname,
817 {
Fatal(erp,
"security protocol 'ztn' disallowed for non-TLS connections.",
827 if (aOK)
return protP;
841 snprintf(msg,
sizeof(msg),
"ztn required plugin (%s) has not been loaded!",
843 Fatal(erp, msg, EIDRM,
false);
851 Fatal(erp,
"insufficient memory for protocol.", ENOMEM,
false);
void Fatal(const char *op, const char *target)
int stat(const char *path, struct stat *buf)
int open(const char *path, int oflag,...)
ssize_t read(int fildes, void *buf, size_t nbyte)
XrdSecBuffer XrdSecCredentials
XrdSecProtocol * XrdSecProtocolztnObject(const char mode, const char *hostname, XrdNetAddrInfo &endPoint, const char *parms, XrdOucErrInfo *erp)
XrdVERSIONINFO(XrdSecProtocolztnObject, secztn)
char * XrdSecProtocolztnInit(const char mode, const char *parms, XrdOucErrInfo *erp)
const char * XrdSysE2T(int errcode)
char * Get(const char *varname)
int setErrInfo(int code, const char *emsg)
const char * c_str() const
char * GetToken(char **rest=0, int lowcase=0)
virtual bool Validate(const char *token, std::string &emsg, long long *expT=0, XrdSecEntity *entP=0)=0
int credslen
Length of the 'creds' data.
XrdNetAddrInfo * addrInfo
Entity's connection details.
char * creds
Raw entity credentials or cert.
char * name
Entity's name.
char * host
Entity's host name dnr dependent.
int Authenticate(XrdSecCredentials *cred, XrdSecParameters **parms, XrdOucErrInfo *einfo=0)
bool needTLS()
Check if this protocol requires TLS to properly function.
XrdSecProtocolztn(const char *hname, XrdNetAddrInfo &endPoint, XrdSciTokensHelper *sthp)
static const int ztnVersion
XrdSecCredentials * getCredentials(XrdSecParameters *parms, XrdOucErrInfo *einfo=0)
void Delete()
Delete the protocol object. DO NOT use C++ delete() on this object.
XrdSecProtocolztn(const char *parms, XrdOucErrInfo *erp, bool &aOK)
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.