XRootD
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 
37 #include "XrdAcc/XrdAccAuthFile.hh"
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 
89 int 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 
145 char XrdAccAuthFile::getID(char **id)
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 
194 int 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 
258 char 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 
325 int 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 
371 int 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 
388 char *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)
int stat(const char *path, struct stat *buf)
int open(const char *path, int oflag,...)
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)
char * GetWord(int lowcase=0)
int Attach(int FileDescriptor, int bsz=2047)
void Close(int hold=0)
void SetEroute(XrdSysError *eroute)
void Tabs(int x=1)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95