XRootD
XrdSecProtocolztn.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 z t n . c c */
4 /* */
5 /* (c) 2020 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 #define __STDC_FORMAT_MACROS 1
32 
33 #include <cctype>
34 #include <cerrno>
35 #include <fcntl.h>
36 #include <cinttypes>
37 #include <iostream>
38 #include <cstdint>
39 #include <cstdio>
40 #include <cstdlib>
41 #include <cstring>
42 #include <ctime>
43 #include <vector>
44 
45 #ifndef __FreeBSD__
46 #include <alloca.h>
47 #endif
48 
49 #include <arpa/inet.h>
50 #include <sys/stat.h>
51 #include <sys/types.h>
52 #include <sys/uio.h>
53 #include <strings.h>
54 #include <unistd.h>
55 
56 #include "XrdVersion.hh"
57 
58 #include "XrdNet/XrdNetAddrInfo.hh"
59 #include "XrdOuc/XrdOucEnv.hh"
60 #include "XrdOuc/XrdOucErrInfo.hh"
62 #include "XrdOuc/XrdOucString.hh"
65 #include "XrdSys/XrdSysE2T.hh"
66 #include "XrdSys/XrdSysHeaders.hh"
68 
69 #ifndef EAUTH
70 #define EAUTH EBADE
71 #endif
72 /******************************************************************************/
73 /* V e r s i o n I n f o r m a t i o n */
74 /******************************************************************************/
75 
77 
78 /******************************************************************************/
79 /* L o c a l F u n c t i o n s */
80 /******************************************************************************/
81 /******************************************************************************/
82 /* F a t a l */
83 /******************************************************************************/
84 
85 namespace
86 {
87 XrdSecCredentials *Fatal(XrdOucErrInfo *erp, const char *eMsg, int rc,
88  bool hdr=true)
89 {
90  if (!erp) std::cerr <<"Secztn: " <<eMsg <<"\n" <<std::flush;
91  else {const char *eVec[2] = {(hdr ? "Secztn: " : ""), eMsg};
92  erp->setErrInfo(rc, eVec, 2);
93  }
94  return 0;
95 }
96 
97 /******************************************************************************/
98 /* m o n o t o n i c _ t i m e */
99 /******************************************************************************/
100 
101 inline uint64_t monotonic_time() {
102  struct timespec tp;
103 #ifdef CLOCK_MONOTONIC_COARSE
104  clock_gettime(CLOCK_MONOTONIC_COARSE, &tp);
105 #else
106  clock_gettime(CLOCK_MONOTONIC, &tp);
107 #endif
108  return tp.tv_sec + (tp.tv_nsec >= 500000000);
109 }
110 
111 /******************************************************************************/
112 /* G l o b a l S t a t i c D a t a */
113 /******************************************************************************/
114 
115 int expiry = 1;
116 bool tokenlib = true;
117 }
118 
119 /******************************************************************************/
120 /* g e t L i n k a g e */
121 /******************************************************************************/
122 
123 namespace
124 {
125  XrdSciTokensHelper **sth_Linkage = 0;
126  char *sth_piName = 0;
127 
128 bool getLinkage(XrdOucErrInfo *erp, const char *piName)
129 {
130  char eMsgBuff[2048];
131  XrdVersionInfo *myVer = &XrdVERSIONINFOVAR(XrdSecProtocolztnObject);
132  XrdOucPinLoader myLib(eMsgBuff, sizeof(eMsgBuff), myVer,
133  "ztn.tokenlib", piName);
134 
135 // Get the address of the pointer to the helper we need
136 //
137  sth_Linkage = (XrdSciTokensHelper **)(myLib.Resolve("SciTokensHelper"));
138 
139 // If we succeeded, record the name of the plugin and return success
140 //
141  if (sth_Linkage)
142  {sth_piName = strdup(piName);
143  return true;
144  }
145 
146 // We failed to find this for one reason or another
147 //
148  erp->setErrInfo(ESRCH, eMsgBuff);
149  return false;
150  }
151 }
152 
153 /******************************************************************************/
154 /* L o c a l D e f i n i t i o n s */
155 /******************************************************************************/
156 
157 namespace
158 {
159 int MaxTokSize = 4096;
160 
161 // Option flags
162 //
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;
167 }
168 
169 /******************************************************************************/
170 /* E x t e r n a l L i n k a g e s */
171 /******************************************************************************/
172 
173 namespace XrdSecztn
174 {
175 extern bool isJWT(const char *);
176 }
177 
178 /******************************************************************************/
179 /* X r d S e c P r o t o c o l z t n C l a s s */
180 /******************************************************************************/
181 
183 {
184 public:
185 
186  int Authenticate (XrdSecCredentials *cred,
187  XrdSecParameters **parms,
188  XrdOucErrInfo *einfo=0);
189 
190  void Delete() {delete this;}
191 
193  XrdOucErrInfo *einfo=0);
194 
195  bool needTLS() {return true;}
196 
197 // Client-side constructor
198 //
199  XrdSecProtocolztn(const char *parms, XrdOucErrInfo *erp, bool &aOK);
200 
201 
202 // Server-side constructor
203 //
204  XrdSecProtocolztn(const char *hname, XrdNetAddrInfo &endPoint,
205  XrdSciTokensHelper *sthp)
206  : XrdSecProtocol("ztn"), sthP(sthp), tokName(""),
207  maxTSize(MaxTokSize), cont(false),
208  rtGet(false), verJWT(false)
209  {Entity.host = strdup(hname);
210  Entity.name = strdup("anon");
211  Entity.addrInfo = &endPoint;
212  }
213 
215  if (Entity.name) free(Entity.name);
216  if (Entity.creds)free(Entity.creds);
217  } // via Delete()
218 
219 static const int ztnVersion = 0;
220 
221 private:
222 
223 
224 struct TokenHdr
225  {char id[4];
226  char ver;
227  char opr;
228  char rsvd[2]; // Reserved bytes (note struct is 8 bytes long)
229 
230  static const char SndAI = 'S';
231  static const char IsTkn = 'T';
232 
233  void Fill(char opc) {strcpy(id, "ztn"); ver = ztnVersion;
234  opr = opc; rsvd[0] = rsvd[1] = 0;
235  }
236  };
237 
238 struct TokenResp
239  {TokenHdr hdr;
240  uint16_t len;
241  char tkn[1]; // Sized to actual token length
242  };
243 
244 XrdSecCredentials *findToken(XrdOucErrInfo *erp,
245  std::vector<XrdOucString> &Vec, bool &isbad);
246 XrdSecCredentials *getToken(XrdOucErrInfo *erp, XrdSecParameters *parms);
247 XrdSecCredentials *readFail(XrdOucErrInfo *erp, const char *path, int rc);
248 XrdSecCredentials *readToken(XrdOucErrInfo *erp, const char *path, bool &isbad);
249 XrdSecCredentials *retToken(XrdOucErrInfo *erp, const char *tkn, int tsz);
250 int SendAI(XrdOucErrInfo *erp, XrdSecParameters **parms);
251 const char *Strip(const char *bTok, int &sz);
252 
253 XrdSciTokensHelper *sthP;
254 const char *tokName;
255 uint64_t ztnInfo;
256 int maxTSize;
257 bool cont;
258 bool rtGet;
259 bool verJWT;
260 };
261 
262 /******************************************************************************/
263 /* C l i e n t O r i e n t e d F u n c t i o n s */
264 /******************************************************************************/
265 /******************************************************************************/
266 /* C o n s t r u c t o r */
267 /******************************************************************************/
268 
270  bool &aOK)
271  : XrdSecProtocol("ztn"), sthP(0),
272  tokName(""), ztnInfo(0), maxTSize(0),
273  cont(false), rtGet(false), verJWT(false)
274 {
275  char *endP;
276 
277 // Assume we will fail
278 //
279  aOK = false;
280 
281 // If there are no parameters then fail as the server must supply them
282 //
283  if (!parms || !(*parms))
284  {Fatal(erp, "Client parameters not specified.", EINVAL);
285  return;
286  }
287 
288 // Server supplied parms: <opts+ver>:<maxtsz>:
289 
290 // The first parameter is the options and version number.
291 //
292  ztnInfo = strtoll(parms, &endP, 10);
293  if (*endP != ':')
294  {Fatal(erp, "Malformed client parameters.", EINVAL);
295  return;
296  }
297  parms = endP+1;
298 
299 // The second parameter is the maximum token size
300 //
301  maxTSize = strtol(parms, &endP, 10);
302  if (maxTSize <= 0 || *endP != ':')
303  {Fatal(erp, "Invalid or missing maxtsz parameter.", EINVAL);
304  return;
305  }
306  endP++;
307 
308 // All done here
309 //
310  aOK = true;
311 }
312 
313 /******************************************************************************/
314 /* Private: f i n d T o k e n */
315 /******************************************************************************/
316 
317 XrdSecCredentials *XrdSecProtocolztn::findToken(XrdOucErrInfo *erp,
318  std::vector<XrdOucString> &Vec,
319  bool &isbad)
320 {
321  XrdSecCredentials *resp;
322  const char *aTok, *bTok;
323  int sz;
324 
325 // Look through all of the possible envars
326 //
327  for (int i = 0; i < (int)Vec.size(); i++)
328  {tokName = Vec[i].c_str();
329 
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;
335  continue;
336  }
337 
338  if (!(aTok = getenv(Vec[i].c_str())) || !*(aTok)) continue;
339 
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;
345  continue;
346  }
347 
348  if (Vec[i].endswith("_FILE"))
349  {if ((resp = readToken(erp, aTok, isbad)) || isbad) return resp;
350  continue;
351  }
352 
353  if ((bTok = Strip(aTok, sz))) return retToken(erp, bTok, sz);
354  }
355 
356 // We support passing the credential cache path via Url parameter
357 //
358  char *ccn = (erp && erp->getEnv()) ? erp->getEnv()->Get("xrd.ztn") : 0;
359  if (ccn)
360  {
361  resp = readToken(erp, ccn, isbad);
362  if (resp || isbad) return resp;
363  }
364 
365 // Look through all of the possible envars
366 // Nothing found
367 //
368  isbad = false;
369  return 0;
370 }
371 
372 /******************************************************************************/
373 /* g e t C r e d e n t i a l s */
374 /******************************************************************************/
375 
377  XrdOucErrInfo *error)
378 {
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);
383 
384  XrdSecCredentials *resp;
385  bool isbad;
386 
387 // If this is a continuation, then handle as such
388 //
389  if (cont) return getToken(error, parms);
390 
391 // Handle the default search
392 //
393  resp = findToken(error, dfltVec, isbad);
394  if (resp || isbad) return resp;
395 
396 // We do not have a envar value then ask the server for a list of
397 // token issuers so we can get one, if allowed. Otherwise, it's an error.
398 //
399  if (rtGet)
400  {TokenHdr *tHdr = (TokenHdr *)malloc(sizeof(TokenHdr));
401  tHdr->Fill(TokenHdr::SndAI);
402  cont = true;
403  return new XrdSecCredentials((char *)tHdr, sizeof(TokenHdr));
404  }
405  Fatal(error, "No token found; runtime fetch disallowed.", ENOPROTOOPT);
406  return 0;
407 }
408 
409 /******************************************************************************/
410 /* Private: g e t T o k e n */
411 /******************************************************************************/
412 
413 XrdSecCredentials *XrdSecProtocolztn::getToken(XrdOucErrInfo *erp,
414  XrdSecParameters *parms)
415 {
416 // We currently do not support dynamic token creation
417 //
418  return Fatal(erp, "Realtime token creation not supported.", ENOTSUP);
419 }
420 
421 /******************************************************************************/
422 /* Private: r e a d F a i l */
423 /******************************************************************************/
424 
425 XrdSecCredentials *XrdSecProtocolztn::readFail(XrdOucErrInfo *erp,
426  const char *path, int rc)
427 {
428  const char *mVec[7];
429  int k = 6;
430 
431  mVec[0] = "Secztn: Unable to find token via ";
432  mVec[1] = tokName;
433  mVec[2] = "=";
434  mVec[3] = path;
435  mVec[4] = "; ";
436  mVec[5] = XrdSysE2T(rc);
437  if (rc == EPERM) mVec[k++] = " because of excessive permissions";
438 
439 
440  if (erp) erp->setErrInfo(rc, mVec, k);
441  else {for (int k = 0; k < 6; k++) std::cerr <<mVec[k];
442  std::cerr <<"\n" <<std::flush;
443  }
444 
445  return 0;
446 }
447 
448 /******************************************************************************/
449 /* Private: r e a d T o k e n */
450 /******************************************************************************/
451 
452 XrdSecCredentials *XrdSecProtocolztn::readToken(XrdOucErrInfo *erp,
453  const char *path, bool &isbad)
454 {
455  struct stat Stat;
456  const char *bTok;
457  char *buff;
458  int rdLen, sz, tokFD;
459 
460 // Be pessimistic
461 //
462  isbad = true;
463 
464 // Get the size of the file
465 //
466  if (stat(path, &Stat))
467  {if (errno != ENOENT) return readFail(erp, path, errno);
468  isbad = false;
469  return 0;
470  }
471 
472 // Make sure token is not too big
473 //
474  if (Stat.st_size > maxTSize) return readFail(erp, path, EMSGSIZE);
475  buff = (char *)alloca(Stat.st_size+1);
476 
477 // Open the token file
478 //
479  if ((tokFD = open(path, O_RDONLY)) < 0)
480  return readFail(erp, path, errno);
481 
482 // Read in the token
483 //
484  if ((rdLen = read(tokFD, buff, Stat.st_size)) != Stat.st_size)
485  {int rc = (rdLen < 0 ? errno : EIO);
486  close(tokFD);
487  return readFail(erp, path, rc);
488  }
489  close(tokFD);
490 
491 // Make sure the token ends with a null byte
492 //
493  buff[Stat.st_size] = 0;
494 
495 // Strip the token
496 //
497  if (!(bTok = Strip(buff, sz)))
498  {isbad = false;
499  return 0;
500  }
501 
502 // Make sure the file is not accessible to anyone but the owner
503 //
504  if (Stat.st_mode & (S_IRWXG | S_IRWXO)) return readFail(erp, path, EPERM);
505 
506 // Return response
507 //
508  return retToken(erp, bTok, sz);
509 }
510 
511 /******************************************************************************/
512 /* Private: r e t T o k e n */
513 /******************************************************************************/
514 
515 XrdSecCredentials *XrdSecProtocolztn::retToken(XrdOucErrInfo *erp,
516  const char *tkn, int tsz)
517 {
518  TokenResp *tResp;
519  int rspLen = sizeof(TokenResp) + tsz + 1;
520 
521 // Make sure token is not too big
522 //
523  if (tsz >= maxTSize) return Fatal(erp, "Token is too big", EMSGSIZE);
524 
525 // Verify that this is actually a JWT if so wanted
526 //
527  if (verJWT && !XrdSecztn::isJWT(tkn)) return 0;
528 
529 // Get sufficient storage to assemble the full response
530 //
531  tResp = (TokenResp *)malloc(rspLen);
532  if (!tResp)
533  {Fatal(erp, "Insufficient memory.", ENOMEM);
534  return 0;
535  }
536 
537 // Fill out the response
538 //
539  tResp->hdr.Fill(TokenHdr::IsTkn);
540  tResp->len = htons(tsz+1);
541  memcpy(tResp->tkn, tkn, tsz);
542  *((tResp->tkn)+tsz) = 0;
543 
544 // Now return it
545 //
546  return new XrdSecCredentials((char *)tResp, rspLen);
547 }
548 
549 /******************************************************************************/
550 /* Private: S t r i p */
551 /******************************************************************************/
552 
553 const char *XrdSecProtocolztn::Strip(const char *bTok, int &sz)
554 {
555  int j, k, n = strlen(bTok);
556 
557 // Make sure we have at least one character here
558 //
559  if (!n) return 0;
560 
561 // Find first non-whitespace character
562 //
563  for (j = 0; j < n; j++) if (!isspace(static_cast<int>(bTok[j]))) break;
564 
565 // Make sure we have at least one character
566 //
567  if (j >= n) return 0;
568 
569 // Find last non-whitespace character
570 //
571  for (k = n-1; k > j; k--) if (!isspace(static_cast<int>(bTok[k]))) break;
572 
573 // Compute length and allocate enough storage to copy the token
574 //
575  if (k <= j) return 0;
576 
577 // Compute length and return pointer to the token
578 //
579  sz = k - j + 1;
580  return bTok + j;
581 }
582 
583 /******************************************************************************/
584 /* S e r v e r O r i e n t e d M e t h o d s */
585 /******************************************************************************/
586 /******************************************************************************/
587 /* A u t h e n t i c a t e */
588 /******************************************************************************/
589 
591  XrdSecParameters **parms,
592  XrdOucErrInfo *erp)
593 {
594  static const int pfxLen = sizeof(TokenHdr) + sizeof(uint16_t);
595  TokenResp *tResp;
596 
597 // Check if we have any credentials or if no credentials really needed.
598 // In either case, use host name as client name
599 //
600  if (cred->size < (int)sizeof(TokenHdr) || !cred->buffer)
601  {Fatal(erp, "Invalid ztn credentials", EINVAL, false);
602  return -1;
603  }
604  tResp = (TokenResp *)cred->buffer;
605 
606 // Check if this is our protocol
607 //
608  if (strcmp(tResp->hdr.id, "ztn"))
609  {char msg[256];
610  snprintf(msg, sizeof(msg),
611  "Authentication protocol id mismatch ('ztn' != '%.4s').",
612  tResp->hdr.id);
613  Fatal(erp, msg, EINVAL, false);
614  return -1;
615  }
616 
617 // Check if caller wants the list of authorized issuers
618 //
619  if (tResp->hdr.opr == TokenHdr::SndAI) return SendAI(erp, parms);
620 
621 // If this is not a token response then this is an error
622 //
623  if (tResp->hdr.opr != TokenHdr::IsTkn)
624  {Fatal(erp, "Invalid ztn response code", EINVAL, false);
625  return -1;
626  }
627 
628 // Make sure the response is consistent
629 //
630  const char *isBad = 0;
631  int tLen = ntohs(tResp->len);
632 
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";
638 
639  if (isBad)
640  {char eText[80];
641  snprintf(eText, sizeof(eText), "'ztn' token malformed; %s", isBad);
642  Fatal(erp, eText, EINVAL, false);
643  return -1;
644  }
645 
646 // Validate the token
647 //
648  std::string msgRC;
649  long long eTime;
650  bool validated = false;
651  if (Entity.name) {free(Entity.name); Entity.name = 0;}
652  if (tokenlib && sthP->Validate(tResp->tkn, msgRC, (expiry ? &eTime : 0), &Entity))
653  {if (expiry)
654  {if (eTime < 0 && expiry > 0)
655  {Fatal(erp, "'ztn' token expiry missing", EINVAL, false);
656  return -1;
657  }
658  if ((monotonic_time() - eTime) <= 0)
659  {Fatal(erp, "'ztn' token expired", EINVAL, false);
660  return -1;
661  }
662  }
663  validated = true;
664  }
665  if (!tokenlib || validated)
666  {
667  Entity.credslen = strlen(tResp->tkn);
668  if (Entity.creds)
669  free(Entity.creds);
670  if ((Entity.creds = (char *)malloc(Entity.credslen+1)))
671  strcpy(Entity.creds, tResp->tkn);
672  else
673  Fatal(erp, "'ztn' bad alloc", ENOMEM, false);
674  if (!Entity.name) Entity.name = strdup("anon");
675  return 0;
676  }
677 
678 // Validation failed, generate message and return failure
679 //
680 // msgRC.insert(0, "ztn validation failed; ");
681  Fatal(erp, msgRC.c_str(), EAUTH, false);
682  return -1;
683 }
684 
685 /******************************************************************************/
686 /* Private: S e n d A I */
687 /******************************************************************************/
688 
689 int XrdSecProtocolztn::SendAI(XrdOucErrInfo *erp, XrdSecParameters **parms)
690 {
691  Fatal(erp, "Authorized issuer request not supported", ENOTSUP);
692  return -1;
693 }
694 
695 /******************************************************************************/
696 /* I n i t i a l i z a t i o n F u n c t i o n s */
697 /******************************************************************************/
698 /******************************************************************************/
699 /* X r d S e c P r o t o c o l z t n I n i t */
700 /******************************************************************************/
701 
702 extern "C"
703 {
704 char *XrdSecProtocolztnInit(const char mode,
705  const char *parms,
706  XrdOucErrInfo *erp)
707 {
708  static char nilstr = 0;
709  XrdOucString accPlugin("libXrdAccSciTokens.so");
711 
712 // This only makes sense for server initialization
713 //
714  if (mode == 'c') return &nilstr;
715 
716 // If there are no parameters, return the defaults
717 //
718  if (!parms || !(*parms))
719  {char buff[256];
720  if (!getLinkage(erp, accPlugin.c_str())) return 0;
721  snprintf(buff, sizeof(buff), "TLS:%" PRIu64 ":%d:", opts, MaxTokSize);
722  return strdup(buff);
723  }
724 
725 // Copy the parameters as we will need modify them
726 //
727  std::vector<XrdOucString> useVec;
728  XrdOucString cfgParms(parms);
729  XrdOucTokenizer cfg(const_cast<char *>(cfgParms.c_str()));
730  char *endP, *val;
731 
732 // Setup to parse parameters
733 //
734  cfg.GetLine();
735 
736 // Parse the parameters: -expiry {none|optional|required} -maxsz <num>
737 // -tokenlib <libpath>
738 //
739  while((val = cfg.GetToken()))
740  { if (!strcmp(val, "-maxsz"))
741  {if (!(val = cfg.GetToken()))
742  {Fatal(erp, "-maxsz argument missing", EINVAL);
743  return 0;
744  }
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);
750  return 0;
751  }
752  }
753  else if (!strcmp(val, "-expiry"))
754  {if (!(val = cfg.GetToken()))
755  {Fatal(erp, "-expiry argument missing", EINVAL);
756  return 0;
757  }
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);
762  return 0;
763  }
764  }
765 
766  else if (!strcmp(val, "-tokenlib"))
767  {if (!(val = cfg.GetToken()))
768  {Fatal(erp, "-acclib plugin path missing", EINVAL);
769  return 0;
770  }
771  if (strcmp(val,"none"))
772  {accPlugin = val;
773  }
774  else
775  {tokenlib = false;
776  }
777  }
778 
779  else {XrdOucString eTxt("Invalid parameter - "); eTxt += val;
780  Fatal(erp, eTxt.c_str(), EINVAL);
781  return 0;
782  }
783  }
784 
785 // We rely on the token authorization plugin to validate tokens unless
786 // it is disabled using '-tokenlib none'. If active load it to
787 // get the validation object pointer. This will be filled in later but we
788 // want to know that it's actually present.
789 //
790  if (tokenlib && !getLinkage(erp, accPlugin.c_str())) return 0;
791 
792 // Assemble the parameter line and return it
793 //
794  char buff[256];
795  snprintf(buff, sizeof(buff), "TLS:%" PRIu64 ":%d:", opts, MaxTokSize);
796  return strdup(buff);
797 }
798 }
799 
800 /******************************************************************************/
801 /* X r d S e c P r o t o c o l z t n O b j e c t */
802 /******************************************************************************/
803 
804 extern "C"
805 {
807  const char *hostname,
808  XrdNetAddrInfo &endPoint,
809  const char *parms,
810  XrdOucErrInfo *erp)
811 {
812  XrdSecProtocolztn *protP;
813 
814 // Whether this is a client of server, the connection must be using TLS.
815 //
816  if (!endPoint.isUsingTLS())
817  {Fatal(erp,"security protocol 'ztn' disallowed for non-TLS connections.",
818  ENOTSUP, false);
819  return 0;
820  }
821 
822 // Get a protocol object appropriate for the mode
823 //
824  if (mode == 'c')
825  {bool aOK;
826  protP = new XrdSecProtocolztn(parms, erp, aOK);
827  if (aOK) return protP;
828  delete protP;
829  return 0;
830  }
831 
832  XrdSciTokensHelper *sthP= nullptr;
833  if (tokenlib)
834  {
835 // In server mode we need to make sure the token plugin was actually
836 // loaded and initialized as we need a pointer to the helper.
837 //
838  sthP= *sth_Linkage;
839  if (!sthP)
840  {char msg[1024];
841  snprintf(msg,sizeof(msg),"ztn required plugin (%s) has not been loaded!",
842  sth_piName);
843  Fatal(erp, msg, EIDRM,false);
844  return 0;
845  }
846  }
847 
848 // Get an authentication object and return it
849 //
850  if (!(protP = new XrdSecProtocolztn(hostname, endPoint, sthP)))
851  Fatal(erp, "insufficient memory for protocol.", ENOMEM, false);
852 
853 // All done
854 //
855  return protP;
856 }
857 }
struct stat Stat
Definition: XrdCks.cc:49
void Fatal(const char *op, const char *target)
Definition: XrdCrc32c.cc:58
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)
#define close(a)
Definition: XrdPosix.hh:43
XrdSecBuffer XrdSecCredentials
#define EAUTH
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)
#define eMsg(x)
struct myOpts opts
const char * XrdSysE2T(int errcode)
Definition: XrdSysE2T.cc:104
if(Avsz)
char * Get(const char *varname)
Definition: XrdOucEnv.hh:69
int setErrInfo(int code, const char *emsg)
XrdOucEnv * getEnv()
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.
Definition: XrdSecEntity.hh:78
XrdNetAddrInfo * addrInfo
Entity's connection details.
Definition: XrdSecEntity.hh:80
char * creds
Raw entity credentials or cert.
Definition: XrdSecEntity.hh:77
char * name
Entity's name.
Definition: XrdSecEntity.hh:69
char * host
Entity's host name dnr dependent.
Definition: XrdSecEntity.hh:70
XrdSecEntity Entity
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)
bool isJWT(const char *)
Definition: XrdSecztn.cc:142
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.