XRootD
XrdVomsFun.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d V o m s F u n . c c */
4 /* */
5 /* (C) 2013 G. Ganis, CERN */
6 /* */
7 /* All rights reserved. The copyright holder's institutional names may not */
8 /* be used to endorse or promote products derived from this software without */
9 /* specific prior written permission. */
10 /* */
11 /* This file is part of the VOMS extraction XRootD plug-in software suite, */
12 /* here after called VOMS-XRootD (see https://github.com/gganis/voms). */
13 /* */
14 /* VOMS-XRootD is free software: you can redistribute it and/or modify it */
15 /* under the terms of the GNU Lesser General Public License as published by */
16 /* the Free Software Foundation, either version 3 of the License, or (at */
17 /* your option) any later version. */
18 /* */
19 /* VOMS-XRootD is distributed in the hope that it will be useful, but */
20 /* WITHOUT ANY WARRANTY, not even the implied warranty of MERCHANTABILITY or */
21 /* FITNESS FOR A PARTICULAR PURPOSE. */
22 /* See the GNU Lesser General Public License for more details. */
23 /* */
24 /* You should have received a copy of the GNU Lesser General Public License */
25 /* along with VOMS-XRootD in a file called COPYING.LGPL (LGPL license) and */
26 /* file COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
27 /* */
28 /******************************************************************************/
29 
30 /******************************************************************************/
31 /* */
32 /* See README.md for hints about usage of this library */
33 /* */
34 /******************************************************************************/
35 
36 #include <cstdio>
37 #include <cstdlib>
38 #include <cstring>
39 #include <cerrno>
40 
41 #include "XrdVoms.hh"
42 #include "XrdVomsFun.hh"
43 #include "XrdVomsTrace.hh"
44 #include "XrdVomsMapfile.hh"
45 
46 #ifdef HAVE_XRDCRYPTO
49 #endif
50 #include "XrdSec/XrdSecEntity.hh"
51 #include "XrdSys/XrdSysLogger.hh"
52 
53 /******************************************************************************/
54 /* L o c a l D e f i n e s */
55 /******************************************************************************/
56 
57 #ifndef SafeFree
58 #define SafeFree(x) { if (x) free(x) ; x = 0; }
59 #endif
60 
61 #define VOMSDBG(m) \
62  if (gDebug) { \
63  PRINT(m); \
64  }
65 
66 #define VOMSDBGSUBJ(m, c) \
67  if (gDebug) { \
68  XrdOucString subject; \
69  NameOneLine(X509_get_subject_name(c), subject); \
70  PRINT(m << subject); \
71  }
72 
73 #define VOMSREPLACE(a, f, e) \
74  if (a.length() > 0) { \
75  f.replace("<g>", e.grps); \
76  f.replace("<r>", e.role); \
77  f.replace("<vo>", e.vorg); \
78  f.replace("<an>", e.endorsements); \
79  }
80 
81 #define VOMSSPTTAB(a) \
82  if (a.length() > 0) { \
83  int sp = -1; \
84  while ((sp = a.find(' ', sp+1)) != STR_NPOS) { a[sp] = '\t'; } \
85  }
86 
87 #define FATAL(x) {std::cerr <<"VomsFun: "<<x<<std::endl; aOK = false;}
88 
89 namespace
90 {
91 static const int gSelAll = 0;
92 static const int gSelGrps = 1;
93 static const short gUseFirst = 0;
94 static const short gUseLast = 1;
95 static const short gUseAll = 2;
96 }
97 
98 /******************************************************************************/
99 /* C o n s t r u c t o r */
100 /******************************************************************************/
101 
103  : gGrpWhich(gUseAll), gDebug(0), gDest(erp),
104  gLogger(erp.logger())
105 {
106 #ifdef HAVE_XRDCRYPTO
107  gCertFmt = gCertRaw; // certfmt:raw|pem|x509 [raw]
108 #else
109  gCertFmt = gCertPEM; // certfmt:pem|x509 [pem]
110 #endif
111 };
112 
113 /******************************************************************************/
114 /* N a m e O n e L i n e */
115 /******************************************************************************/
116 
117 // Function to convert X509_NAME into a one-line human readable string
118 //
119 void XrdVomsFun::NameOneLine(X509_NAME *nm, XrdOucString &s)
120 {
121  BIO *mbio = BIO_new(BIO_s_mem());
122  X509_NAME_print_ex(mbio, nm, 0, XN_FLAG_COMPAT);
123  char *data = 0;
124  long len = BIO_get_mem_data(mbio, &data);
125  s = "/";
126  s.insert(data, 1, len);
127  BIO_free(mbio);
128  s.replace(", ", "/");
129 
130  // Done
131  return;
132 }
133 
134 /******************************************************************************/
135 /* F m t R e p l a c e */
136 /******************************************************************************/
137 
138 // Method to convert X509_NAME into a one-line human readable string
139 //
140 void XrdVomsFun::FmtReplace(XrdSecEntity &ent)
141 {
142  XrdOucString gf(gGrpFmt), rf(gRoleFmt), vf(gVoFmt);
143 
144  VOMSREPLACE(gGrpFmt, gf, ent);
145  VOMSREPLACE(gRoleFmt, rf, ent);
146  VOMSREPLACE(gVoFmt, vf, ent);
147 
148  if (gf.length() > 0) {
149  SafeFree(ent.grps);
150  ent.grps = strdup(gf.c_str());
151  }
152  if (rf.length() > 0) {
153  SafeFree(ent.role);
154  ent.role = strdup(rf.c_str());
155  }
156  if (vf.length() > 0) {
157  SafeFree(ent.vorg);
158  ent.vorg = strdup(vf.c_str());
159  }
160 }
161 
162 /******************************************************************************/
163 /* F m t E x t r a c t */
164 /******************************************************************************/
165 
166 // Method to extract out a tag
167 //
168 void XrdVomsFun::FmtExtract(XrdOucString &out,
169  XrdOucString in, const char *tag)
170 {
171  // Output group format string
172  int igf = in.find(tag);
173  if (igf != STR_NPOS) {
174  int from = igf + strlen(tag);
175  if (in[from] == '"') {
176  out.assign(in, from + 1);
177  out.erase(out.find('"'));
178  } else {
179  out.assign(in, from);
180  while(out.endswith(' ')) out.erasefromend(1);
181  }
182  }
183 }
184 
185 /******************************************************************************/
186 /* V O M S F u n */
187 /******************************************************************************/
188 
189 // The Main Method
190 //
192 {
193  // Implementation of XrdSecgsiAuthzFun extracting the information from the
194  // proxy chain in entity.creds
195  EPNAME("Fun");
196 
197  vomsdata v;
198  X509 *pxy = 0;
199  STACK_OF(X509) *stk = 0;
200  int freestk = 1;
201 
202 // Set extractor name in the XrdSecEntity object
203 //
204  strcpy(ent.prox, "xrdvoms");
205 
206  if (gCertFmt == gCertRaw) {
207 #ifdef HAVE_XRDCRYPTO
208  //
209  // RAW format
210  //
212  if (!c) {
213  PRINT("ERROR: no proxy chain found!");
214  return -1;
215  }
216 
217  XrdCryptoX509 *xp = c->End();
218  if (!xp) {
219  PRINT("ERROR: no proxy certificate in chain!");
220  return -1;
221  }
222  pxy = (X509 *) xp->Opaque();
223  VOMSDBGSUBJ("proxy: ", pxy)
224  freestk = 2;
225 
226  stk =sk_X509_new_null();
227  XrdCryptoX509 *xxp = c->Begin();
228  while (xxp) {
229  if (xxp == c->End()) break;
230  if (xxp->type != XrdCryptoX509::kCA) {
231  VOMSDBGSUBJ("adding cert: ", (X509 *) xxp->Opaque())
232  sk_X509_push(stk, (X509 *) xxp->Opaque());
233  }
234  xxp = c->Next();
235  }
236 #else
237  //
238  // Do not have support for RAW format
239  //
240  PRINT("ERROR: compiled without support for RAW format! Re-run with 'certfmt=pem'");
241  return -1;
242 #endif
243  } else if (gCertFmt == gCertPEM) {
244  //
245  // PEM format
246  //
247  // Create a bio_mem to store the certificates
248  BIO *bmem = BIO_new(BIO_s_mem());
249  if (!bmem) {
250  PRINT("unable to create BIO for memory operations");
251  return -1;
252  }
253 
254  // Write data to BIO
255  int nw = BIO_write(bmem, (const void *)(ent.creds), ent.credslen);
256  if (nw != ent.credslen) {
257  PRINT("problems writing data to memory BIO (nw: "<<nw<<")");
258  BIO_free(bmem);
259  return -1;
260  }
261 
262  // Get certificate from BIO
263  if (!(pxy = PEM_read_bio_X509(bmem,0,0,0))) {
264  PRINT("unable to read certificate to memory BIO");
265  BIO_free(bmem);
266  return -1;
267  }
268  VOMSDBGSUBJ("proxy: ", pxy)
269  //
270  // The chain now
271  X509 *xc = 0;
272  stk =sk_X509_new_null();
273  while ((xc = PEM_read_bio_X509(bmem,0,0,0))) {
274  VOMSDBGSUBJ("adding cert: ", xc)
275  sk_X509_push(stk, xc);
276  }
277  //
278  // Free BIO
279  BIO_free(bmem);
280 
281  } else {
282  //
283  // STACK_OF(X509) format
284  //
285  Voms_x509_in_t *voms_in = (Voms_x509_in_t *) ent.creds;
286  pxy = voms_in->cert;
287  stk = voms_in->chain;
288  freestk = 0;
289  }
290 
291  bool extfound = 0;
292  XrdOucString endor, grps, role, vo, xendor, xgrps, xrole, xvo;
293  if (v.Retrieve(pxy, stk, RECURSE_CHAIN)) {
294  VOMSDBG("retrieval successful");
295  extfound = 1;
296  std::vector<voms>::iterator i = v.data.begin();
297  for ( ; i != v.data.end(); i++) {
298  VOMSDBG("found VO: " << (*i).voname);
299  xvo = (*i).voname.c_str(); VOMSSPTTAB(xvo);
300  // Filter the VO? (*i) is voms
301  if (gVOs.Num() > 0 && !gVOs.Find((*i).voname.c_str())) continue;
302  // Save VO name (in tuple mode this is done later, in the loop over groups)
303  if (gGrpWhich < gUseAll) vo = xvo;
304  std::vector<data> dat = (*i).std;
305  std::vector<data>::iterator idat = dat.begin();
306  // Same size as std::vector<data> by construction (same information in compact form)
307  std::vector<std::string> fqa = (*i).fqan;
308  std::vector<std::string>::iterator ifqa = fqa.begin();
309  for (; idat != dat.end(); idat++, ifqa++) {
310  VOMSDBG(" ---> group: '"<<(*idat).group<<"', role: '"<<(*idat).role<<"', cap: '" <<(*idat).cap<<"'");
311  VOMSDBG(" ---> fqan: '"<<(*ifqa)<<"'");
312  xgrps = (*idat).group.c_str(); VOMSSPTTAB(xgrps);
313  xrole = (*idat).role.c_str(); VOMSSPTTAB(xrole);
314  xendor = (*ifqa).c_str(); VOMSSPTTAB(xendor);
315  bool fillgrp = true;
316  if (gGrps.Num() && !gGrps.Find((*idat).group.c_str()))
317  fillgrp = false;
318  if (fillgrp) {
319  if (gGrpWhich == gUseAll) {
320  if (vo.length() > 0) vo += " ";
321  vo += (*i).voname.c_str();
322  if (grps.length() > 0) grps += " ";
323  grps += (*idat).group.c_str();
324  if (role.length() > 0) role += " ";
325  role += (*idat).role.c_str();
326  if (endor.length() > 0) endor += ",";
327  endor += (*ifqa).c_str();
328  } else {
329  grps = (*idat).group.c_str();
330  role = (*idat).role.c_str();
331  endor = (*ifqa).c_str();
332  }
333  }
334  // If we are asked to take the first we break
335  if (gGrpWhich == gUseFirst && grps.length() > 0) break;
336  }
337  if (grps.length() <= 0) {
338  // Reset all the fields
339  role = "";
340  vo = "";
341  endor = "";
342  }
343  }
344  // Save the information found
345  SafeFree(ent.vorg);
346  SafeFree(ent.grps);
347  SafeFree(ent.role);
348  SafeFree(ent.endorsements);
349  if (vo.length() > 0) {
350  ent.vorg = strdup(vo.c_str());
351  // Save the groups
352  if (grps.length() > 0) ent.grps = strdup(grps.c_str());
353  if (role.length() > 0) ent.role = strdup(role.c_str());
354  // Save the whole string in endorsements
355  if (endor.length() > 0) ent.endorsements = strdup(endor.c_str());
356  } else if (extfound) {
357  VOMSDBG("VOMS extensions do not match required criteria ("<<gRequire<<")");
358  }
359  } else {
360  PRINT("retrieval FAILED: "<< v.ErrorMessage());
361  }
362 
363  // Fix spaces in XrdSecEntity::name
364 // char *sp = 0;
365 // while ((sp = strchr(ent.name, ' '))) { *sp = '\t'; }
366 
367  // Adjust the output format, if required
368  FmtReplace(ent);
369 
370  // Free memory taken by the chain, if required
371  if (stk && freestk > 0) {
372  if (freestk == 1) {
373  sk_X509_pop_free(stk, X509_free);
374  X509_free(pxy);
375  } else if (freestk == 2) {
376  while (sk_X509_pop(stk)) { }
377  sk_X509_free(stk);
378  }
379  }
380 
381  // Success or failure?
382  int rc = !ent.vorg ? -1 : 0;
383  if (rc == 0 && gGrps.Num() && !ent.grps) rc = -1;
384 
385  // If we have a mapfile object, apply the mapping now.
386  if (m_mapfile) {
387  auto mapfile_rc = m_mapfile->Apply(ent);
388  rc = rc ? rc : mapfile_rc;
389  }
390 
391  // Done
392  return rc;
393 }
394 
395 /******************************************************************************/
396 /* V O M S I n i t */
397 /******************************************************************************/
398 
399 // Method to initialize this object
400 //
401 int XrdVomsFun::VOMSInit(const char *cfg)
402 {
403  // Initialize the relevant parameters from the 'cfg' string.
404  // Return -1 on failure.
405  // Otherwise, the return code indicates the format required by the main function
406  // defined by 'certfmt' below.
407  //
408  // Supported options:
409  // certfmt=raw|pem|x509 Certificate format: [raw]
410  // raw to be used with XrdCrypto tools
411  // pem PEM base64 format (i.e. cert files)
412  // x509 As a STACK_OF(X509)
413  // grpopt=opt What to do with the group names: [1]
414  // opt = sel * 10 + which
415  // with 'sel'
416  // 0 consider all those present
417  // 1 select among those specified by
418  // 'grps' (see below)
419  // and 'which'
420  // 0 take the first one
421  // 1 take the last
422  // 2 take all
423  //
424  // grpopt=useall|usefirst|uselast
425  // useall: all applicable groups
426  // usefirst: only the first applicable on
427  // uselast: only the last applicable on
428  //
429  // grps=grp1[,grp2,...] Group(s) for which the information is
430  // extracted; if specified the gropt
431  // 'sel' is set to 1 regardless of
432  // the setting.
433  // vos=vo1[,vo2,...] VOs to be considered; the first match is taken
434  // grpfmt=<string> Format to use for XrdSecEntity::grps
435  // rolefmt=<string> Format to use for XrdSecEntity::role
436  // vofmt=<string> Format to use for XrdSecEntity::vorg
437  // Recognized place holders in the above
438  // format strings:
439  // <r> role, from the parsing procedure
440  // <g> group
441  // <vo> VO
442  // <an> Full Qualified Attribute Name
443  // For example, rolefmt=<g>,grpfmt=<r> will
444  // inverse the group and role in XrdSecEntity
445  // dbg To force verbose mode
446  //
447  EPNAME("Init");
448  vomsdata vomsInit; // This forces libssl initialization at load time
449 
450  XrdOucString oos(cfg);
451 
452  XrdOucString fmt, go, grps, voss, gfmt, rfmt, vfmt, sdbg, sdbg2;
453  XrdOucString gr, vo, ss;
454  bool aOK = true;
455 
456  if (oos.length() > 0) {
457 
458 #define NTAG 9
459  XrdOucString *var[NTAG] = { &fmt, &go, &grps, &voss, &gfmt, &rfmt, &vfmt,
460  &sdbg, &sdbg2};
461  const char *tag[] = {"certfmt=", "grpopt=", "grps=", "vos=",
462  "grpfmt=", "rolefmt=", "vofmt=", "dbg", "dbg2"};
463  int jb[NTAG], je[NTAG];
464 
465  // Begin of ranges
466  int i = 0, j = -1;
467  for(; i < NTAG; i++) {
468  jb[i] = -1;
469  int j = oos.find(tag[i]);
470  if (j != STR_NPOS) jb[i] = j;
471 // DEBUG("["<<i<<"] "<<tag[i]<<" is "<<(j == STR_NPOS?"no":"")<<"spec");
472  }
473  // End of ranges
474  for(i = 0; i < NTAG; i++) {
475  je[i] = -1;
476 // DEBUG("-------------");
477  if (jb[i] > -1) {
478  int k = -1;
479  for(j = 0; j < NTAG; j++) {
480  if (j != i) {
481  if (jb[j] > jb[i] && (k < 0 || jb[j] < jb[k])) k = j;
482 // DEBUG("jb[" << j << "] = " << jb[j] <<" jb[ "<< i<<"] = "<<jb[i] << " -> k:" << k);
483  }
484  }
485  if (k >= 0) {
486  je[i] = jb[k] - 2;
487  } else {
488  je[i] = oos.length() - 1;
489  }
490  if (i < NTAG-2) {
491  ss.assign(oos, jb[i], je[i]);
492  FmtExtract(*var[i], ss, tag[i]);
493  } else {
494  *var[i] = tag[i];
495  }
496  DEBUG(tag[i] <<"\"" << *var[i] << "\"");
497  }
498 // DEBUG("jb["<<i<<"] = "<<jb[i] <<" ---> "<< "je["<<i<<"] = "<<je[i]);
499  }
500 
501 
502  // Certificate format
503  if (fmt.length() > 0) {
504  if (fmt == "raw") {
505 #ifdef HAVE_XRDCRYPTO
506  gCertFmt = gCertRaw;
507 #else
508  //
509  // Do not have support for RAW format
510  //
511  PRINT("VomsFun: support for RAW format not available: forcing PEM");
512  gCertFmt = gCertPEM;
513 #endif
514  } else if (fmt == "pem") {
515  gCertFmt = gCertPEM;
516  } else if (fmt == "x509") {
517  gCertFmt = gCertX509;
518  }
519  else FATAL("Unsupported cert format - '"<<fmt.c_str()<<"'.")
520  }
521 
522  // Group option
523  if (go.length() > 0) {
524  if (go.isdigit()) {
525  int grpopt = go.atoi();
526  int n = grpopt / 10;
527  if (n != gSelAll && n != gSelGrps) {
528  FATAL("grpopt 'select' must be in [0,1] not '"<<n<<"'");
529  }
530  gGrpWhich = grpopt % 10;
531  if (gGrpWhich != gUseFirst && gGrpWhich != gUseLast
532  && gGrpWhich != gUseAll) {
533  FATAL("grpopt 'which' must be in [0,2] not '"<<gGrpWhich<<"'");
534  }
535  } else {
536  if (go == "useall") gGrpWhich = gUseAll;
537  else if (go == "usefirst") gGrpWhich = gUseFirst;
538  else if (go == "uselast") gGrpWhich = gUseLast;
539  else FATAL("Invalid grpopt '"<<go<<"'");
540  }
541  gRequire = "grpopt="; gRequire += go;
542  }
543 
544  // Groups selection
545  if (grps.length() > 0) {
546  int from = 0, flag = 1;
547  while ((from = grps.tokenize(gr, from, ',')) != -1) {
548  // Analyse tok
549  VOMSSPTTAB(gr);
550  gGrps.Add(gr.c_str(), &flag);
551  }
552  if (gRequire.length() > 0) gRequire += ";";
553  gRequire += "grps="; gRequire += grps;
554  }
555 
556  // VO selection
557  if (voss.length() > 0) {
558  int from = 0, flag = 1;
559  while ((from = voss.tokenize(vo, from, ',')) != -1) {
560  // Analyse tok
561  VOMSSPTTAB(vo);
562  gVOs.Add(vo.c_str(), &flag);
563  }
564  if (gRequire.length() > 0) gRequire += ";";
565  gRequire += "vos="; gRequire += voss;
566  }
567 
568  // Output group format string
569  FmtExtract(gGrpFmt, gfmt, "grpfmt=");
570  // Output role format string
571  FmtExtract(gRoleFmt, rfmt, "rolefmt=");
572  // Output vo format string
573  FmtExtract(gVoFmt, vfmt, "vofmt=");
574 
575  // Verbose mode
576  if (sdbg == "dbg" && !gDebug) gDebug = 1;
577  if (sdbg2 == "dbg2") gDebug = 2;
578  }
579 
580  // Notify
581  const char *cfmt[3] = { "raw", "pem base64", "STACK_OF(X509)" };
582  const char *cgrs[2] = { "all groups", "specified group(s)"};
583  const char *cgrw[3] = { "first", "last", "all" };
584  int n = (gGrps.Num() ? 1 : 0);
585  PRINT("++++++++++++++++++ VOMS plug-in +++++++++++++++++++++++++++++++");
586  PRINT("+++ proxy fmt: "<< cfmt[gCertFmt]);
587  PRINT("+++ group option: "<<cgrw[gGrpWhich]<<" of "<<cgrs[n]);
588  if (grps.length() > 0) {
589  PRINT("+++ group(s): "<< grps);
590  } else {
591  PRINT("+++ group(s): <not specified>");
592  }
593  if (gGrpFmt.length() > 0)
594  PRINT("+++ grps fmt: "<< gGrpFmt);
595  if (gRoleFmt.length() > 0)
596  PRINT("+++ role fmt: "<< gRoleFmt);
597  if (gVoFmt.length() > 0)
598  PRINT("+++ vorg fmt: "<< gVoFmt);
599  if (gVOs.Num() > 0) {PRINT("+++ VO(s): "<< voss);}
600  else {PRINT("+++ VO(s): all");}
601  PRINT("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
602 
603  m_mapfile = XrdVomsMapfile::Configure(&gDest);
604  if (m_mapfile == VOMS_MAP_FAILED) {
605  aOK = false;
606  PRINT("VOMS mapfile requested but initialization failed; failing VOMS plugin config.");
607  }
608 
609  // Done
610  return (aOK ? gCertFmt : -1);
611 }
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
#define PRINT(y)
#define STR_NPOS
if(Avsz)
#define VOMSSPTTAB(a)
Definition: XrdVomsFun.cc:81
#define NTAG
#define VOMSREPLACE(a, f, e)
Definition: XrdVomsFun.cc:73
#define SafeFree(x)
Definition: XrdVomsFun.cc:58
#define FATAL(x)
Definition: XrdVomsFun.cc:87
#define VOMSDBG(m)
Definition: XrdVomsFun.cc:61
#define VOMSDBGSUBJ(m, c)
Definition: XrdVomsFun.cc:66
#define VOMS_MAP_FAILED
XrdCryptoX509 * Next()
XrdCryptoX509 * Begin()
XrdCryptoX509 * End() const
virtual XrdCryptoX509data Opaque()
EX509Type type
T * Add(const char *KeyVal, T *KeyData, const int LifeTime=0, XrdOucHash_Options opt=Hash_default)
Definition: XrdOucHash.icc:61
T * Find(const char *KeyVal, time_t *KeyTime=0)
Definition: XrdOucHash.icc:160
void insert(const int i, int start=-1)
const char * c_str() const
void assign(const char *s, int j, int k=-1)
int erasefromend(int sz=0)
bool endswith(char c)
int erase(int start=0, int size=0)
int replace(const char *s1, const char *s2, int from=0, int to=-1)
int find(const char c, int start=0, bool forward=1)
int length() const
bool isdigit(int from=0, int to=-1)
long atoi(int from=0, int to=-1)
int tokenize(XrdOucString &tok, int from, char del=':')
char * vorg
Entity's virtual organization(s)
Definition: XrdSecEntity.hh:71
int credslen
Length of the 'creds' data.
Definition: XrdSecEntity.hh:78
char prox[XrdSecPROTOIDSIZE]
Auth extractor used (e.g. xrdvoms)
Definition: XrdSecEntity.hh:68
char * creds
Raw entity credentials or cert.
Definition: XrdSecEntity.hh:77
char * grps
Entity's group name(s)
Definition: XrdSecEntity.hh:73
char * role
Entity's role(s)
Definition: XrdSecEntity.hh:72
char * endorsements
Protocol specific endorsements.
Definition: XrdSecEntity.hh:75
XrdVomsFun(XrdSysError &erp)
Definition: XrdVomsFun.cc:102
int VOMSInit(const char *cfg)
Definition: XrdVomsFun.cc:401
int VOMSFun(XrdSecEntity &ent)
Definition: XrdVomsFun.cc:191
static XrdVomsMapfile * Configure(XrdSysError *)
int Apply(XrdSecEntity &)
X509 * cert
Definition: XrdVoms.hh:40