Loading...
Searching...
No Matches
XrdOucGMap.cc
Go to the documentation of this file.
/******************************************************************************/
/* */
/* X r d O u c G M a p . h h */
/* */
/* (c) 2006 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 <http://www.gnu.org/licenses/>. */
/* */
/* 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. */
/******************************************************************************/
/* ************************************************************************** */
/* */
/* Interface to grid map files */
/* */
/* This code was initially in XrdSecProtocolgsi. It has been extracted */
/* to allow usage in other contexts, namely XrdHttp. */
/* */
/* ************************************************************************** */
#include <cerrno>
#include <fcntl.h>
#include <sys/stat.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "XrdOuc/XrdOucEnv.hh"
#include "XrdOuc/XrdOucGMap.hh"
#include "XrdOuc/XrdOucTrace.hh"
#include "XrdOuc/XrdOucStream.hh"
#include "XrdSys/XrdSysE2T.hh"
enum XrdOucGMap_Match {kFull = 0,
kBegins = 1,
kEnds = 2,
kContains = 4
};
#define PRINT(t,n,y) {if (t) {t->Beg(n); std::cerr <<y; t->End();}}
#define DEBUG(d,t,n,y) {if (d && t) {t->Beg(n); std::cerr <<y; t->End();}}
//__________________________________________________________________________
static int FindMatchingCondition(const char *, XrdSecGMapEntry_t *mc, void *xmp)
{
// Print content of entry 'ui' and go to next
XrdSecGMapEntry_t *mpe = (XrdSecGMapEntry_t *)xmp;
bool match = 0;
if (mc && mpe) {
if (mc->type == kContains) {
if (mpe->val.find(mc->val) != STR_NPOS) match = 1;
} else if (mc->type == kBegins) {
if (mpe->val.beginswith(mc->val)) match = 1;
} else if (mc->type == kEnds) {
if (mpe->val.endswith(mc->val)) match = 1;
} else {
if (mpe->val.matches(mc->val.c_str())) match = 1;
}
if (match) mpe->user = mc->user;
}
// We stop if matched, otherwise we continue
return (match) ? 1 : 0;
}
// Getter
//
extern "C"
{
XrdOucGMap *XrdOucgetGMap(XrdOucGMapArgs)
{
// Create a XrdOucGMap object and return it if valid
XrdOucGMap *gm = new XrdOucGMap(eDest, mapfn, parms);
if (gm && gm->isValid()) return gm;
if (gm) delete gm;
return (XrdOucGMap *)0;
}}
// Constructor
//
XrdOucGMap::XrdOucGMap(XrdOucGMapArgs)
: valid(0), mf_mtime(-1), notafter(-1), timeout(600), elogger(eDest), tracer(0), dbg(0)
{
// Set tracer
//
tracer = new XrdOucTrace(eDest);
// Parse parameters, if any
//
XrdOucString pp(parms), p;
if (pp.length() > 0) {
int from = 0;
while ((from = pp.tokenize(p, from, '|')) != -1) {
// Debug
if (p == "debug" || p == "dbg") {
dbg = 1;
} else if (p.beginswith("to=")) {
p.erasefromstart(3);
if (p.isdigit()) {
timeout = p.atoi();
} else {
PRINT(tracer, "OucGMap", "timeout value badly formatted ("<<p<<"); ignoring");
}
}
}
}
// Set notafter is timeout is active
//
if (timeout > 0) notafter = time(0) + (time_t) timeout;
// Set the file name
//
mf_name = mapfn;
if (mf_name.length() <= 0) {
mf_name = getenv("GRIDMAP");
if (mf_name.length() <= 0)
mf_name = "/etc/grid-security/grid-mapfile";
}
// Check if it can be read
//
if (access(mf_name.c_str(), R_OK) != 0) {
PRINT(tracer, "OucGMap", "cannot access grid map file '"<< mf_name
<<"' in read mode; " <<XrdSysE2T(errno));
return;
}
// Load the file
//
if (load(mf_name.c_str()) != 0) {
PRINT(tracer, "OucGMap", "unable to load file "<<mf_name<<" - aborting");
return;
}
// Done
valid = 1;
}
// Loader
//
int XrdOucGMap::load(const char *mf, bool force)
{
(void)mf;
// We need an exclusive lock here
xsl.Lock(xs_Exclusive);
// Check if we need to load
//
struct stat st;
if (stat(mf_name.c_str(), &st) != 0) {
PRINT(tracer, "OucGMap::load", "cannot access grid map file '"
<<mf_name <<"'; " <<XrdSysE2T(errno));
// Delete the stored information if the file has been deleted
if (errno == ENOENT) mappings.Purge();
xsl.UnLock();
return -(int)errno;
}
#if defined(__APPLE__)
if (mf_mtime > 0 && (mf_mtime >= st.st_mtimespec.tv_sec) && !force) {
#else
if (mf_mtime > 0 && (mf_mtime >= st.st_mtim.tv_sec) && !force) {
#endif
DEBUG(dbg, tracer, "OucGMap::load", "map information up-to-date: no need to load");
xsl.UnLock();
return 0;
}
// Delete the stored information
//
mappings.Purge();
// Read the file
//
int fD, rc;
const char *inst = getenv("XRDINSTANCE") ? getenv("XRDINSTANCE") : "gmap config instance";
XrdOucEnv myEnv;
XrdOucStream mapf(elogger, inst, &myEnv, "");
if ( (fD = open(mf_name.c_str(), O_RDONLY, 0)) < 0) {
PRINT(tracer, "OucGMap::load", "map file '"<<mf_name
<<"' could not be open; " <<XrdSysE2T(errno));
xsl.UnLock();
return -(int)errno;
}
mapf.Attach(fD);
// Now start reading records until eof.
//
char *var;
while ((var = mapf.GetLine())) {
int len = strlen(var);
if (len < 2) continue;
if (var[0] == '#') continue;
// Extract DN
char *p0 = &var[0];
char cr = ' ';
if (p0[0] == '"') {
p0 = &var[1];
cr = '"';
}
char *p = p0;
int l0 = 0;
while (p0[l0] != cr)
l0++;
p0 = (p0 + l0 + 1);
while (*p0 == ' ')
p0++;
// Check for special delimiters
char stype[20] = {"matching"};
int type = kFull;
if (p[0] == '^') {
// Starts-with
type = kBegins;
p++;
l0--;
strcpy(stype, "beginning with");
} else {
if (p[l0-1] == '$') {
// Ends-with
type = kEnds;
p[--l0] = '\0';
strcpy(stype, "ending with");
} else if (p[l0-1] == '+') {
// Contains
type = kContains;
p[--l0] = '\0';
strcpy(stype, "containing");
}
}
XrdOucString udn(p, l0);
// Extract username
XrdOucString usr(p0);
// Register
if (usr.length() > 0) {
mappings.Add(p, new XrdSecGMapEntry_t(udn.c_str(), usr.c_str(), type));
DEBUG(dbg, tracer, "XrdOucGMap::load", "mapping DN: '"<<udn<<"' to user: '"<< usr <<"' (type:'"<< stype <<"')");
} else {
PRINT(tracer, "OucGMap::load", "ERROR: incomplete line found in file '"
<<mf_name <<"': "<<var<<" - skipping");
}
}
// Now check if any errors occurred during file i/o
//
if ((rc = mapf.LastError())) {
PRINT(tracer, "OucGMap::load", "ERROR: reading file '"<<mf_name<<"'; "
<<XrdSysE2T(rc));
rc = -rc;
}
mapf.Close();
// Store the modification time
//
#if defined(__APPLE__)
mf_mtime = st.st_mtimespec.tv_sec;
#else
mf_mtime = st.st_mtim.tv_sec;
#endif
// Done
xsl.UnLock();
return rc;
}
// Mapper
//
int XrdOucGMap::dn2user(const char *dn, char *user, int ulen, time_t now)
{
int rc = -1;
// Reset output
//
if (user && ulen > 0) {
memset(user, '\0', ulen);
} else {
PRINT(tracer, "OucGMap::dn2user",
"buffer for the user name is undefined or has undefined length");
return -(int)EINVAL;
}
// Check if we need to reload the information
//
if (notafter > 0) {
if (now <= 0) now = time(0);
if (notafter < now) {
// Reload the file
if (load(mf_name.c_str()) != 0) {
PRINT(tracer, "OucGMap::dn2user",
"problems loading file "<<mf_name);
return -(int)errno;
}
if (timeout > 0) notafter = now + (time_t) timeout;
}
}
// A shared lock is enough
xsl.Lock(xs_Shared);
// Search
//
XrdSecGMapEntry_t *mc = 0;
// Try the full match first
//
if ((mc = mappings.Find(dn))) {
// Save the associated user
int ul = mc->user.length();
strncpy(user, mc->user.c_str(), ul);
user[ul] = 0;
rc = 0;
} else {
// Else scan the available mappings
//
mc = new XrdSecGMapEntry_t(dn, "", kFull);
mappings.Apply(FindMatchingCondition, (void *)mc);
if (mc->user.length() > 0) {
int ul = mc->user.length();
strncpy(user, mc->user.c_str(), ul);
user[ul] = 0;
rc = 0;
}
if (mc) delete mc;
}
if (rc == 0) {
DEBUG(dbg, tracer, "XrdOucGMap::dn2user", "mapping DN '"<<dn<<"' to '"<<user<<"'");
} else {
DEBUG(dbg, tracer, "XrdOucGMap::dn2user", "no valid match found for DN '"<<dn<<"'");
rc = -(int)EFAULT;
}
// Done
xsl.UnLock();
return rc;
}
DEBUG
#define DEBUG(x)
Definition XrdBwmTrace.hh:54
eDest
static XrdSysError eDest(0,"crypto_")
PRINT
#define PRINT(y)
Definition XrdCryptosslTrace.hh:39
XrdOucEnv.hh
XrdOucgetGMap
XrdOucGMap * XrdOucgetGMap(XrdOucGMapArgs)
Definition XrdOucGMap.cc:92
XrdOucGMap_Match
XrdOucGMap_Match
Definition XrdOucGMap.cc:54
kBegins
@ kBegins
Definition XrdOucGMap.cc:55
kEnds
@ kEnds
Definition XrdOucGMap.cc:56
kContains
@ kContains
Definition XrdOucGMap.cc:57
kFull
@ kFull
Definition XrdOucGMap.cc:54
FindMatchingCondition
static int FindMatchingCondition(const char *, XrdSecGMapEntry_t *mc, void *xmp)
Definition XrdOucGMap.cc:64
XrdOucGMap.hh
XrdOucGMapArgs
#define XrdOucGMapArgs
Definition XrdOucGMap.hh:89
XrdOucStream.hh
STR_NPOS
#define STR_NPOS
Definition XrdOucString.hh:250
XrdOucTrace.hh
access
#define access(a, b)
Definition XrdPosix.hh:44
open
#define open
Definition XrdPosix.hh:76
stat
#define stat(a, b)
Definition XrdPosix.hh:101
XrdSysE2T
const char * XrdSysE2T(int errcode)
Definition XrdSysE2T.cc:104
XrdSysE2T.hh
xs_Exclusive
@ xs_Exclusive
Definition XrdSysXSLock.hh:38
xs_Shared
@ xs_Shared
Definition XrdSysXSLock.hh:38
XrdOucGMap
Definition XrdOucGMap.hh:49
XrdOucGMap::XrdOucGMap
XrdOucGMap(XrdOucGMapArgs)
Definition XrdOucGMap.cc:103
XrdOucGMap::isValid
bool isValid() const
Validity checker.
Definition XrdOucGMap.hh:104
XrdOucGMap::dn2user
virtual int dn2user(const char *dn, char *user, int ulen, time_t now=0)
Definition XrdOucGMap.cc:292
XrdOucHash::Purge
void Purge()
Definition XrdOucHash.icc:193
XrdOucString
Definition XrdOucString.hh:252
XrdOucString::erasefromstart
int erasefromstart(int sz=0)
Definition XrdOucString.hh:328
XrdOucString::endswith
bool endswith(char c)
Definition XrdOucString.cc:406
XrdOucString::beginswith
bool beginswith(char c)
Definition XrdOucString.hh:289
XrdOucString::matches
int matches(const char *s, char wch=' *')
Definition XrdOucString.cc:426
XrdOucString::find
int find(const char c, int start=0, bool forward=1)
Definition XrdOucString.cc:260
XrdOucString::length
int length() const
Definition XrdOucString.hh:279
XrdOucString::isdigit
bool isdigit(int from=0, int to=-1)
Definition XrdOucString.cc:1270
XrdOucString::atoi
long atoi(int from=0, int to=-1)
Definition XrdOucString.cc:1295
XrdOucString::c_str
const char * c_str() const
Definition XrdOucString.hh:278
XrdOucTrace
Definition XrdOucTrace.hh:36
XrdSecGMapEntry_t
Definition XrdOucGMap.hh:40
XrdSecGMapEntry_t::user
XrdOucString user
Definition XrdOucGMap.hh:44
XrdSecGMapEntry_t::type
int type
Definition XrdOucGMap.hh:45
XrdSecGMapEntry_t::val
XrdOucString val
Definition XrdOucGMap.hh:43
XrdSysXSLock::Lock
void Lock(const XrdSysXS_Type usage)
Definition XrdSysXSLock.cc:55
XrdSysXSLock::UnLock
void UnLock(const XrdSysXS_Type usage=xs_None)
Definition XrdSysXSLock.cc:95