/******************************************************************************/ /* */ /* X r d S e c g s i A u t h z F u n V O . c c */ /* */ /* (c) 2011 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. */ /******************************************************************************/ /* Trivial AuthzKey/Func(), propogates the VO as a unix user and/or group. 1. To be used with gsi parametrized like: sec.protocol /opt/xrootd/lib/x86_64_linux_26 gsi \ -certdir:/etc/grid-security/certificates \ -cert:/etc/grid-security/xrd/xrdcert.pem \ -key:/etc/grid-security/xrd/xrdkey.pem -crl:3 \ -authzfun:libXrdAuthzVO.so -authzfunparms: \ -gmapopt:10 -gmapto:0 2. The optional authzfunparms is formatted as a CGI string with one or more of the following key-value pairs: debug=1 valido= vo2grp= vo2usr= Where: debug - turns debugging on. vlist - specifies a comma-separated list of vo names that are acceptable. If not specified, all vo's are accepted. Otherwise, failure is returned if the the vo is not in the list of vo's. gspec - specifies how the vo is to be inserted into a group name. Specify a printf-like format string with a single %s. This is where the vo name is inserted. So, "%s" simply makes the group name the vo name. uspec - specifies how the vo is to be inserted into a user name. The same rules apply as for gspec. If uspec is not specified then the name comes from distinguished name in the certificate (i.e. text after '/CN=') with spaces turned into underscores and the vo is not used. If uspec is specified as a single asterisk (*) then the name field is not touched and is as set by the gsi module. */ #include #include #include #include #include "XrdVersion.hh" #include "XrdSys/XrdSysHeaders.hh" #include "XrdSys/XrdSysPthread.hh" #include "XrdSec/XrdSecEntity.hh" #include "XrdOuc/XrdOucEnv.hh" #include "XrdOuc/XrdOucLock.hh" /******************************************************************************/ /* V e r s i o n I n f o r m a t i o n */ /******************************************************************************/ XrdVERSIONINFO(XrdSecgsiAuthzFun,secgsiauthz); XrdVERSIONINFO(XrdSecgsiAuthzKey,secgsiauthz); XrdVERSIONINFO(XrdSecgsiAuthzInit,secgsiauthz); /******************************************************************************/ /* E x t e r n a l F u n c t i o n s */ /******************************************************************************/ // The following functions are called by the authz plug-in driver. // extern "C" { int XrdSecgsiAuthzInit(const char *cfg); int XrdSecgsiAuthzFun(XrdSecEntity &entity); int XrdSecgsiAuthzKey(XrdSecEntity &entity, char **key); } /******************************************************************************/ /* G l o b a l V a r i a b l e s */ /******************************************************************************/ namespace { const int g_certificate_format = 1; const int g_maxvolen = 255; static char *g_valido = 0; static char *g_vo2grp = 0; static char *g_vo2usr = 0; static int g_debug = 0; static int g_cn2usr = 1; } /******************************************************************************/ /* L o c a l D e f i n e s */ /******************************************************************************/ #undef PRINT #define PRINT(y) if (g_debug) {std::cerr << y << "\n";} #undef PROUT #define PROUT(_x_) \ std::cerr <0 error (this will still log the guy in, it seems) 0 success, local username in entity.name */ int XrdSecgsiAuthzFun(XrdSecEntity &entity) { static const char* inf_pfx = "INFO in AuthzFun: "; static XrdSysMutex Mutex; const char *vtxt = "", *etxt = 0; char vbuff[(g_maxvolen+1)*2]; int i, n; // We must have a vo, it must be shorter than 255 bytes, and it must be in our // vo list of we have one // if (!entity.vorg) etxt = "missing"; else if ((n = strlen(entity.vorg)) > g_maxvolen) etxt = "too long"; else if (g_valido) {*vbuff = ','; strcpy(vbuff+1, entity.vorg); if (!strstr(g_valido, vbuff)) {vtxt = entity.vorg; etxt = " not allowed";} } // Check if we passed the tests // if (etxt) {std::cerr <<"AuthzVO: Invalid cert; vo " <= 0; i--) {if (*cP == '_') *cP = 0;} if (*vbuff) {if (entity.name) free(entity.name); entity.name = strdup(vbuff); } } // If debugging then print information. However, get a global mutex to keep // from inter-leaving these lines with other threads, as much as possible. // if (g_debug) {XrdOucLock lock(&Mutex); PROUT(name); PROUT(host); PROUT(grps); PROUT(vorg); PROUT(role); } // All done // return 0; } /******************************************************************************/ /* X r d S e c g s i A u t h z K e y */ /******************************************************************************/ int XrdSecgsiAuthzKey(XrdSecEntity &entity, char **key) { // Return key by which entity.creds will be hashed. // For now return entity.creds itself. // The plan is to use DN + VO endorsements in the future. static const char* err_pfx = "ERR in AuthzKey: "; static const char* inf_pfx = "INFO in AuthzKey: "; // Must have got something if (!key) { PRINT(err_pfx << "'key' is not defined!"); return -1; } PRINT(inf_pfx << "Returning creds of len " << entity.credslen << " as key."); // Set the key *key = new char[entity.credslen + 1]; strcpy(*key, entity.creds); return entity.credslen; } /******************************************************************************/ /* X r d S e c g s i A u t h z I n i t */ /******************************************************************************/ int XrdSecgsiAuthzInit(const char *cfg) { // Return: // -1 on falure // 0 to get credentials in raw form // 1 to get credentials in PEM base64 encoded form static const char* inf_pfx = "INFO in AuthzInit: "; XrdOucEnv *envP; char cfgbuff[2048], *sP; int i; // The configuration string may mistakingly include other parms following // the auzparms. So, trim the string. // if (cfg) {i = strlen(cfg); if (i >= (int)sizeof(cfgbuff)) i = sizeof(cfgbuff)-1; memcpy(cfgbuff, cfg, i); cfgbuff[i] = 0; if ((sP = index(cfgbuff, ' '))) *sP = 0; } if (!cfg || !(*cfg)) return g_certificate_format; // Parse the config line (it's in cgi format) // envP = new XrdOucEnv(cfgbuff); // Set debug value // if ((sP = envP->Get("debug")) && *sP == '1') g_debug = 1; // Get the mapping strings // if ((g_vo2grp = envP->Get("vo2grp"))) g_vo2grp = strdup(g_vo2grp); if ((g_vo2usr = envP->Get("vo2usr"))) {g_cn2usr = 0; g_vo2usr = (!strcmp(g_vo2usr, "*") ? 0 : strdup(g_vo2usr)); } // Now process the valid vo's // if ((sP = envP->Get("valido"))) {i = strlen(sP); g_valido = (char *)malloc(i+2); *g_valido = ','; strcpy(g_valido+1, sP); } // All done with environment // delete envP; // All done. // PRINT(inf_pfx <<"cfg='"<< (cfg ? cfg : "null") << "'."); return g_certificate_format; }