XRootD
Loading...
Searching...
No Matches
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
47#include "XrdAcc/XrdAccPrivs.hh"
48#include "XrdSys/XrdSysError.hh"
51#include "XrdNet/XrdNetAddr.hh"
52#include "XrdOuc/XrdOucEnv.hh"
54
55/******************************************************************************/
56/* G l o b a l O b j e c t s */
57/******************************************************************************/
58
59char *PrivsConvert(XrdAccPrivCaps &ctab, char *buff, int blen);
60
62
64
66
67XrdSysError eroute(&myLogger, "acc_");
68
69namespace
70{
71XrdSecEntity Entity("host");
72
73XrdNetAddr netAddr;
74
75bool v2 = false;
76}
77
78/******************************************************************************/
79/* O p e r a t i o n T a b l e */
80/******************************************************************************/
81typedef 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
99int opcnt = sizeof(optab)/sizeof(optab[0]);
100
101/******************************************************************************/
102/* U s a g e */
103/******************************************************************************/
104
105void 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
123void 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
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
152int main(int argc, char **argv)
153{
154static XrdVERSIONINFODEF(myVer, XrdAccTest, XrdVNUMBER, XrdVERSION);
155extern int optind;
156extern char *optarg;
158 const char *cfn,
159 const char *parm,
160 XrdVersionInfo &myVer);
161int DoIt(int argpnt, int argc, char **argv, bool singleshot);
162
163const char *cfHost = "localhost", *cfProg = "xrootd";
164char *p2l(XrdAccPrivs priv, char *buff, int blen);
165char *argval[32], buff[255], tident[80], c;
166int DoIt(int argnum, int argc, char **argv, int singleshot);
167XrdOucStream Command;
168const int maxargs = sizeof(argval)/sizeof(argval[0]);
169char *at, *lp, *ConfigFN = (char *)"./acc.cf";
170int argnum, rc = 0;
171bool 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//
214if (!(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
262int DoIt(int argpnt, int argc, char **argv, bool singleshot)
263{
264char *opc, *opv, *path, *result, buff[80];
265Access_Operation cmd2op(char *opname);
266void Usage(const char *);
267Access_Operation optype;
268XrdAccPrivCaps pargs;
269XrdAccPrivs 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
346return 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
366char *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)
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
@ XrdAccPriv_Insert
@ XrdAccPriv_Lookup
@ XrdAccPriv_Rename
@ XrdAccPriv_Read
@ XrdAccPriv_Lock
@ XrdAccPriv_None
@ XrdAccPriv_Write
@ XrdAccPriv_Delete
int extra
Definition XrdAccTest.cc:63
Access_Operation cmd2op(char *opname)
int main(int argc, char **argv)
void ZapEntity()
void Usage(const char *msg)
Access_Operation oper
Definition XrdAccTest.cc:81
char * PrivsConvert(XrdAccPrivCaps &ctab, char *buff, int blen)
int DoIt(int argpnt, int argc, char **argv, bool singleshot)
optab_t optab[]
Definition XrdAccTest.cc:82
XrdAccAuthorize * Authorize
Definition XrdAccTest.cc:61
XrdSysLogger myLogger
Definition XrdAccTest.cc:65
int opcnt
Definition XrdAccTest.cc:99
#define tident
static XrdVERSIONINFODEF(compiledVer, XrdHttpProtocolTest, XrdVNUMBER, XrdVERSION)
int optind
bool SetID
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:170
char * GetLine()
int Attach(int FileDescriptor, int bsz=2047)
char * GetToken(int lowcase=0)
XrdAccPrivs nprivs
XrdAccPrivs pprivs