XRootD
XrdSecgsiAuthzFunVO.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d S e c g s i A u t h z F u n V O . c c */
4 /* */
5 /* (c) 2011 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 /* Trivial AuthzKey/Func(), propogates the VO as a unix user and/or group.
32 
33 1. To be used with gsi parametrized like:
34 
35  sec.protocol /opt/xrootd/lib/x86_64_linux_26 gsi \
36  -certdir:/etc/grid-security/certificates \
37  -cert:/etc/grid-security/xrd/xrdcert.pem \
38  -key:/etc/grid-security/xrd/xrdkey.pem -crl:3 \
39  -authzfun:libXrdAuthzVO.so -authzfunparms:<parms> \
40  -gmapopt:10 -gmapto:0
41 
42 2. The optional authzfunparms is formatted as a CGI string with one or more
43  of the following key-value pairs:
44 
45  debug=1
46  valido=<vlist>
47  vo2grp=<gspec>
48  vo2usr=<uspec>
49 
50  Where: debug - turns debugging on.
51  vlist - specifies a comma-separated list of vo names that are
52  acceptable. If not specified, all vo's are accepted.
53  Otherwise, failure is returned if the the vo is not in
54  the list of vo's.
55  gspec - specifies how the vo is to be inserted into a group name.
56  Specify a printf-like format string with a single %s. This
57  is where the vo name is inserted. So, "%s" simply makes the
58  group name the vo name.
59  uspec - specifies how the vo is to be inserted into a user name.
60  The same rules apply as for gspec. If uspec is not specified
61  then the name comes from distinguished name in the
62  certificate (i.e. text after '/CN=') with spaces turned
63  into underscores and the vo is not used. If uspec is
64  specified as a single asterisk (*) then the name field is
65  not touched and is as set by the gsi module.
66 */
67 
68 #include <cstdio>
69 #include <cstdlib>
70 #include <cstring>
71 #include <unistd.h>
72 
73 #include "XrdVersion.hh"
74 
75 #include "XrdSys/XrdSysHeaders.hh"
76 #include "XrdSys/XrdSysPthread.hh"
77 #include "XrdSec/XrdSecEntity.hh"
78 #include "XrdOuc/XrdOucEnv.hh"
79 #include "XrdOuc/XrdOucLock.hh"
80 
81 /******************************************************************************/
82 /* V e r s i o n I n f o r m a t i o n */
83 /******************************************************************************/
84 
86 
88 
90 
91 /******************************************************************************/
92 /* E x t e r n a l F u n c t i o n s */
93 /******************************************************************************/
94 
95 // The following functions are called by the authz plug-in driver.
96 //
97 extern "C"
98 {
99  int XrdSecgsiAuthzInit(const char *cfg);
100  int XrdSecgsiAuthzFun(XrdSecEntity &entity);
101  int XrdSecgsiAuthzKey(XrdSecEntity &entity, char **key);
102 }
103 
104 /******************************************************************************/
105 /* G l o b a l V a r i a b l e s */
106 /******************************************************************************/
107 
108 namespace
109 {
110  const int g_certificate_format = 1;
111  const int g_maxvolen = 255;
112  static char *g_valido = 0;
113  static char *g_vo2grp = 0;
114  static char *g_vo2usr = 0;
115  static int g_debug = 0;
116  static int g_cn2usr = 1;
117 }
118 
119 /******************************************************************************/
120 /* L o c a l D e f i n e s */
121 /******************************************************************************/
122 
123 #undef PRINT
124 #define PRINT(y) if (g_debug) {std::cerr << y << "\n";}
125 #undef PROUT
126 #define PROUT(_x_) \
127  std::cerr <<inf_pfx <<"entity." #_x_ "='" <<(entity._x_ ? entity._x_ : "") <<"'.\n"
128 
129 /******************************************************************************/
130 /* X r d S e c g s i A u t h z F u n */
131 /******************************************************************************/
132 
133 /* Replace the group list and/or user name with the VO name if the VO is ours.
134 
135  Return <0 on fatal failure
136  >0 error (this will still log the guy in, it seems)
137  0 success, local username in entity.name
138 */
139 
141 {
142  static const char* inf_pfx = "INFO in AuthzFun: ";
143  static XrdSysMutex Mutex;
144  const char *vtxt = "", *etxt = 0;
145  char vbuff[(g_maxvolen+1)*2];
146  int i, n;
147 
148 // We must have a vo, it must be shorter than 255 bytes, and it must be in our
149 // vo list of we have one
150 //
151  if (!entity.vorg) etxt = "missing";
152  else if ((n = strlen(entity.vorg)) > g_maxvolen) etxt = "too long";
153  else if (g_valido)
154  {*vbuff = ',';
155  strcpy(vbuff+1, entity.vorg);
156  if (!strstr(g_valido, vbuff))
157  {vtxt = entity.vorg; etxt = " not allowed";}
158  }
159 
160 // Check if we passed the tests
161 //
162  if (etxt)
163  {std::cerr <<"AuthzVO: Invalid cert; vo " <<vtxt <<etxt <<std::endl;
164  return -1;
165  }
166 
167 // Format group name if so wanted
168 //
169  if (g_vo2grp)
170  {snprintf(vbuff, sizeof(vbuff), g_vo2grp, entity.vorg);
171  if (entity.grps) free(entity.grps);
172  entity.grps = strdup(vbuff);
173  }
174 
175 // Format user name if so wanted
176 //
177  if (g_vo2usr)
178  {snprintf(vbuff, sizeof(vbuff), g_vo2usr, entity.vorg);
179  if (entity.name) free(entity.name);
180  entity.name = strdup(vbuff);
181  } else if (g_cn2usr && entity.name && (vtxt=strstr(entity.name,"/CN=")))
182  {char *cP = vbuff;
183  strncpy(vbuff, vtxt+4, g_maxvolen); vbuff[n] = 0;
184  while(*cP) {if (*cP == ' ') *cP = '_'; cP++;}
185  for (i = n-1; i >= 0; i--) {if (*cP == '_') *cP = 0;}
186  if (*vbuff)
187  {if (entity.name) free(entity.name);
188  entity.name = strdup(vbuff);
189  }
190  }
191 
192 // If debugging then print information. However, get a global mutex to keep
193 // from inter-leaving these lines with other threads, as much as possible.
194 //
195  if (g_debug)
196  {XrdOucLock lock(&Mutex);
197  PROUT(name); PROUT(host); PROUT(grps); PROUT(vorg); PROUT(role);
198  }
199 
200 // All done
201 //
202  return 0;
203 }
204 
205 /******************************************************************************/
206 /* X r d S e c g s i A u t h z K e y */
207 /******************************************************************************/
208 
209 int XrdSecgsiAuthzKey(XrdSecEntity &entity, char **key)
210 {
211  // Return key by which entity.creds will be hashed.
212  // For now return entity.creds itself.
213  // The plan is to use DN + VO endorsements in the future.
214 
215  static const char* err_pfx = "ERR in AuthzKey: ";
216  static const char* inf_pfx = "INFO in AuthzKey: ";
217 
218  // Must have got something
219  if (!key) {
220  PRINT(err_pfx << "'key' is not defined!");
221  return -1;
222  }
223 
224  PRINT(inf_pfx << "Returning creds of len " << entity.credslen << " as key.");
225 
226  // Set the key
227  *key = new char[entity.credslen + 1];
228  strcpy(*key, entity.creds);
229 
230  return entity.credslen;
231 }
232 
233 /******************************************************************************/
234 /* X r d S e c g s i A u t h z I n i t */
235 /******************************************************************************/
236 
237 int XrdSecgsiAuthzInit(const char *cfg)
238 {
239  // Return:
240  // -1 on falure
241  // 0 to get credentials in raw form
242  // 1 to get credentials in PEM base64 encoded form
243 
244  static const char* inf_pfx = "INFO in AuthzInit: ";
245  XrdOucEnv *envP;
246  char cfgbuff[2048], *sP;
247  int i;
248 
249 // The configuration string may mistakingly include other parms following
250 // the auzparms. So, trim the string.
251 //
252  if (cfg)
253  {i = strlen(cfg);
254  if (i >= (int)sizeof(cfgbuff)) i = sizeof(cfgbuff)-1;
255  memcpy(cfgbuff, cfg, i);
256  cfgbuff[i] = 0;
257  if ((sP = index(cfgbuff, ' '))) *sP = 0;
258  }
259  if (!cfg || !(*cfg)) return g_certificate_format;
260 
261 // Parse the config line (it's in cgi format)
262 //
263  envP = new XrdOucEnv(cfgbuff);
264 
265 // Set debug value
266 //
267  if ((sP = envP->Get("debug")) && *sP == '1') g_debug = 1;
268 
269 // Get the mapping strings
270 //
271  if ((g_vo2grp = envP->Get("vo2grp"))) g_vo2grp = strdup(g_vo2grp);
272  if ((g_vo2usr = envP->Get("vo2usr")))
273  {g_cn2usr = 0;
274  g_vo2usr = (!strcmp(g_vo2usr, "*") ? 0 : strdup(g_vo2usr));
275  }
276 
277 // Now process the valid vo's
278 //
279  if ((sP = envP->Get("valido")))
280  {i = strlen(sP);
281  g_valido = (char *)malloc(i+2);
282  *g_valido = ',';
283  strcpy(g_valido+1, sP);
284  }
285 
286 // All done with environment
287 //
288  delete envP;
289 
290 // All done.
291 //
292  PRINT(inf_pfx <<"cfg='"<< (cfg ? cfg : "null") << "'.");
293  return g_certificate_format;
294 }
#define PRINT(y)
XrdVERSIONINFO(XrdSecgsiAuthzFun, secgsiauthz)
#define PROUT(_x_)
int XrdSecgsiAuthzKey(XrdSecEntity &entity, char **key)
int XrdSecgsiAuthzFun(XrdSecEntity &entity)
int XrdSecgsiAuthzInit(const char *cfg)
char * Get(const char *varname)
Definition: XrdOucEnv.hh:69
char * vorg
Entity's virtual organization(s)
Definition: XrdSecEntity.hh:71
int credslen
Length of the 'creds' data.
Definition: XrdSecEntity.hh:78
char * creds
Raw entity credentials or cert.
Definition: XrdSecEntity.hh:77
char * grps
Entity's group name(s)
Definition: XrdSecEntity.hh:73
char * name
Entity's name.
Definition: XrdSecEntity.hh:69
XrdOucEnv * envP
Definition: XrdPss.cc:109