Revision dc584a77e70b12a1ce843f0964f13c1789e095b6 authored by Fons Rademakers on 02 July 2009, 10:50:48 UTC, committed by Fons Rademakers on 02 July 2009, 10:50:48 UTC
trunk for patch releases. git-svn-id: http://root.cern.ch/svn/root/branches/v5-24-00-patches@29307 27541ba8-7e3a-0410-8455-c3a389f83636
1 parent 7d28017
GlobusAuth.cxx
// @(#)root/globus:$Id$
// Author: Gerardo Ganis 15/01/2003
/*************************************************************************
* Copyright (C) 1995-2002, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
/* Parts of this file are adapted from the Globus Tool Kit version 2.2.3
* are subject to related licenses.
* Please refer to www.globus.org for details
*/
#include "RConfigure.h"
#include <errno.h>
#include <signal.h>
#include <string.h>
// #include <stdlib.h>
#include "TSocket.h"
#include "TAuthenticate.h"
#include "THostAuth.h"
#include "TDatime.h"
#include "TError.h"
#include "TSystem.h"
#include "TROOT.h"
#include "TApplication.h"
#include "TEnv.h"
#include "Getline.h"
#include "NetErrors.h"
#define HAVE_MEMMOVE 1
extern "C" {
#ifdef IOV_MAX
#undef IOV_MAX
#endif
#include <globus_common.h>
#include <globus_gss_assist.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <sys/ipc.h>
#include <sys/shm.h>
}
static gss_cred_id_t gGlbCredHandle = GSS_C_NO_CREDENTIAL;
static gss_cred_id_t gGlbDelCredHandle = GSS_C_NO_CREDENTIAL;
static int gShmIdCred = -1;
Int_t GlobusAuthenticate(TAuthenticate *, TString &, TString &);
Int_t GlobusCheckSecContext(const char *, gss_ctx_id_t);
Int_t GlobusCheckSecCtx(const char *, TRootSecContext *);
Int_t GlobusCleanupContext(gss_ctx_id_t);
void GlobusCleanupShm();
Int_t GlobusIssuerName(TString &);
void GlobusError(char *, OM_uint32, OM_uint32, Int_t);
Int_t GlobusGetCredHandle(Int_t, gss_cred_id_t *);
Int_t GlobusGetDelCred();
void GlobusGetDetails(Int_t, Int_t, TString &);
Int_t GlobusGetLocalEnv(Int_t *, TString);
Int_t GlobusGetSecContLifeTime(gss_ctx_id_t);
Int_t GlobusNameFromCred(gss_cred_id_t, TString &);
class GlobusAuthInit {
public:
GlobusAuthInit() {
TAuthenticate::SetGlobusAuthHook(&GlobusAuthenticate);
}};
static GlobusAuthInit globusauth_init;
//______________________________________________________________________________
Int_t GlobusAuthenticate(TAuthenticate * tAuth, TString & user,
TString & details)
{
// Globus authentication code.
// Returns 0 in case authentication failed
// 1 in case of success
// 2 in case of the remote node doesn not seem to support
// Globus Authentication
// 3 in case of the remote node doesn not seem to have
// certificates for our CA or is unable to init credentials
int auth = 0, rc;
int retval = 0, kind = 0, type = 0, server_auth = 0, brcv = 0, bsnd = 0;
gss_ctx_id_t glbContextHandle = GSS_C_NO_CONTEXT;
OM_uint32 majStat = 0;
OM_uint32 minStat = 0;
OM_uint32 gssRetFlags = 0;
OM_uint32 gssReqFlags = 0;
int glbTokenStatus = 0;
char *host_subj = 0;
TDatime expDate = TDatime();
// Check if called for cleanup
if (user == "-1") {
if (gDebug > 2)
Info("GlobusAuthenticate", " cleanup call (%s)",details.Data());
if (details == "context") {
// Security context cleaning
GlobusCleanupContext((gss_ctx_id_t)tAuth);
} else if (details == "shm") {
// Shared memory cleaning (TProofServ)
GlobusCleanupShm();
}
return 1;
}
// From the calling TAuthenticate
TSocket *sock = tAuth->GetSocket();
TString protocol = tAuth->GetProtocol();
if (gDebug > 2)
Info("GlobusAuthenticate", " enter: protocol:'%s' user:'%s'", protocol.Data(),
user.Data());
// The host FQDN ... for debugging
const char *hostFQDN = sock->GetInetAddress().GetHostName();
// Determine local calling environment ...
Int_t localCallEnv = -1;
if ((rc = GlobusGetLocalEnv(&localCallEnv, protocol))) {
if (gDebug > 0)
Error("GlobusAuthenticate",
"unable to set relevant environment variables (rc=%d)",
rc);
return -1;
}
if (gDebug > 3)
Info("GlobusAuthenticate", " localCallEnv is %d", localCallEnv);
// Get credential handle ... either genuine or delegated
if (GlobusGetCredHandle(localCallEnv, &gGlbCredHandle)) {
if (gDebug > 0)
Error("GlobusAuthenticate", "unable to acquire valid credentials");
return -1;
}
if (gDebug > 3)
Info("GlobusAuthenticate", " Credential Handle is 0x%x",
gGlbCredHandle);
// Inquire credentials for subject name and convert it in human readable form ...
TString ssuj;
if ((rc = GlobusNameFromCred(gGlbCredHandle, ssuj))) {
if (gDebug > 0)
Error("GlobusAuthenticate",
"PROOF Master: unable to determine name from cred (rc=%d)", rc);
return -1;
}
// Create Options string
Int_t opt = TAuthenticate::GetAuthReUse() * kAUTH_REUSE_MSK +
tAuth->GetRSAKeyType() * kAUTH_RSATY_MSK;
TString options(Form("%d %d %s", opt, ssuj.Length(), ssuj.Data()));
// Check established authentications
kind = kROOTD_GLOBUS;
retval = TAuthenticate::GetAuthReUse();
if ((rc = tAuth->AuthExists(ssuj, TAuthenticate::kGlobus, options,
&kind, &retval, &GlobusCheckSecCtx)) == 1) {
// A valid authentication exists: we are done ...
return 1;
}
if (rc == -2) {
return rc;
}
if (kind == kROOTD_ERR) {
return 0;
}
// If server does not support Globus authentication we can't continue ...
if (retval == 0 || kind != kROOTD_GLOBUS) {
if (gDebug > 2)
Info("GlobusAuthenticate", "server does not support Globus authentication");
return -1;
}
if (sock->GetRemoteProtocol() < 18) {
TString isuj;
if (GlobusIssuerName(isuj)) {
if (gDebug > 0)
Error("GlobusAuthenticate",
"unable to determine issuer name from certificate");
return 0;
}
// Now we send the issuer to the server daemon
char buf[20];
sprintf(buf, "%d", (int) (isuj.Length() + 1));
if ((bsnd = sock->Send(buf, kMESS_STRING)) != (int) (strlen(buf)+1)) {
if (gDebug > 0)
Error("GlobusAuthenticate",
"Length of Issuer name not send correctly: bytes sent: %d (tot len: %d)",
bsnd - 1, strlen(buf));
return 0;
}
// Now we send it to the server daemon
if ((bsnd = sock->Send(isuj.Data(), kMESS_STRING)) < (Int_t)(isuj.Length()+1)) {
if (gDebug > 0)
Error("GlobusAuthenticate",
"Issuer name not send correctly: bytes sent: %d (tot len: %d)",
bsnd - 1, isuj.Length());
return 0;
}
}
// Now we wait for the replay from the server ...
sock->Recv(retval, kind);
if (kind == kROOTD_ERR) {
if (gDebug > 0)
Error("GlobusAuthenticate",
"recv host subj: host unable init credentials");
return 3;
}
if (kind != kROOTD_GLOBUS) {
if (gDebug > 0)
Error("GlobusAuthenticate",
"recv host subj: unexpected message from daemon:"
" kind: %d (expecting: %d)",kind, kROOTD_GLOBUS);
} else {
if (retval == 0) {
if (gDebug > 0)
Error("GlobusAuthenticate",
"recv host subj: host not able to authenticate this CA");
return 0;
} else {
if (gDebug > 3)
Info("GlobusAuthenticate",
"recv host subj: buffer length is: %d", retval);
host_subj = new char[retval + 1];
brcv = sock->Recv(host_subj, retval, kind);
if (gDebug > 3)
Info("GlobusAuthenticate",
"received host_subj: %s: (%d)", host_subj, brcv);
if (strlen(host_subj) < (UInt_t)(retval - 1) ||
retval <= 1) {
if (gDebug > 0) {
Error("GlobusAuthenticate",
"recv host subj: did not receive all the bytes"
" (recv: %d, due >%d)", brcv, retval);
Error("GlobusAuthenticate", "recv host subj: (%d) %s",
strlen(host_subj), host_subj);
}
if (host_subj) delete[] host_subj;
return 0;
}
}
}
// Now we have a valid subject name for the host ...
if (gDebug > 2)
Info("GlobusAuthenticate", "Host subject: %s", host_subj);
// We need to associate a FILE* stream with the socket
// It will automatically closed when the socket will be closed ...
int sockFd = sock->GetDescriptor();
FILE *sockStream = fdopen(sockFd, "w+");
// Type of request for credentials depend on calling environment
gssReqFlags =
localCallEnv >
0 ? (GSS_C_DELEG_FLAG | GSS_C_MUTUAL_FLAG) : GSS_C_MUTUAL_FLAG;
if (gDebug > 3)
Info("GlobusAuthenticate",
" gssReqFlags: %p, GlbCredentials: %p", gssReqFlags, gGlbCredHandle);
// Now we are ready to start negotiating with the Server
if ((majStat =
globus_gss_assist_init_sec_context(&minStat, gGlbCredHandle,
&glbContextHandle, host_subj,
gssReqFlags, &gssRetFlags,
&glbTokenStatus,
globus_gss_assist_token_get_fd,
(void *) sockStream,
globus_gss_assist_token_send_fd,
(void *) sockStream)) !=
GSS_S_COMPLETE) {
if (gDebug > 0)
GlobusError("GlobusAuthenticate: gss_assist_init_sec_context",
majStat, minStat, glbTokenStatus);
if (host_subj) delete[] host_subj;
sock->Send(0,kROOTD_ERR);
return 0;
} else {
// Set expiration date
expDate.Set(expDate.Convert() + GlobusGetSecContLifeTime(glbContextHandle));
if (gDebug > 2) {
Info("GlobusAuthenticate", "authenticated to host %s", hostFQDN);
Info("GlobusAuthenticate", "expiring on '%s'", expDate.AsString());
}
if (fflush(sockStream) != 0) {
Warning("GlobusAuthenticate", "unable to fflush socket:"
" may cause authentication problems on server side");
}
auth = 1;
}
// Now we have the subject and we can release some resources ...
if (host_subj) delete[] host_subj;
// Receive username used for login or key request info and type of key
int nrec = sock->Recv(retval, type); // returns user
Int_t rsaKey = 0;
if (type == kROOTD_RSAKEY) {
if (retval <= 0 || retval > 2)
Warning("GlobusAuthenticate",
"problems recvn RSA key flag: got message %d, retval: %d",
type, retval);
rsaKey = retval - 1;
// Send the key securely
TAuthenticate::SendRSAPublicKey(sock,rsaKey);
// Receive username used for login
nrec = sock->Recv(retval, type); // returns user
}
if (type != kROOTD_GLOBUS || retval < 1)
Warning("GlobusAuthenticate",
"problems recvn (user,offset) length (%d:%d bytes:%d)", type,
retval, nrec);
char *rfrm = new char[retval + 1];
nrec = sock->Recv(rfrm, retval + 1, type); // returns user
if (type != kMESS_STRING)
Warning("GlobusAuthenticate",
"username and offset not received (%d:%d)", type, nrec);
else if (gDebug > 2)
Info("GlobusAuthenticate", "logging remotely as %s ", rfrm);
// Parse answer
char *lUser = new char[retval];
Int_t offSet = -1;
sscanf(rfrm, "%s %d", lUser, &offSet);
// Return username
user = lUser;
// Receive token
char *token = 0;
if (TAuthenticate::GetAuthReUse() == 1 && offSet > -1) {
if (TAuthenticate::SecureRecv(sock, 1, rsaKey, &token) == -1) {
Warning("GlobusAuthenticate",
"Problems secure-receiving token -"
" may result in corrupted token");
}
if (gDebug > 3)
Info("GlobusAuthenticate", "received from server: token: '%s' ",
token);
} else {
token = StrDup("");
}
// Create SecContext object
GlobusGetDetails(localCallEnv, 0, details);
TRootSecContext *ctx =
tAuth->GetHostAuth()->CreateSecContext((const char *)lUser,
hostFQDN, (Int_t)TAuthenticate::kGlobus, offSet,
details, (const char *)token, expDate,
(void *)glbContextHandle, rsaKey);
// Transmit it to TAuthenticate
tAuth->SetSecContext(ctx);
// receive status from server
sock->Recv(server_auth, kind);
if (gDebug > 2)
Info("GlobusAuthenticate", "received auth status from server: %d (%d)",
server_auth, kind);
if (auth && !server_auth) {
Warning("GlobusAuthenticate",
" it looks like server did not authenticate: probably a problem with mapping");
auth = 0;
}
// free allocated memory ...
if (rfrm) delete[] rfrm;
if (lUser) delete[] lUser;
if (token) delete[] token;
// return result
return auth;
}
//______________________________________________________________________________
int GlobusGetDelCred()
{
// This function fetchs from the shared memory segment created by 'proofd'.
// the delegated credentials needed to autheticate the slaves ...
// The shared memory segment is destroyed.
struct shmid_ds shm_ds;
OM_uint32 majStat = 0;
OM_uint32 minStat = 0;
if (gDebug > 2)
Info("GlobusGetDelCred:", "Enter ...");
// Attach segment to address
gss_buffer_t databuf = (gss_buffer_t) shmat(gShmIdCred, 0, 0);
// Import credentials
// credential= (gss_buffer_t)malloc(sizeof(gss_buffer_desc)+databuf->length);
gss_buffer_t credential =
(gss_buffer_t) new char[sizeof(gss_buffer_desc) + databuf->length];
credential->length = databuf->length;
credential->value =
(void *) ((char *) credential + sizeof(size_t) + sizeof(void *));
void *dbufval =
(void *) ((char *) databuf + sizeof(size_t) + sizeof(void *));
memmove(credential->value, dbufval, credential->length);
if ((majStat =
gss_import_cred(&minStat, &gGlbDelCredHandle, 0, 0, credential, 0,
0)) != GSS_S_COMPLETE) {
if (gDebug > 0)
GlobusError("GlobusGetDelCred: gss_import_cred", majStat, minStat,
0);
return 1;
} else if (gDebug > 3)
Info("GlobusGetDelCred:",
"Globus Credentials successfully imported (0x%x)",
gGlbDelCredHandle);
if (credential) delete[] credential;
// Detach from shared memory segment
int rc = shmdt((const void *) databuf);
if (rc != 0) {
if (gDebug > 0)
Info("GlobusGetDelCred:",
"unable to detach from shared memory segment (rc=%d)", rc);
}
if (gDebug > 3) {
rc = shmctl(gShmIdCred, IPC_STAT, &shm_ds);
Info("GlobusGetDelCred:",
"Process: uid: %d, euid: %d - Buffer: uid: %d, cuid: %d",
getuid(), geteuid(), shm_ds.shm_perm.uid, shm_ds.shm_perm.cuid);
}
rc = shmctl(gShmIdCred, IPC_RMID, &shm_ds);
if (rc == 0) {
if (gDebug > 2)
Info("GlobusGetDelCred:",
"shared memory segment successfully marked as destroyed");
} else {
Warning("GlobusGetDelCred:",
"unable to mark segment %d as destroyed", gShmIdCred);
}
return 0;
}
//______________________________________________________________________________
void GlobusError(char *mess, OM_uint32 majs, OM_uint32 mins, int toks)
{
// Handle error ...
char *glbErr = 0;
if (!globus_gss_assist_display_status_str
(&glbErr, mess, majs, mins, toks)) {
Error("GlobusError:","%s (majst=%d,minst=%d,tokst:%d)",
glbErr, majs, mins, toks);
} else {
Error("GlobusError:","%s (not resolved) (majst=%d,minst=%d,tokst:%d)",
mess, majs, mins, toks);
}
if (glbErr) delete[] glbErr;
}
//______________________________________________________________________________
Int_t GlobusGetLocalEnv(Int_t *localEnv, TString protocol)
{
// Determines calling environment.
// Returns 0 if successful; 1 otherwise.
int retval = 0;
// Calling application
TApplication *lApp = gROOT->GetApplication();
if (gDebug > 2) {
int i = 0;
for (; i < lApp->Argc(); i++) {
Info("GlobusGetLocalEnv", "application arguments: %d: %s", i,
lApp->Argv(i));
}
}
*localEnv = 0;
if (lApp != 0) {
if (gROOT->IsProofServ()) {
// This is PROOF ... either Master or Slave ...
if (gDebug > 3) {
Info("GlobusGetLocalEnv",
"PROOF environment, called by the MASTER/SLAVE");
Info("GlobusGetLocalEnv",
"string with pointer to del cred is 0x%x",
gGlbDelCredHandle);
}
*localEnv = 2;
gShmIdCred = -1;
const char *p = gSystem->Getenv("ROOTSHMIDCRED");
if (p)
gShmIdCred = strtol(p, (char **)0, 10);
if (gShmIdCred <= 0) {
Info("GlobusGetLocalEnv",
"delegate credentials undefined");
retval = 1;
}
} else {
if (strstr(protocol.Data(), "proof") != 0) {
if (gDebug > 3)
Info("GlobusGetLocalEnv",
"PROOF environment, called by the CLIENT");
*localEnv = 1;
} else if (strstr(protocol.Data(), "root") != 0 ||
strstr(protocol.Data(), "sock") != 0) {
if (gDebug > 3)
Info("GlobusGetLocalEnv",
"ROOT environment (%s)", protocol.Data());
} else {
if (gDebug > 0)
Info("GlobusGetLocalEnv",
"unable to recognize the environment"
" (protocol: %s)-> assume ROOT",protocol.Data());
}
}
} else {
if (gDebug > 0)
Info("GlobusGetLocalEnv",
"unable to get pointer to current application"
" -> assume ROOT environment");
}
return retval;
}
//______________________________________________________________________________
Int_t GlobusNameFromCred(gss_cred_id_t cred, TString &subjName)
{
// Get subject name from credential handle cred.
// Returns 0 is successfull, 1 otherwise.
if (gDebug > 2)
Info("GlobusNamesFromCred", "Enter: Handle: 0x%p", cred);
// Inquire credentials for Subject name and convert it in human readable form ...
OM_uint32 majStat = 0;
OM_uint32 minStat = 0;
gss_name_t name;
OM_uint32 lifeTime;
gss_cred_usage_t credUsage;
gss_OID_set mech;
if ((majStat = gss_inquire_cred(&minStat, cred, &name,
&lifeTime, &credUsage, &mech)) != GSS_S_COMPLETE) {
if (gDebug > 0)
GlobusError("GlobusNameFromCred: gss_inquire_cred",
majStat, minStat,0);
return 1;
}
gss_buffer_desc outBuf;
gss_OID nameType;
if ((majStat = gss_display_name(&minStat, name, &outBuf,
&nameType)) != GSS_S_COMPLETE) {
if (gDebug > 0)
GlobusError("GlobusNameFromCred: gss_display_name",
majStat, minStat, 0);
return 2;
} else
subjName = TString((const char *)outBuf.value);
// Notify
if (gDebug > 2)
Info("GlobusNameFromCred", "subject name: %s", subjName.Data());
// Successful
return 0;
}
//______________________________________________________________________________
Int_t GlobusGetSecContLifeTime(gss_ctx_id_t ctx)
{
// Returns lifetime of established sec context 'ctx'
OM_uint32 majStat = 0;
OM_uint32 minStat = 0;
OM_uint32 gssRetFlags = 0;
OM_uint32 glbContLifeTime = 0;
gss_OID mechType;
gss_name_t *targName = 0, *name = 0;
int dum1, dum2;
if (ctx != 0 && ctx != GSS_C_NO_CONTEXT) {
if ((majStat = gss_inquire_context(&minStat, ctx, name,
targName, &glbContLifeTime, &mechType, &gssRetFlags,
&dum1, &dum2)) != GSS_S_COMPLETE) {
if (gDebug > 0)
GlobusError("GlobusGetSecContLifeTime: gss_inquire_context",
majStat, minStat, 0);
return 0;
} else {
if (gDebug > 3)
Info("GlobusGetSecContLifeTime"," remaining lifetime: %d sec",
glbContLifeTime);
return (Int_t)glbContLifeTime;
}
}
return 0;
}
//______________________________________________________________________________
Int_t GlobusCleanupContext(gss_ctx_id_t ctx)
{
// This function cleans up security context ctx
OM_uint32 majStat = 0;
OM_uint32 minStat = 0;
// Delete context
if ((majStat = gss_delete_sec_context(&minStat, &ctx,
GSS_C_NO_BUFFER)) != GSS_S_COMPLETE) {
if (gDebug > 0)
GlobusError("GlobusCleanupContext: gss_delete_sec_context",
majStat,minStat, 0);
return 0;
}
return 1;
}
//______________________________________________________________________________
Int_t GlobusCheckSecCtx(const char *subj, TRootSecContext *ctx)
{
// Globus version of CheckSecCtx to be passed to TAuthenticate::AuthExists
// Check if Subj matches the one in Ctx
// Returns: 1 if ok, 0 if not
// Deactivates Ctx is not valid
Int_t rc = 0;
if (ctx->IsActive())
rc = GlobusCheckSecContext(subj,(gss_ctx_id_t)(ctx->GetContext()));
return rc;
}
//______________________________________________________________________________
void GlobusCleanupShm()
{
// This function cleans up shared memories associated with Globus
if (gROOT->IsProofServ()) {
struct shmid_ds shm_ds;
int rc;
// Delegated Credentials
gShmIdCred = -1;
const char *p = gSystem->Getenv("ROOTSHMIDCRED");
if (p)
gShmIdCred = strtol(p, (char **)0, 10);
if (gShmIdCred != -1) {
if ((rc = shmctl(gShmIdCred, IPC_RMID, &shm_ds)) != 0) {
if ((rc == EINVAL) || (rc == EIDRM)) {
if (gDebug > 3)
Info("GlobusCleanupShm:",
"credentials shared memory segment %s"
"already marked as destroyed");
} else {
Warning("GlobusCleanupShm:",
"unable to mark segment as destroyed (error: 0x%x)",
rc);
}
} else if (gDebug > 3)
Info("GlobusCleanupShm:",
"shared memory segment %d marked for destruction",
gShmIdCred);
} else if (gDebug > 3) {
Info("GlobusCleanupShm:",
"gShmIdCred not defined in this session");
}
}
}
//______________________________________________________________________________
Int_t GlobusCheckSecContext(const char *subjName, gss_ctx_id_t ctx)
{
// Checks if SubjName match the one assigned to sec context Ctx
// Check also validity of Ctx.
// Returns 1 if everything is ok, 0 if non-matching
// -1 if Ctx is no more valid and should be discarded
if (!ctx)
return 0;
int rc = 0;
OM_uint32 majStat = 0;
OM_uint32 minStat = 0;
OM_uint32 gssRetFlags = 0;
OM_uint32 glbContLifeTime = 0;
if (gDebug > 2)
Info("GlobusCheckSecContext", "checking subj:%s", subjName);
// Check validity of the retrieved context ...
Int_t dum1, dum2;
gss_OID mechType;
gss_name_t *targName = 0;
gss_name_t name;
if (ctx != 0 && ctx != GSS_C_NO_CONTEXT) {
if ((majStat = gss_inquire_context(&minStat, ctx, &name,
targName, &glbContLifeTime, &mechType,
&gssRetFlags, &dum1, &dum2)) != GSS_S_COMPLETE) {
if (gDebug > 0)
GlobusError("GlobusCheckSecContext: gss_inquire_context",
majStat, minStat, 0);
rc = -1;
} else {
gss_buffer_desc nameBuffer;
// Get the subject name now
if ((majStat = gss_display_name(&minStat, name, &nameBuffer,
GLOBUS_NULL)) != GSS_S_COMPLETE) {
if (gDebug > 0)
GlobusError("GlobusCheckSecContext: gss_display_name",
majStat, minStat, 0);
nameBuffer.length = 0;
nameBuffer.value = GLOBUS_NULL;
} else {
char *theName = new char[nameBuffer.length+1];
strncpy(theName,(char *)(nameBuffer.value),(Int_t)(nameBuffer.length));
theName[nameBuffer.length]= '\0';
if (gDebug > 2)
Info("GlobusCheckSecContext","with subject name: %s (%d)",
theName, nameBuffer.length);
if (!strcmp(theName, subjName)) {
if (gDebug > 2)
Info("GlobusCheckSecContext",
"client already authenticated (remaining lifetime: %d sec)",
glbContLifeTime);
rc = 1;
}
// Release allocated space
if (theName)
delete[] theName;
if ((majStat = gss_release_name(&minStat, &name))
!= GSS_S_COMPLETE) {
if (gDebug > 0)
GlobusError("GlobusCheckSecContext: gss_release_name",
majStat, minStat, 0);
}
}
}
} else {
rc = -1;
}
return rc;
}
//______________________________________________________________________________
int GlobusGetCredHandle(Int_t localEnv, gss_cred_id_t * credHandle)
{
// Get Credential Handle, either from scratch, or from delegated info ...
// Returns 0 is successfull, 1 otherwise.
int retval = 0;
OM_uint32 majStat = 0;
OM_uint32 minStat = 0;
if (gDebug > 2)
Info("GlobusGetCredHandle", "Enter: LocalEnv: %d", localEnv);
if (localEnv == 2) {
// If we are a PROOF Master autheticating vs Slaves
// we only need to fetch the delegated credentials
// from the shared memory segment the first time we are called ...
if (gGlbDelCredHandle == GSS_C_NO_CREDENTIAL) {
if (GlobusGetDelCred()) {
if (gDebug > 0)
Error("GlobusGetCredHandle",
"unable to fetch valid credentials from the shared memory segment");
retval = 1;
goto exit;
}
}
*credHandle = gGlbDelCredHandle;
} else {
// Inquire Globus credentials:
// This is looking to file X509_USER_PROXY for valid a X509 cert
// (default /tmp/x509up_u<uid> )
if ((majStat =
globus_gss_assist_acquire_cred(&minStat, GSS_C_INITIATE,
credHandle)) != GSS_S_COMPLETE) {
// Check if interactive session
if (isatty(0) && isatty(1)) {
// Check special settings for the certificates
TString det;
GlobusGetDetails(localEnv, 1, det);
if (gDebug > 3) {
GlobusError("GlobusNameFromCred: gss_display_name",
majStat, minStat, 0);
Info("GlobusGetCredHandle",
"Failed to acquire credentials: trying to initialize proxies ...");
}
// Try to get credentials with usual command line ...
if (!gSystem->Getenv("GLOBUS_LOCATION")) {
if (gDebug > 0)
Error("GlobusGetCredHandle",
"Please define a valid GLOBUS_LOCATION");
retval = 2;
goto exit;
}
// First check if there are special requests for proxy duration ...
TString initDur(gEnv->GetValue("Globus.ProxyDuration", "default"));
if (!initDur.Contains("default")) {
initDur.Insert(0,"-hours ");
if (gDebug > 2)
Info("GlobusGetCredHandle", "initDur: %s (%s)", initDur.Data(),
gEnv->GetValue("Globus.ProxyDuration", "default"));
} else
initDur = TString("");
// ... and for number of bits in key ...
TString initBit(gEnv->GetValue("Globus.ProxyKeyBits", "default"));
if (!initBit.Contains("default")) {
initBit.Insert(0,"-bits ");
if (gDebug > 2)
Info("GlobusGetCredHandle", "initBit: %s (%s)", initBit.Data(),
gEnv->GetValue("Globus.ProxyKeyBits", "default"));
} else
initBit = TString("");
// ... and the proxy ...
TString initPxy;
if (gSystem->Getenv("X509_USER_PROXY")) {
initPxy = Form("-out %s", gSystem->Getenv("X509_USER_PROXY"));
if (gDebug > 3)
Info("GlobusGetCredHandle", "initPxy: %s", initPxy.Data());
}
// ... and environment variables
TString initEnv(Form("export X509_CERT_DIR=%s",
gSystem->Getenv("X509_CERT_DIR")));
initEnv += TString(Form("; export X509_USER_CERT=%s",
gSystem->Getenv("X509_USER_CERT")));
initEnv += TString(Form("; export X509_USER_KEY=%s",
gSystem->Getenv("X509_USER_KEY")));
if (gDebug > 3)
Info("GlobusGetCredHandle", "initEnv: %s", initEnv.Data());
// to execute command to initiate the proxies one needs
// to source the globus shell environment
TString proxyInit("source $GLOBUS_LOCATION/etc/globus-user-env.sh; ");
proxyInit += initEnv;
proxyInit += Form("; grid-proxy-init %s %s %s",
initDur.Data(), initBit.Data(), initPxy.Data());
gSystem->Exec(proxyInit);
// retry now
if ((majStat =
globus_gss_assist_acquire_cred(&minStat, GSS_C_INITIATE,
credHandle)) !=
GSS_S_COMPLETE) {
if (gDebug > 0)
GlobusError("GlobusGetCredHandle: gss_assist_acquire_cred",
majStat, minStat, 0);
retval = 3;
goto exit;
}
} else {
Warning("GlobusGetCredHandle",
"not a tty: cannot prompt for credentials, returning failure");
retval = 3;
goto exit;
}
}
}
exit:
return retval;
}
//______________________________________________________________________________
void GlobusGetDetails(Int_t localEnv, Int_t opt, TString &details)
{
// Resolve the details string from localEnv. If opt == 0 just fill the string,
// otherwise initialize the envs, prompting the user, if needed
// Returns 0 is successfull, 1 otherwise.
if (localEnv < 2) {
// User settings
Int_t reUse = TAuthenticate::GetAuthReUse();
Int_t prompt = TAuthenticate::GetPromptUser();
if (gDebug > 2)
Info("GlobusGetDetails", "prompt: %d, reUse: %d", prompt, reUse);
// System defaults
TString ddir = "~/.globus";
TString dcer = "usercert.pem";
TString dkey = "userkey.pem";
TString dadi = "/etc/grid-security/certificates";
// User defaults
if (strlen(TAuthenticate::GetDefaultUser()) > 0) {
TString dets = TAuthenticate::GetDefaultUser();
TString t;
Int_t from = 0;
while (dets.Tokenize(t,from," ")) {
if (t.BeginsWith("cd:"))
ddir = t.ReplaceAll("cd:", "");
else if (t.BeginsWith("cf:"))
dcer = t.ReplaceAll("cf:", "");
else if (t.BeginsWith("kf:"))
dkey = t.ReplaceAll("kf:", "");
else if (t.BeginsWith("ad:"))
dadi = t.ReplaceAll("ad:", "");
}
}
// Check if needs to prompt the client
if (TAuthenticate::GetPromptUser()) {
TString ppt(Form(" Local Globus settings (%s %s %s %s)\n"
" Enter <key>:<new value> to change: ",
ddir.Data(), dcer.Data(), dkey.Data(), dadi.Data()));
TString indet;
if (!gROOT->IsProofServ()) {
indet = Getline(ppt);
// get rid of \n
indet.Remove(TString::kTrailing, '\n');
if (indet.Length() > 0) {
TString t;
Int_t from = 0;
while (indet.Tokenize(t,from," ")) {
if (t.BeginsWith("cd:"))
ddir = t.ReplaceAll("cd:", "");
else if (t.BeginsWith("cf:"))
dcer = t.ReplaceAll("cf:", "");
else if (t.BeginsWith("kf:"))
dkey = t.ReplaceAll("kf:", "");
else if (t.BeginsWith("ad:"))
dadi = t.ReplaceAll("ad:", "");
}
}
} else {
Warning("GlobusGetDetails",
"proofserv: cannot prompt for info");
}
}
// Build Details
details = Form("pt:%d ru:%d %s %s %s %s",
TAuthenticate::GetPromptUser(),
TAuthenticate::GetAuthReUse(),
ddir.Data(), dcer.Data(), dkey.Data(), dadi.Data());
// Set the envs, if required
if (opt > 0) {
// Perform "~" expansion ...
gSystem->ExpandPathName(ddir);
gSystem->ExpandPathName(dcer);
gSystem->ExpandPathName(dkey);
gSystem->ExpandPathName(dadi);
// or allow for paths relative to .globus
if (!ddir.BeginsWith("/"))
ddir.Insert(0, Form("%s/.globus/", gSystem->HomeDirectory()));
if (!dcer.BeginsWith("/"))
dcer.Insert(0, Form("%s/", ddir.Data()));
if (!dkey.BeginsWith("/"))
dkey.Insert(0, Form("%s/", ddir.Data()));
if (!dadi.BeginsWith("/"))
dadi.Insert(0, Form("%s/.globus/", gSystem->HomeDirectory()));
if (gDebug > 3)
Info("GlobusSetCertificates", "after expansion: %s %s %s",
dcer.Data(), dkey.Data(), dadi.Data());
// Save them
gSystem->Setenv("X509_CERT_DIR", dadi);
gSystem->Setenv("X509_USER_CERT", dcer);
gSystem->Setenv("X509_USER_KEY", dkey);
}
}
// Done
return;
}
//______________________________________________________________________________
Int_t GlobusIssuerName(TString &issuerName)
{
// Get issuer name from the certificate read either from the
// certificate file or from the proxy file.
// Returns 0 is successfull, 1 otherwise.
if (gDebug > 2)
Info("GlobusIssuerName", "enter");
// Locate the relevant file
TString fn = gSystem->Getenv("X509_USER_PROXY");
if (fn.Length() <= 0)
fn = Form("/tmp/x509up_u%d",gSystem->GetUid());
if (gSystem->AccessPathName(fn, kReadPermission)) {
TString emsg = Form("cannot read requested file(s): %s ", fn.Data());
// Not available: try the certificate file itself
fn = gSystem->Getenv("X509_USER_CERT");
if (fn.Length() <= 0)
fn = Form("%s/.globus/usercert.pem",gSystem->HomeDirectory());
if (gSystem->AccessPathName(fn, kReadPermission)) {
emsg += fn;
Error("GlobusIssuerName", emsg.Data());
return 1;
}
}
// Load the certificate ...
X509 *xcert = 0;
FILE *fcert = fopen(fn.Data(), "r");
if (!fcert) {
Error("GlobusIssuerName", "unable to open file %s", fn.Data());
return 1;
}
// Read certificate(s) from the file
Bool_t notfound = kTRUE;
while (notfound && PEM_read_X509(fcert, &xcert, 0, 0)) {
// Retrieve issuer name
char *in = X509_NAME_oneline(X509_get_issuer_name(xcert), 0, 0);
// Retrieve subject name
char *cn = X509_NAME_oneline(X509_get_subject_name(xcert), 0, 0);
if (strncmp(in, cn, strlen(in))) {
// This is the certificate
issuerName = in;
notfound = kFALSE;
}
free(in); free(cn);
}
fclose(fcert);
// Notify failure
if (notfound) {
Error("GlobusIssuerName", "certificate not found in file %s", fn.Data());
return 1;
}
// Notify
if (gDebug > 2)
Info("GlobusIssuerName", "issuer name: %s", issuerName.Data());
// Successful
return 0;
}
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...