XRootD
XrdAccTest.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d A c c T e s t . c c */
4 /* */
5 /* (c) 2017 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 #include <unistd.h>
32 #include <cctype>
33 #include <cerrno>
34 #include <cstdlib>
35 #include <strings.h>
36 #include <cstdio>
37 #include <grp.h>
38 #include <arpa/inet.h>
39 #include <sys/param.h>
40 #include <sys/socket.h>
41 
42 #include "XrdVersion.hh"
43 
45 #include "XrdAcc/XrdAccConfig.hh"
46 #include "XrdAcc/XrdAccGroups.hh"
47 #include "XrdAcc/XrdAccPrivs.hh"
48 #include "XrdSys/XrdSysError.hh"
49 #include "XrdSys/XrdSysHeaders.hh"
50 #include "XrdSys/XrdSysLogger.hh"
51 #include "XrdNet/XrdNetAddr.hh"
52 #include "XrdOuc/XrdOucEnv.hh"
53 #include "XrdOuc/XrdOucStream.hh"
54 
55 /******************************************************************************/
56 /* G l o b a l O b j e c t s */
57 /******************************************************************************/
58 
59 char *PrivsConvert(XrdAccPrivCaps &ctab, char *buff, int blen);
60 
62 
63 int extra;
64 
66 
67 XrdSysError eroute(&myLogger, "acc_");
68 
69 namespace
70 {
71 XrdSecEntity Entity("host");
72 
73 XrdNetAddr netAddr;
74 
75 bool v2 = false;
76 }
77 
78 /******************************************************************************/
79 /* O p e r a t i o n T a b l e */
80 /******************************************************************************/
81 typedef struct {const char *opname; Access_Operation oper;} optab_t;
83  {{"?", AOP_Any},
84  {"cm", AOP_Chmod},
85  {"co", AOP_Chown},
86  {"cr", AOP_Create},
87  {"ec", AOP_Excl_Create},
88  {"rm", AOP_Delete},
89  {"lk", AOP_Lock},
90  {"mk", AOP_Mkdir},
91  {"mv", AOP_Rename},
92  {"ei", AOP_Excl_Insert},
93  {"rd", AOP_Read},
94  {"ls", AOP_Readdir},
95  {"st", AOP_Stat},
96  {"wr", AOP_Update}
97  };
98 
99 int opcnt = sizeof(optab)/sizeof(optab[0]);
100 
101 /******************************************************************************/
102 /* U s a g e */
103 /******************************************************************************/
104 
105 void Usage(const char *msg)
106 {
107  if (msg) std::cerr <<"xrdacctest: " <<msg <<std::endl;
108  std::cerr <<"Usage: xrdacctest [-c <cfn>] [<ids> | <user> <host>] <act>\n\n";
109  std::cerr <<"<ids>: -a <auth> -g <grp> -h <host> -o <org> -r <role> -u <user>\n";
110  std::cerr <<"<act>: <opc> <path> [<path> [...]]\n";
111  std::cerr <<"<opc>: cr - create mv - rename st - status lk - lock\n";
112  std::cerr <<" rd - read wr - write ls - readdir rm - remove\n";
113  std::cerr <<" ec - excl create ei - excl rename\n";
114  std::cerr <<" * - zap args ? - display privs\n";
115  std::cerr << std::flush;
116  exit(msg ? 1 : 0);
117 }
118 
119 /******************************************************************************/
120 /* S e t I D */
121 /******************************************************************************/
122 
123 void SetID(char *&dest, char *val)
124 {
125  if (dest) free(dest);
126  dest = (strcmp(val, "none") ? strdup(val) : 0);
127 }
128 
129 /******************************************************************************/
130 /* Z a p E n t i t y */
131 /******************************************************************************/
132 
133 void ZapEntity()
134 {
135  strncpy(Entity.prot, "host", sizeof(Entity.prot));
136  if (Entity.grps) free(Entity.grps);
137  Entity.grps = 0;
138  if (Entity.host) free(Entity.host);
139  Entity.host = 0;
140  if (Entity.vorg) free(Entity.vorg);
141  Entity.vorg = 0;
142  if (Entity.role) free(Entity.role);
143  Entity.role = 0;
144  if (Entity.name) free(Entity.name);
145  Entity.name = 0;
146 }
147 
148 /******************************************************************************/
149 /* m a i n */
150 /******************************************************************************/
151 
152 int main(int argc, char **argv)
153 {
154 static XrdVERSIONINFODEF(myVer, XrdAccTest, XrdVNUMBER, XrdVERSION);
155 extern int optind;
156 extern char *optarg;
158  const char *cfn,
159  const char *parm,
160  XrdVersionInfo &myVer);
161 int DoIt(int argpnt, int argc, char **argv, bool singleshot);
162 
163 const char *cfHost = "localhost", *cfProg = "xrootd";
164 char *p2l(XrdAccPrivs priv, char *buff, int blen);
165 char *argval[32], buff[255], tident[80], c;
166 int DoIt(int argnum, int argc, char **argv, int singleshot);
167 XrdOucStream Command;
168 const int maxargs = sizeof(argval)/sizeof(argval[0]);
169 char *at, *lp, *ConfigFN = (char *)"./acc.cf";
170 int argnum, rc = 0;
171 bool singleshot=false;
172 
173 // Print help if no args
174 //
175  if (argc == 1) Usage(0);
176  Entity.addrInfo = &netAddr;
177  sprintf(tident, "acctest.%d:0@localhost", getpid());
178  Entity.tident = tident;
179 
180 // Get all of the options.
181 //
182  while ((c=getopt(argc,argv,"a:c:de:g:h:o:r:u:s")) != (char)EOF)
183  { switch(c)
184  {
185  case 'a':
186  {size_t size = sizeof(Entity.prot)-1;
187  strncpy(Entity.prot, optarg, size);
188  Entity.prot[size] = '\0';
189  }
190  v2 = true; break;
191  case 'd': break;
192  case 'e': Entity.ueid = atoi(optarg); v2 = true; break;
193  case 'g': SetID(Entity.grps, optarg); v2 = true; break;
194  case 'h': SetID(Entity.host, optarg); v2 = true; break;
195  case 'o': SetID(Entity.vorg, optarg); v2 = true; break;
196  case 'r': SetID(Entity.role, optarg); v2 = true; break;
197  case 'u': SetID(Entity.name, optarg); v2 = true; break;
198  case 'c': ConfigFN = optarg; break;
199  case 's': singleshot = true; break;
200  default: sprintf(buff, "-%c option is invalid.", c);
201  Usage(buff);
202  }
203  }
204 
205 // Establish environment
206 //
207  if ((at = index(ConfigFN, '@')))
208  {*at++ = 0; if (*at) cfHost = at;}
209  sprintf(buff, "%s anon@%s", cfProg, cfHost);
210  XrdOucEnv::Export("XRDINSTANCE", buff);
211 
212 // Obtain the authorization object
213 //
214 if (!(Authorize = XrdAccDefaultAuthorizeObject(&myLogger, ConfigFN, 0, myVer)))
215  {std::cerr << "testaccess: Initialization failed." <<std::endl;
216  exit(2);
217  }
218 
219 // If command line options specified, process this
220 //
221  if (optind < argc) {rc = DoIt(optind, argc, argv, singleshot); exit(rc);}
222 
223 // Start accepting command from standard in until eof
224 //
225  bool dequote;
226  Command.Attach(0);
227  std::cerr << "Enter arguments: ";
228  while((lp = Command.GetLine()) && *lp)
229  {dequote = false;
230  char *xp = lp;
231  while(*xp)
232  {if (*xp == '\'')
233  {*xp++ = ' ';
234  dequote = true;
235  while(*xp)
236  {if (*xp == ' ') *xp = '\t';
237  else if (*xp == '\'') {*xp++ = ' '; break;}
238  xp++;
239  }
240  } else xp++;
241  }
242 
243  for (argnum=1;
244  argnum < maxargs && (argval[argnum]=Command.GetToken());
245  argnum++) {}
246  if (dequote)
247  {for (int i = 1; i < argnum; i++)
248  {char *ap = argval[i];
249  while(*ap) {if (*ap == '\t') *ap = ' '; ap++;}
250  }
251  }
252  Entity.ueid++;
253  rc |= DoIt(1, argnum, argval, singleshot=0);
254  std::cerr << "Enter arguments: ";
255  }
256 
257 // All done
258 //
259  exit(rc);
260 }
261 
262 int DoIt(int argpnt, int argc, char **argv, bool singleshot)
263 {
264 char *opc, *opv, *path, *result, buff[80];
265 Access_Operation cmd2op(char *opname);
266 void Usage(const char *);
267 Access_Operation optype;
268 XrdAccPrivCaps pargs;
269 XrdAccPrivs auth;
270 
271 // Get options (this may be interactive mode)
272 //
273  while(argpnt < argc && *argv[argpnt] == '-')
274  {opc = argv[argpnt++];
275  if (argpnt >= argc)
276  {sprintf(buff, "%s option value not specified.", opc);
277  Usage(buff);
278  }
279  opv = argv[argpnt++];
280  if (strlen(opc) != 2)
281  {sprintf(buff, "%s option is invalid.", opc);
282  Usage(buff);
283  }
284  switch(*(opc+1))
285  {case 'a': {size_t size = sizeof(Entity.prot)-1;
286  strncpy(Entity.prot, opv, size);
287  Entity.prot[size] = '\0';
288  }
289  v2 = true; break;
290  case 'e': Entity.ueid = atoi(opv); v2 = true; break;
291  case 'g': SetID(Entity.grps, opv); v2 = true; break;
292  case 'h': SetID(Entity.host, opv); v2 = true; break;
293  case 'o': SetID(Entity.vorg, opv); v2 = true; break;
294  case 'r': SetID(Entity.role, opv); v2 = true; break;
295  case 'u': SetID(Entity.name, opv); v2 = true; break;
296  default: sprintf(buff, "%s option is invalid.", opc);
297  Usage(buff);
298  break;
299  }
300  }
301 
302 // Make sure user and host specified if v1 version being used
303 //
304  if (!v2)
305  {if (argpnt >= argc) Usage("user not specified.");
306  Entity.name = argv[argpnt++];
307  if (argpnt >= argc) Usage("host not specified.");
308  Entity.host = argv[argpnt++];
309  }
310 
311 // Make sure op specified unless we are v2
312 //
313  if (argpnt >= argc)
314  {if (v2) return 0;
315  else Usage("operation not specified.");
316  }
317  if (!strcmp(argv[argpnt], "*"))
318  {ZapEntity();
319  return 0;
320  }
321  optype = cmd2op(argv[argpnt++]);
322 
323 // Make sure path specified
324 //
325  if (argpnt >= argc) Usage("path not specified.");
326 
327 // Set host, ignore errors
328 //
329  if (Entity.host) netAddr.Set(Entity.host, 0);
330 
331 // Process each path, as needed
332 //
333  while(argpnt < argc)
334  {path = argv[argpnt++];
335  auth = Authorize->Access((const XrdSecEntity *)&Entity,
336  (const char *)path,
337  optype);
338  if (optype != AOP_Any) result=(auth?(char *)"allowed":(char *)"denied");
339  else {pargs.pprivs = auth; pargs.nprivs = XrdAccPriv_None;
340  result = PrivsConvert(pargs, buff, sizeof(buff));
341  }
342  std::cout <<result <<": " <<path <<std::endl;
343  if (singleshot) return !auth;
344  }
345 
346 return 0;
347 }
348 
349 /******************************************************************************/
350 /* c m d 2 o p */
351 /******************************************************************************/
352 
354 {
355  int i;
356  for (i = 0; i < opcnt; i++)
357  if (!strcmp(opname, optab[i].opname)) return optab[i].oper;
358  std::cerr << "testaccess: Invalid operation - " <<opname <<std::endl;
359  return AOP_Any;
360 }
361 
362 /******************************************************************************/
363 /* P r i v s C o n v e r t */
364 /******************************************************************************/
365 
366 char *PrivsConvert(XrdAccPrivCaps &ctab, char *buff, int blen)
367 {
368  int i=0, j, k=2, bmax = blen-1;
369  XrdAccPrivs privs;
370  static struct {XrdAccPrivs pcode; char plet;} p2l[] =
371  {{XrdAccPriv_Delete, 'd'},
372  {XrdAccPriv_Insert, 'i'},
373  {XrdAccPriv_Lock, 'k'},
374  {XrdAccPriv_Lookup, 'l'},
375  {XrdAccPriv_Rename, 'n'},
376  {XrdAccPriv_Read, 'r'},
377  {XrdAccPriv_Write, 'w'}
378  };
379  static int p2lnum = sizeof(p2l)/sizeof(p2l[0]);
380 
381  privs = ctab.pprivs;
382  while(k--)
383  {for (j = 0; j < p2lnum && i < bmax; j++)
384  if (privs & p2l[j].pcode) buff[i++] = p2l[j].plet;
385  if (i < bmax && ctab.nprivs != XrdAccPriv_None) buff[i++] = '-';
386  else break;
387  privs = ctab.nprivs;
388  }
389  buff[i] = '\0';
390  return buff;
391 }
XrdAccAuthorize * XrdAccDefaultAuthorizeObject(XrdSysLogger *lp, const char *cfn, const char *parm, XrdVersionInfo &urVer)
Definition: XrdAccAccess.cc:64
Access_Operation
The following are supported operations.
@ AOP_Delete
rm() or rmdir()
@ AOP_Mkdir
mkdir()
@ AOP_Update
open() r/w or append
@ AOP_Create
open() with create
@ AOP_Readdir
opendir()
@ AOP_Chmod
chmod()
@ AOP_Any
Special for getting privs.
@ AOP_Stat
exists(), stat()
@ AOP_Rename
mv() for source
@ AOP_Read
open() r/o, prepare()
@ AOP_Excl_Create
open() with O_EXCL|O_CREAT
@ AOP_Lock
n/a
@ AOP_Chown
chown()
@ AOP_Excl_Insert
mv() where destination doesn't exist.
XrdAccPrivs
Definition: XrdAccPrivs.hh:39
@ XrdAccPriv_Insert
Definition: XrdAccPrivs.hh:44
@ XrdAccPriv_Lookup
Definition: XrdAccPrivs.hh:47
@ XrdAccPriv_Rename
Definition: XrdAccPrivs.hh:48
@ XrdAccPriv_Read
Definition: XrdAccPrivs.hh:49
@ XrdAccPriv_Lock
Definition: XrdAccPrivs.hh:45
@ XrdAccPriv_None
Definition: XrdAccPrivs.hh:53
@ XrdAccPriv_Write
Definition: XrdAccPrivs.hh:51
@ XrdAccPriv_Delete
Definition: XrdAccPrivs.hh:43
int extra
Definition: XrdAccTest.cc:63
Access_Operation cmd2op(char *opname)
Definition: XrdAccTest.cc:353
int main(int argc, char **argv)
Definition: XrdAccTest.cc:152
void ZapEntity()
Definition: XrdAccTest.cc:133
void Usage(const char *msg)
Definition: XrdAccTest.cc:105
Access_Operation oper
Definition: XrdAccTest.cc:81
char * PrivsConvert(XrdAccPrivCaps &ctab, char *buff, int blen)
Definition: XrdAccTest.cc:366
int DoIt(int argpnt, int argc, char **argv, bool singleshot)
Definition: XrdAccTest.cc:262
optab_t optab[]
Definition: XrdAccTest.cc:82
void SetID(char *&dest, char *val)
Definition: XrdAccTest.cc:123
XrdAccAuthorize * Authorize
Definition: XrdAccTest.cc:61
XrdSysLogger myLogger
Definition: XrdAccTest.cc:65
int opcnt
Definition: XrdAccTest.cc:99
#define tident
int optind
virtual XrdAccPrivs Access(const XrdSecEntity *Entity, const char *path, const Access_Operation oper, XrdOucEnv *Env=0)=0
static int Export(const char *Var, const char *Val)
Definition: XrdOucEnv.cc:188
char * GetLine()
int Attach(int FileDescriptor, int bsz=2047)
char * GetToken(int lowcase=0)
XrdVERSIONINFODEF(myVersion, cmsclient, XrdVNUMBER, XrdVERSION)
XrdAccPrivs nprivs
Definition: XrdAccPrivs.hh:78
XrdAccPrivs pprivs
Definition: XrdAccPrivs.hh:77