XRootD
Loading...
Searching...
No Matches
XrdDigAuth.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d D i g A u t h . c c */
4/* */
5/* (C) 2013 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 Deprtment 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 <fcntl.h>
34#include <cstdio>
35#include <cstdlib>
36#include <strings.h>
37#include <sys/param.h>
38#include <sys/stat.h>
39
40#include "XrdDig/XrdDigAuth.hh"
41
43
45
46#include "XrdSys/XrdSysE2T.hh"
47#include "XrdSys/XrdSysError.hh"
48
49/******************************************************************************/
50/* d e f i n e s */
51/******************************************************************************/
52
53#define TS_Xeq(x,m) if (!strcmp(x,var)) return m(Config);
54
55/******************************************************************************/
56/* G l o b a l S t a t i c O b j e c t s */
57/******************************************************************************/
58
59namespace XrdDig
60{
61 extern XrdSysError *eDest;
62
64};
65
66using namespace XrdDig;
67
68/******************************************************************************/
69/* S t a t i c L o c a l V a l u e s */
70/******************************************************************************/
71
72namespace
73{
74 const char eVec[] = "nhorg";
75
76 struct aToks {const char *aTok; XrdDigAuthEnt::aType aRef;} aTab[] =
77 {{"conf", XrdDigAuthEnt::aConf},
78 {"core", XrdDigAuthEnt::aCore},
79 {"logs", XrdDigAuthEnt::aLogs},
80 {"proc", XrdDigAuthEnt::aProc}
81 };
82
83};
84
85/******************************************************************************/
86/* A u t h o r i z e */
87/******************************************************************************/
88
91 bool aVec[XrdDigAuthEnt::aNum]
92 )
93{
94 XrdSysMutexHelper mHelp(&authMutex);
95 time_t tNow = time(0);
96 XrdDigAuthEnt *aP;
97 int rc;
98
99// Check if we need to refresh the auth list
100//
101 if (tNow >= authCHK)
102 {struct stat Stat;
103 if ((rc = stat(authFN, &Stat)) && errno != ENOENT)
104 {eDest->Emsg("Config",errno,"stat dig auth file", authFN);
105 authCHK = tNow + 30;
106 } else {
107 if (rc) {if (authList) {if (!Refresh()) authCHK = tNow + 30;}
108 else authCHK = tNow + 60;
109 }
110 else if (authTOD == Stat.st_mtime) authCHK = tNow + 5;
111 else if (!Refresh()) authCHK = tNow + 30;
112 }
113 }
114
115// Clear aVec if so supplied (client's auth mask)
116//
117 if (aVec) memset(aVec, false, XrdDigAuthEnt::aNum);
118
119// Check if we have anything to authorize with
120//
121 if (!authList) return false;
122
123// Check if we are granting access to this resouce at all
124//
125 if (aType != XrdDigAuthEnt::aNum && !accOK[aType]) return false;
126
127// Go through the access list and try to match the client
128//
129 aP = authList;
130 while(aP)
131 {do {if (strcmp(client->prot, aP->prot)) break;
132 if (aP->eChk[XrdDigAuthEnt::eName] && (!client->name ||
133 strcmp(client->name, aP->eChk[XrdDigAuthEnt::eName]))) break;
134
136 && strcmp(client->addrInfo->Name(""),
137 aP->eChk[XrdDigAuthEnt::eHost])) break;
138
139 if (aP->eChk[XrdDigAuthEnt::eVorg] && (!client->vorg ||
140 strcmp(client->vorg, aP->eChk[XrdDigAuthEnt::eVorg]))) break;
141
142 if (aP->eChk[XrdDigAuthEnt::eRole] && (!client->role ||
143 strcmp(client->role, aP->eChk[XrdDigAuthEnt::eRole]))) break;
144
145 if (aP->eChk[XrdDigAuthEnt::eGrp ] && (!client->grps ||
146 !OkGrp(client->grps, aP->eChk[XrdDigAuthEnt::eGrp ]))) break;
147
148 if (aVec) memcpy(aVec, aP->accOK, XrdDigAuthEnt::aNum);
149 return (aType == XrdDigAuthEnt::aNum ? false : aP->accOK[aType]);
150 } while(1);
151 aP = aP->next;
152 }
153
154// Client failed the test
155//
156 return false;
157}
158
159/******************************************************************************/
160/* C o n f i g u r e */
161/******************************************************************************/
162
163bool XrdDigAuth::Configure(const char *aFN)
164{
165/*
166 Function: Configure authorization (one time call).
167
168 Input: None.
169
170 Output: true upon success or false otherwise.
171*/
172
173// Establish the location of the auth file (stable string do not copy)
174//
175 if (!aFN || !(*aFN))
176 {eDest->Emsg("Config", "Dig authorization file not specified.");
177 return false;
178 }
179
180// Initialize authorization
181//
182 authFN = strdup(aFN);
183 SetupAuth(false);
184 return true;
185}
186
187/******************************************************************************/
188/* Private: F a i l u r e */
189/******************************************************************************/
190
191bool XrdDigAuth::Failure(int lNum, const char *txt1, const char *txt2)
192{
193 char buff[256];
194
195 sprintf(buff, "Error in dig authfile line %d:", lNum);
196 eDest->Emsg("Auth", buff, txt1, txt2);
197 return false;
198}
199
200/******************************************************************************/
201/* Private: O k G r p */
202/******************************************************************************/
203
204bool XrdDigAuth::OkGrp(const char *glist, const char *gname)
205{
206 const char *ghit;
207 int glen = strlen(gname);
208
209// Attempt to find a match in the list
210//
211 do {if (!(ghit = strstr(glist, gname))) return false;
212 ghit += glen;
213 if (!(*ghit) || *ghit == ' ') return true;
214 glist = ghit;
215 } while(1);
216 return false;
217}
218
219/******************************************************************************/
220/* Private: P a r s e */
221/******************************************************************************/
222
223bool XrdDigAuth::Parse(XrdOucStream &aFile, int lNum)
224{
225 struct aEntHelper
226 {XrdDigAuthEnt *eP;
227 aEntHelper() {eP = new XrdDigAuthEnt;}
228 ~aEntHelper() {if (eP) delete eP;}
229 } aEnt;
230 static const char *eCode;
231 char buff[4096];
232 char *var, *rec, *bP = buff;
233 int k, n, bLeft = sizeof(buff);
234 bool aOK = false, tfVal;
235
236// Get the record type tokens first
237//
238 while((var = aFile.GetToken()) && *var)
239 { if (!strcmp(var, "all"))
240 {for (k = 0; k < (int)XrdDigAuthEnt::aNum; k++)
241 aEnt.eP->accOK[k] = true;
242 aOK = true; continue;
243 }
244 else if (!strcmp(var, "allow")) break;
245 else{if (*var == '-') {tfVal = false; var++;}
246 else tfVal = true;
247
248 for (n = 0; n < (int)XrdDigAuthEnt::aNum; n++)
249 if (!strcmp(var, aTab[n].aTok))
250 {aEnt.eP->accOK[aTab[n].aRef] = tfVal; aOK = true; break;}
251
252 if (n >= (int)XrdDigAuthEnt::aNum)
253 return Failure(lNum, "Invalid token -", var);
254 }
255 }
256
257
258// Make sure a type has been specified
259//
260 if (!aOK) return Failure(lNum, "Information type not specified.");
261
262// Now scan for the security protocol
263//
264 if (!(var = aFile.GetToken()) || !(*var))
265 return Failure(lNum, "Auth protocol not specified.");
266
267// Make sure it is not too big
268//
269 if (strlen(var) >= sizeof(aEnt.eP->prot))
270 return Failure(lNum, "Invalid auth protocol -", var);
271 strcpy(aEnt.eP->prot, var);
272
273// Now start getting the auth values
274//
275 aOK = false;
276 while((var = aFile.GetToken()) && *var)
277 {if (!(eCode = index(eVec, *var))) // "nhorg" lookup
278 return Failure(lNum, "Invalid entity type -", var);
279 if (*(var+1) != '=' || !*(var+2))
280 return Failure(lNum, "Badly formed entity value in", var);
281 n = snprintf(bP, bLeft, "%s", var+2) + 1;
282 if ((bLeft -= n) <= 0) break;
283 if ((var = index(bP, '\\'))) Squash(var);
284 aEnt.eP->eChk[eCode-eVec] = bP; bP += n;
285 aOK = true;
286 }
287
288// Check if we over-ran the buffer
289//
290 if (bLeft <= 0) return Failure(lNum, "Too many auth values.");
291
292// Make sure we have somthing here
293//
294 if (!aOK) return Failure(lNum, "No entity values specified.");
295
296// Create composite mask (we assume no memory failures)
297//
298 aOK = false;
299 for (n = 0; n < (int)XrdDigAuthEnt::aNum; n++)
300 if (aEnt.eP->accOK[n]) accOK[n] = aOK = true;
301 if(!aOK) return Failure(lNum, "Entity has no effective access.");
302
303// Allocate a new value record
304//
305 if (!(rec = (char *)malloc(bP-buff)))
306 return Failure(lNum, "Insufficient memory.");
307 memcpy(rec, buff, bP-buff);
308 aEnt.eP->rec = rec;
309
310// Relocate pointers
311//
312 for (k = (int)XrdDigAuthEnt::eName; k < (int)XrdDigAuthEnt::eNum; k++)
313 {if (aEnt.eP->eChk[k])
314 aEnt.eP->eChk[k] = rec + (aEnt.eP->eChk[k] - buff);
315 }
316
317// Chain this record into the record list and return success
318//
319 aEnt.eP->next = authList;
320 authList = aEnt.eP;
321 aEnt.eP = 0;
322 return true;
323}
324
325/******************************************************************************/
326/* Private: R e f r e s h */
327/******************************************************************************/
328
329bool XrdDigAuth::Refresh() // authMutex must be locked!
330{
331 XrdDigAuthEnt *aP, *nP = authList;
332
333// Delete the current auth list
334//
335 while((aP = nP)) {nP = aP->next; delete aP;}
336 authList = 0;
337
338// Resetup the auth list
339//
340 return SetupAuth(true);
341}
342
343/******************************************************************************/
344/* Private: S e t u p A u t h */
345/******************************************************************************/
346
347bool XrdDigAuth::SetupAuth(bool isRefresh)
348{
349 XrdOucStream aFile(eDest);
350 struct stat Stat;
351 char *line;
352 int authFD, retc, lNum = 1;
353 bool NoGo = false;
354
355// Clear summary flags
356//
357 memset(accOK, 0, sizeof(accOK));
358
359// Print message
360//
361 eDest->Say("++++++ Dig ", (isRefresh ? "refreshing" : "initializing"),
362 " from ", authFN);
363
364// Try to open the configuration file.
365//
366 if ( (authFD = open(authFN, O_RDONLY, 0)) < 0)
367 {NoGo = errno != ENOENT;
368 eDest->Say("Config ",XrdSysE2T(errno)," opening dig auth file ",authFN);
369 return SetupAuth(isRefresh, !NoGo);
370 }
371 aFile.Attach(authFD, 4096);
372
373// Get the time the file was ctreated
374//
375 if (fstat(authFD, &Stat))
376 {eDest->Say("Config ",XrdSysE2T(errno)," stating dig auth file ",authFN);
377 close(authFD);
378 return SetupAuth(isRefresh, false);
379 }
380 authTOD = Stat.st_mtime;
381
382// Now start reading records until eof.
383//
384 while((line = aFile.GetLine()))
385 {if (*line && *line != '#') NoGo |= !Parse(aFile, lNum);
386 lNum++;
387 }
388
389// Now check if any errors occurred during file i/o
390//
391 if ((retc = aFile.LastError()))
392 {eDest->Say("Config ",XrdSysE2T(-retc)," reading config file ",authFN);
393 NoGo = true;
394 }
395 aFile.Close();
396
397// All done
398//
399 return SetupAuth(isRefresh, !NoGo);
400}
401
402/******************************************************************************/
403
404bool XrdDigAuth::SetupAuth(bool isRefresh, bool aOK)
405{
406
407// Indicate whether we are active or not
408//
409 if (!authList) eDest->Say("Config ","No users authorized to access digFS; "
410 "access suspended.");
411
412// All done
413//
414 eDest->Say("------ Dig auth ", (isRefresh ? "refresh" : "initialization"),
415 (aOK ? " succeeded." : " encountered errors."));
416
417 return aOK;
418}
419
420/******************************************************************************/
421/* Private: S q u a s h */
422/******************************************************************************/
423
424void XrdDigAuth::Squash(char *bP)
425{
426
427// Insert spaces where needed
428//
429 do {if (*(bP+1) == 's') {*bP = ' '; strcpy(bP+1, bP+2);}
430 } while((bP = index(bP+1, '\\')));
431}
struct stat Stat
Definition XrdCks.cc:49
static XrdSysError eDest(0,"crypto_")
#define close(a)
Definition XrdPosix.hh:43
#define fstat(a, b)
Definition XrdPosix.hh:57
#define open
Definition XrdPosix.hh:71
#define stat(a, b)
Definition XrdPosix.hh:96
const char * XrdSysE2T(int errcode)
Definition XrdSysE2T.cc:104
char prot[XrdSecPROTOIDSIZE]
Definition XrdDigAuth.hh:48
char * eChk[eNum]
Definition XrdDigAuth.hh:51
XrdDigAuthEnt * next
Definition XrdDigAuth.hh:46
bool accOK[aNum]
Definition XrdDigAuth.hh:54
bool Authorize(const XrdSecEntity *client, XrdDigAuthEnt::aType aType, bool aVec[XrdDigAuthEnt::aNum]=0)
Definition XrdDigAuth.cc:89
bool Configure(const char *aFN)
const char * Name(const char *eName=0, const char **eText=0)
char * GetLine()
int Attach(int FileDescriptor, int bsz=2047)
void Close(int hold=0)
char * GetToken(int lowcase=0)
char * vorg
Entity's virtual organization(s)
XrdNetAddrInfo * addrInfo
Entity's connection details.
char prot[XrdSecPROTOIDSIZE]
Auth protocol used (e.g. krb5)
char * grps
Entity's group name(s)
char * name
Entity's name.
char * role
Entity's role(s)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
XrdDigAuth Auth
Definition XrdDigAuth.cc:63
XrdSysError * eDest