/******************************************************************************/ /* */ /* X r d A c c A u t h F i l e . c c */ /* */ /* (c) 2003 by the Board of Trustees of the Leland Stanford, Jr., University */ /* All Rights Reserved */ /* Produced by Andrew Hanushevsky for Stanford University under contract */ /* DE-AC02-76-SFO0515 with the Department of Energy */ /* */ /* This file is part of the XRootD software suite. */ /* */ /* XRootD is free software: you can redistribute it and/or modify it under */ /* the terms of the GNU Lesser General Public License as published by the */ /* Free Software Foundation, either version 3 of the License, or (at your */ /* option) any later version. */ /* */ /* XRootD is distributed in the hope that it will be useful, but WITHOUT */ /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */ /* License for more details. */ /* */ /* You should have received a copy of the GNU Lesser General Public License */ /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ /* COPYING (GPL license). If not, see . */ /* */ /* The copyright holder's institutional names and contributor's names may not */ /* be used to endorse or promote products derived from this software without */ /* specific prior written permission of the institution or contributor. */ /******************************************************************************/ #include #include #include #include #include #include "XrdAcc/XrdAccAuthFile.hh" /******************************************************************************/ /* X r d A c c A u t h D B _ O b j e c t */ /******************************************************************************/ XrdAccAuthDB *XrdAccAuthDBObject(XrdSysError *erp) { static XrdAccAuthFile mydatabase(erp); return (XrdAccAuthDB *)&mydatabase; } /******************************************************************************/ /* C o n s t r u c t o r */ /******************************************************************************/ XrdAccAuthFile::XrdAccAuthFile(XrdSysError *erp) { // Set starting values // authfn = 0; flags = Noflags; modtime = 0; Eroute = erp; // Setup for an error in the first record // strcpy(path_buff, "start of file"); } /******************************************************************************/ /* D e s t r u c t o r */ /******************************************************************************/ XrdAccAuthFile::~XrdAccAuthFile() { // If the file is open, close it // if (flags &isOpen) Close(); // Free the authfn string // if (authfn) free(authfn); } /******************************************************************************/ /* C h a n g e d */ /******************************************************************************/ int XrdAccAuthFile::Changed(const char *dbfn) { struct stat statbuff; // If no file here, indicate nothing changed // if (!authfn || !*authfn) return 0; // If file paths differ, indicate that something has changed // if (dbfn && strcmp(dbfn, authfn)) return 1; // Get the modification timestamp for this file // if (stat(authfn, &statbuff)) {Eroute->Emsg("AuthFile", errno, "find", authfn); return 0; } // Indicate whether or not the file has changed // return (modtime < statbuff.st_mtime); } /******************************************************************************/ /* C l o s e */ /******************************************************************************/ int XrdAccAuthFile::Close() { // Return is the file is not open // if (!(flags & isOpen)) return 1; // Close the stream // DBfile.Close(); // Unlock the protecting mutex // DBcontext.UnLock(); // Indicate file is no longer open // flags = (DBflags)(flags & ~isOpen); // Return indicator of whether we had any errors // if (flags & dbError) return 0; return 1; } /******************************************************************************/ /* g e t I D */ /******************************************************************************/ char XrdAccAuthFile::getID(char **id) { char *pp, idcode[2] = {0,0}; // If a record has not been read, return end of record (i.e., 0) // if (!(flags & inRec)) return 0; // Read the next word from the record (if none, simulate end of record) // if (!(pp = DBfile.GetWord())) {flags = (DBflags)(flags & ~inRec); return 0; } // Id's are of the form 'c:', make sure we have that (don't validate it) // if (strlen(pp) != 2 || !index("ghoru", *pp)) {Eroute->Emsg("AuthFile", "Invalid ID sprecifier -", pp); flags = (DBflags)(flags | dbError); return 0; } idcode[0] = *pp; // Now get the actual id associated with it // if (!(pp = DBfile.GetWord())) {flags = (DBflags)(flags & ~inRec); Eroute->Emsg("AuthFile", "ID value missing after", idcode); flags = (DBflags)(flags | dbError); return 0; } // Copy the value since the stream buffer might get overlaid. // Copy(path_buff, pp, sizeof(path_buff)-1); // Return result // *id = path_buff; return idcode[0]; } /******************************************************************************/ /* g e t P P */ /******************************************************************************/ int XrdAccAuthFile::getPP(char **path, char **priv, bool &istmplt) { // char *pp, *bp; char *pp; // If a record has not been read, return end of record (i.e., 0) // if (!(flags & inRec)) return 0; // read the next word from the record (if none, simulate end of record) // if (!(pp = DBfile.GetWord())) {flags = (DBflags)(flags & ~inRec); return 0; } // Check of objectid specification // istmplt = false; *path = path_buff; if (*pp == '\\') {if (*(pp+1)) pp++; else {Eroute->Emsg("AuthFile", "Object ID missing after '\\'"); *path = 0; flags = (DBflags)(flags | dbError); } } else if (*pp != '/') istmplt = true; // Copy the value since the stream buffer might get overlaid. // // bp = Copy(path_buff, pp, sizeof(path_buff)-1); if (path) Copy(path_buff, pp, sizeof(path_buff)-1); // Check if this is really a path or a template // if (istmplt) {*priv = (char *)0; return 1;} // Verify that the path ends correctly (normally we would force a slash to // appear at the end but that prevents caps on files. So, we commented the // code out until we decide that maybe we really need to do this, sigh. // // bp--; // if (*bp != '/') {bp++; *bp = '/'; bp++; *bp = '\0';} // Get the next word which should be the privilege string // if (!(pp = DBfile.GetWord())) {flags = (DBflags)(flags & ~inRec); Eroute->Emsg("AuthFile", "Privileges missing after", path_buff); flags = (DBflags)(flags | dbError); *priv = (char *)0; return 0; } // All done here // *priv = pp; return 1; } /******************************************************************************/ /* g e t R e c */ /******************************************************************************/ char XrdAccAuthFile::getRec(char **recname) { char *pp; int idok; // Do this until we get a vlaid record // while(1) { // If we arer still in the middle of a record, flush it // if (flags & inRec) while(DBfile.GetWord()) {} else flags = (DBflags)(flags | inRec); // Get the next word, the record type // if (!(pp = DBfile.GetWord())) {*recname = (char *)0; return '\0';} // Verify the id-type // idok = 0; if (strlen(pp) == 1) switch(*pp) {case 'g': case 'h': case 's': case 'n': case 'o': case 'r': case 't': case 'u': case 'x': case '=': idok = 1; break; default: break; } // Check if the record type was valid // if (!idok) {Eroute->Emsg("AuthFile", "Invalid id type -", pp); flags = (DBflags)(flags | dbError); continue; } rectype = *pp; // Get the record name. It must exist // if (!(pp = DBfile.GetWord())) {Eroute->Emsg("AuthFile","Record name is missing after",path_buff); flags = (DBflags)(flags | dbError); continue; } // Copy the record name // Copy(recname_buff, pp, sizeof(recname_buff)); *recname = recname_buff; return rectype; } return '\0'; // Keep the compiler happy :-) } /******************************************************************************/ /* O p e n */ /******************************************************************************/ int XrdAccAuthFile::Open(XrdSysError &eroute, const char *path) { struct stat statbuff; int authFD; // Enter the DB context (serialize use of this database) // DBcontext.Lock(); Eroute = &eroute; // Use whichever path is the more recent // if (path) {if (authfn) free(authfn); authfn = strdup(path);} if( !authfn || !*authfn) return Bail(0, "Authorization file not specified."); // Get the modification timestamp for this file // if (stat(authfn, &statbuff)) return Bail(errno, "find", authfn); // Try to open the authorization file. // if ( (authFD = open(authfn, O_RDONLY, 0)) < 0) return Bail(errno,"open authorization file",authfn); // Copy in all the relevant information // modtime = statbuff.st_mtime; flags = isOpen; DBfile.SetEroute(Eroute); DBfile.Tabs(0); // Attach the file to the stream // if (DBfile.Attach(authFD)) return Bail(DBfile.LastError(), "initialize stream for", authfn); return 1; } /******************************************************************************/ /* P r i v a t e M e t h o d s */ /******************************************************************************/ /******************************************************************************/ /* B a i l */ /******************************************************************************/ int XrdAccAuthFile::Bail(int retc, const char *txt1, const char *txt2) { // This routine is typically used by open and the DBcontext lock must be held // flags = (DBflags)(flags & ~isOpen); DBcontext.UnLock(); if (retc) Eroute->Emsg("AuthFile", retc, txt1, txt2); else Eroute->Emsg("AuthFile", txt1, txt2); return 0; } /******************************************************************************/ /* C o p y */ /******************************************************************************/ // This routine is used instead of strncpy because, frankly, it's a lot smarter char *XrdAccAuthFile::Copy(char *dp, char *sp, int dplen) { // Copy one less that the size of the buffer so that we have room for null // while(--dplen && *sp) {*dp = *sp; dp++; sp++;} // Insert a null character and return a pointer to it. // *dp = '\0'; return dp; }