/******************************************************************************/
/* */
/* X r d S e c g s i G M A P F u n D N . c c */
/* */
/* (c) 2011, G. Ganis / CERN */
/* */
/* 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. */
/* */
/******************************************************************************/
/* ************************************************************************** */
/* */
/* GMAP function implementation extracting info from the DN */
/* */
/* ************************************************************************** */
#include
#include
#include
#include
#include "XrdVersion.hh"
#include "XrdOuc/XrdOucHash.hh"
#include "XrdOuc/XrdOucString.hh"
#include "XrdOuc/XrdOucTrace.hh"
#include "XrdSys/XrdSysError.hh"
#include "XrdSys/XrdSysLogger.hh"
static XrdSysError dnDest(0, "gmapdn_");
static XrdSysLogger dnLogger;
static XrdOucTrace *dnTrace = 0;
#define TRACE_Authen 0x0002
#define EPNAME(x) static const char *epname = x;
#define PRINT(y) {if (dnTrace) {dnTrace->Beg(epname); cerr <End();}}
#define DEBUG(y) if (dnTrace && (dnTrace->What & TRACE_Authen)) PRINT(y)
/******************************************************************************/
/* V e r s i o n I n f o r m a t i o n */
/******************************************************************************/
XrdVERSIONINFO(XrdSecgsiGMAPFun,secgsigmap);
/******************************************************************************/
/* G l o b a l s & S t a t i c s */
/******************************************************************************/
enum XrdSecgsi_Match {kFull = 0,
kBegins = 1,
kEnds = 2,
kContains = 4
};
class XrdSecgsiMapEntry_t
{
public:
XrdSecgsiMapEntry_t(const char *v, const char *u, int t) : val(v), user(u), type(t) { }
XrdOucString val;
XrdOucString user;
int type;
};
static XrdOucHash gMappings;
/******************************************************************************/
/* F u n c t i o n s & M e t h o d s */
/******************************************************************************/
//__________________________________________________________________________
static int FindMatchingCondition(const char *, XrdSecgsiMapEntry_t *mc, void *xmp)
{
// Print content of entry 'ui' and go to next
XrdSecgsiMapEntry_t *mpe = (XrdSecgsiMapEntry_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;
}
int XrdSecgsiGMAPInit(const char *cfg);
//
// Main function
//
extern "C"
{
char *XrdSecgsiGMAPFun(const char *dn, int now)
{
// Implementation of XrdSecgsiGMAPFun extracting the information from the
// distinguished name 'dn'
EPNAME("GMAPFunDN");
// Init the relevant fields (only once)
if (now <= 0) {
if (XrdSecgsiGMAPInit(dn) != 0)
return (char *)-1;
return (char *)0;
}
// Output
char *name = 0;
XrdSecgsiMapEntry_t *mc = 0;
// Try the full match first
if ((mc = gMappings.Find(dn))) {
// Get the associated user
name = new char[mc->val.length() + 1];
strcpy(name, mc->val.c_str());
} else {
// Else scan the available mappings
mc = new XrdSecgsiMapEntry_t(dn, "", kFull);
gMappings.Apply(FindMatchingCondition, (void *)mc);
if (mc->user.length() > 0) {
name = new char[mc->user.length() + 1];
strcpy(name, mc->user.c_str());
}
}
if (name) {
DEBUG("mapping DN '"< 0) {
if (p == "d" || p == "dbg" || p == "debug") {
debug = 1;
} else {
cfg = p;
}
}
}
// Initiate error logging and tracing
dnDest.logger(&dnLogger);
dnTrace = new XrdOucTrace(&dnDest);
if (debug) dnTrace->What |= TRACE_Authen;
if (cfg.length() <= 0) cfg = getenv("XRDGSIGMAPDNCF");
if (cfg.length() <= 0) {
PRINT("ERROR: undefined config file path");
return -1;
}
FILE *fcf = fopen(cfg.c_str(), "r");
if (fcf) {
char l[4096], val[4096], usr[256];
while (fgets(l, sizeof(l), fcf)) {
int len = strlen(l);
if (len < 2) continue;
if (l[0] == '#') continue;
if (l[len-1] == '\n') l[len-1] = '\0';
if (sscanf(l, "%4096s %256s", val, usr) >= 2) {
XrdOucString stype = "matching";
char *p = &val[0];
int type = kFull;
if (val[0] == '^') {
// Starts-with
type = kBegins;
p = &val[1];
stype = "beginning with";
} else {
int vlen = strlen(val);
if (val[vlen-1] == '$') {
// Ends-with
type = kEnds;
val[vlen-1] = '\0';
stype = "ending with";
} else if (val[vlen-1] == '+') {
// Contains
type = kContains;
val[vlen-1] = '\0';
stype = "containing";
}
}
// Register
gMappings.Add(p, new XrdSecgsiMapEntry_t(p, usr, type));
//
DEBUG("mapping DNs "<