XRootD
Loading...
Searching...
No Matches
XrdAccAuthFile.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d A c c A u t h F i l e . c c */
4/* */
5/* (c) 2003 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 <cerrno>
32#include <fcntl.h>
33#include <cstring>
34#include <strings.h>
35#include <sys/stat.h>
36
38
39/******************************************************************************/
40/* X r d A c c A u t h D B _ O b j e c t */
41/******************************************************************************/
42
44{
45 static XrdAccAuthFile mydatabase(erp);
46
47 return (XrdAccAuthDB *)&mydatabase;
48}
49
50/******************************************************************************/
51/* C o n s t r u c t o r */
52/******************************************************************************/
53
55{
56
57// Set starting values
58//
59 authfn = 0;
60 flags = Noflags;
61 modtime = 0;
62 Eroute = erp;
63
64// Setup for an error in the first record
65//
66 strcpy(path_buff, "start of file");
67}
68
69/******************************************************************************/
70/* D e s t r u c t o r */
71/******************************************************************************/
72
74{
75
76// If the file is open, close it
77//
78 if (flags &isOpen) Close();
79
80// Free the authfn string
81//
82 if (authfn) free(authfn);
83}
84
85/******************************************************************************/
86/* C h a n g e d */
87/******************************************************************************/
88
89int XrdAccAuthFile::Changed(const char *dbfn)
90{
91 struct stat statbuff;
92
93// If no file here, indicate nothing changed
94//
95 if (!authfn || !*authfn) return 0;
96
97// If file paths differ, indicate that something has changed
98//
99 if (dbfn && strcmp(dbfn, authfn)) return 1;
100
101// Get the modification timestamp for this file
102//
103 if (stat(authfn, &statbuff))
104 {Eroute->Emsg("AuthFile", errno, "find", authfn);
105 return 0;
106 }
107
108// Indicate whether or not the file has changed
109//
110 return (modtime < statbuff.st_mtime);
111}
112
113/******************************************************************************/
114/* C l o s e */
115/******************************************************************************/
116
118{
119// Return is the file is not open
120//
121 if (!(flags & isOpen)) return 1;
122
123// Close the stream
124//
125 DBfile.Close();
126
127// Unlock the protecting mutex
128//
129 DBcontext.UnLock();
130
131// Indicate file is no longer open
132//
133 flags = (DBflags)(flags & ~isOpen);
134
135// Return indicator of whether we had any errors
136//
137 if (flags & dbError) return 0;
138 return 1;
139}
140
141/******************************************************************************/
142/* g e t I D */
143/******************************************************************************/
144
146{
147 char *pp, idcode[2] = {0,0};
148
149// If a record has not been read, return end of record (i.e., 0)
150//
151 if (!(flags & inRec)) return 0;
152
153// Read the next word from the record (if none, simulate end of record)
154//
155 if (!(pp = DBfile.GetWord()))
156 {flags = (DBflags)(flags & ~inRec);
157 return 0;
158 }
159
160// Id's are of the form 'c', but historically they were 'c:' so we accept a
161// two character specification but only validate the first to be backward
162// compatible.
163//
164 if (strlen(pp) > 2 || !index("ghoru", *pp))
165 {Eroute->Emsg("AuthFile", "Invalid ID sprecifier -", pp);
166 flags = (DBflags)(flags | dbError);
167 return 0;
168 }
169 idcode[0] = *pp;
170
171// Now get the actual id associated with it
172//
173 if (!(pp = DBfile.GetWord()))
174 {flags = (DBflags)(flags & ~inRec);
175 Eroute->Emsg("AuthFile", "ID value missing after", idcode);
176 flags = (DBflags)(flags | dbError);
177 return 0;
178 }
179
180// Copy the value since the stream buffer might get overlaid.
181//
182 Copy(path_buff, pp, sizeof(path_buff)-1);
183
184// Return result
185//
186 *id = path_buff;
187 return idcode[0];
188}
189
190/******************************************************************************/
191/* g e t P P */
192/******************************************************************************/
193
194int XrdAccAuthFile::getPP(char **path, char **priv, bool &istmplt)
195{
196// char *pp, *bp;
197 char *pp;
198
199// If a record has not been read, return end of record (i.e., 0)
200//
201 if (!(flags & inRec)) return 0;
202
203// read the next word from the record (if none, simulate end of record)
204//
205 if (!(pp = DBfile.GetWord()))
206 {flags = (DBflags)(flags & ~inRec);
207 return 0;
208 }
209
210// Check of objectid specification
211//
212 istmplt = false;
213 *path = path_buff;
214 if (*pp == '\\')
215 {if (*(pp+1)) pp++;
216 else {Eroute->Emsg("AuthFile", "Object ID missing after '\\'");
217 *path = 0;
218 flags = (DBflags)(flags | dbError);
219 }
220 } else if (*pp != '/') istmplt = true;
221
222// Copy the value since the stream buffer might get overlaid.
223//
224// bp = Copy(path_buff, pp, sizeof(path_buff)-1);
225 if (path) Copy(path_buff, pp, sizeof(path_buff)-1);
226
227// Check if this is really a path or a template
228//
229 if (istmplt) {*priv = (char *)0; return 1;}
230
231// Verify that the path ends correctly (normally we would force a slash to
232// appear at the end but that prevents caps on files. So, we commented the
233// code out until we decide that maybe we really need to do this, sigh.
234//
235// bp--;
236// if (*bp != '/') {bp++; *bp = '/'; bp++; *bp = '\0';}
237
238// Get the next word which should be the privilege string
239//
240 if (!(pp = DBfile.GetWord()))
241 {flags = (DBflags)(flags & ~inRec);
242 Eroute->Emsg("AuthFile", "Privileges missing after", path_buff);
243 flags = (DBflags)(flags | dbError);
244 *priv = (char *)0;
245 return 0;
246 }
247
248// All done here
249//
250 *priv = pp;
251 return 1;
252}
253
254/******************************************************************************/
255/* g e t R e c */
256/******************************************************************************/
257
258char XrdAccAuthFile::getRec(char **recname)
259{
260 char *pp;
261 int idok;
262
263// Do this until we get a vlaid record
264//
265 while(1)
266 {
267 // If we arer still in the middle of a record, flush it
268 //
269 if (flags & inRec) while(DBfile.GetWord()) {}
270 else flags = (DBflags)(flags | inRec);
271
272 // Get the next word, the record type
273 //
274 if (!(pp = DBfile.GetWord()))
275 {*recname = (char *)0; return '\0';}
276
277 // Verify the id-type
278 //
279 idok = 0;
280 if (strlen(pp) == 1)
281 switch(*pp)
282 {case 'g':
283 case 'h':
284 case 's':
285 case 'n':
286 case 'o':
287 case 'r':
288 case 't':
289 case 'u':
290 case 'x':
291 case '=': idok = 1;
292 break;
293 default: break;
294 }
295
296 // Check if the record type was valid
297 //
298 if (!idok) {Eroute->Emsg("AuthFile", "Invalid id type -", pp);
299 flags = (DBflags)(flags | dbError);
300 continue;
301 }
302 rectype = *pp;
303
304 // Get the record name. It must exist
305 //
306 if (!(pp = DBfile.GetWord()))
307 {Eroute->Emsg("AuthFile","Record name is missing after",path_buff);
308 flags = (DBflags)(flags | dbError);
309 continue;
310 }
311
312 // Copy the record name
313 //
314 Copy(recname_buff, pp, sizeof(recname_buff));
315 *recname = recname_buff;
316 return rectype;
317 }
318 return '\0'; // Keep the compiler happy :-)
319}
320
321/******************************************************************************/
322/* O p e n */
323/******************************************************************************/
324
325int XrdAccAuthFile::Open(XrdSysError &eroute, const char *path)
326{
327 struct stat statbuff;
328 int authFD;
329
330// Enter the DB context (serialize use of this database)
331//
332 DBcontext.Lock();
333 Eroute = &eroute;
334
335// Use whichever path is the more recent
336//
337 if (path)
338 {if (authfn) free(authfn); authfn = strdup(path);}
339 if( !authfn || !*authfn) return Bail(0, "Authorization file not specified.");
340
341// Get the modification timestamp for this file
342//
343 if (stat(authfn, &statbuff)) return Bail(errno, "find", authfn);
344
345// Try to open the authorization file.
346//
347 if ( (authFD = open(authfn, O_RDONLY, 0)) < 0)
348 return Bail(errno,"open authorization file",authfn);
349
350// Copy in all the relevant information
351//
352 modtime = statbuff.st_mtime;
353 flags = isOpen;
354 DBfile.SetEroute(Eroute);
355 DBfile.Tabs(0);
356
357// Attach the file to the stream
358//
359 if (DBfile.Attach(authFD))
360 return Bail(DBfile.LastError(), "initialize stream for", authfn);
361 return 1;
362}
363
364/******************************************************************************/
365/* P r i v a t e M e t h o d s */
366/******************************************************************************/
367/******************************************************************************/
368/* B a i l */
369/******************************************************************************/
370
371int XrdAccAuthFile::Bail(int retc, const char *txt1, const char *txt2)
372{
373// This routine is typically used by open and the DBcontext lock must be held
374//
375 flags = (DBflags)(flags & ~isOpen);
376 DBcontext.UnLock();
377 if (retc) Eroute->Emsg("AuthFile", retc, txt1, txt2);
378 else Eroute->Emsg("AuthFile", txt1, txt2);
379 return 0;
380}
381
382/******************************************************************************/
383/* C o p y */
384/******************************************************************************/
385
386// This routine is used instead of strncpy because, frankly, it's a lot smarter
387
388char *XrdAccAuthFile::Copy(char *dp, char *sp, int dplen)
389{
390 // Copy one less that the size of the buffer so that we have room for null
391 //
392 while(--dplen && *sp) {*dp = *sp; dp++; sp++;}
393
394// Insert a null character and return a pointer to it.
395//
396 *dp = '\0';
397 return dp;
398}
XrdAccAuthDB * XrdAccAuthDBObject(XrdSysError *erp)
#define open
Definition XrdPosix.hh:76
#define stat(a, b)
Definition XrdPosix.hh:101
char getRec(char **recname)
int Open(XrdSysError &eroute, const char *path=0)
int Changed(const char *dbpath)
XrdAccAuthFile(XrdSysError *erp)
int getPP(char **path, char **priv, bool &istmplt)
char getID(char **id)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)