Skip to content

Commit

Permalink
[Server] Enable use of delegated credentials for 3rd party copy.
Browse files Browse the repository at this point in the history
  • Loading branch information
abh3 committed Jun 20, 2018
1 parent 02c9a0d commit 59f6c2a
Show file tree
Hide file tree
Showing 16 changed files with 565 additions and 65 deletions.
14 changes: 9 additions & 5 deletions docs/man/xrdcp.1
Expand Up @@ -11,8 +11,8 @@ xrdcp - copy files
[\fB--nopbar\fR] [\fB--posc\fR] [\fB--proxy \fIipaddr\fB:\fIport\fR]
[\fB--recursive\fR] [\fB--retry\fR \fItime\fR] [\fB--server\fR]
[\fB--silent\fR] [\fB--sources\fR \fInum\fR] [\fB--streams\fR \fInum\fR]
[\fB--tpc\fR \fIfirst\fR|\fIonly\fR] [\fB--verbose\fR] [\fB--version\fR]
[\fB--xrate\fR \fIrate\fR] [\fB--zip\fR \fIfile\fR]
[\fB--tpc\fR [\fBdelegate\fR] \fBfirst\fR|\fBonly\fR] [\fB--verbose\fR]
[\fB--version\fR] [\fB--xrate\fR \fIrate\fR] [\fB--zip\fR \fIfile\fR]

\fIlegacy options\fR: [\fB-adler\fR] [\fB-DS\fR\fIparm string\fR] [\fB-DI\fR\fIparm number\fR]
[\fB-md5\fR] [\fB-np\fR] [\fB-OD\fR\fIcgi\fR] [\fB-OS\fR\fIcgi\fR] [\fB-x\fR]
Expand Down Expand Up @@ -109,14 +109,18 @@ uses \fInum\fR additional parallel streams to do the transfer.
The maximum value is 15. The default is 0 (i.e., use only the main stream).

.RE
\fB--tpc\fR \fIfirst|only\fR
\fB--tpc\fR [\fBdelegate\fR] \fBfirst\fR|\fBonly\fR
.RS 5
copies the file from remote server to remote server using third-party-copy
protocol (i.e., data flows from server to server). The source and destination
servers must support third party copies. Additional security restrictions
may apply and may cause the copy to fail if they cannot be satisfied.
Argument \fI'first'\fR tries tpc and if it fails, does a normal copy;
while \fI'only'\fR fails the copy unless tpc succeeds.
Argument '\fBfirst\fR' tries tpc and if it fails, does a normal copy;
while '\fBonly\fR' fails the copy unless tpc succeeds. When '\fBdelegate\fR' is
specified, the copy delegates the command issuer's credentials to the target
server which uses those credentials to authenticate with the source server.
Delegation is ignored if the target server is not configured to use delegated
credentials. Currently, only gsi credentials can be delegated.

.RE
\fB-v\fR | \fB--verbose\fR
Expand Down
16 changes: 12 additions & 4 deletions src/XrdApps/XrdCpConfig.cc
Expand Up @@ -265,6 +265,14 @@ do{while(optind < Argc && Legacy(optind)) {}
if (!a2i(optarg, &nStrm, 1, 15)) Usage(22);
break;
case OpTpc: OpSpec |= DoTpc;
if (!strcmp("delegate", optarg))
{OpSpec|= DoTpcDlgt;
if (optind >= Argc)
{UMSG("Missing tpc qualifier after "
"'delegate'");
}
optarg = Argv[optind++];
}
if (!strcmp("only", optarg)) OpSpec|= DoTpcOnly;
else if (strcmp("first", optarg))
{optind--;
Expand Down Expand Up @@ -864,10 +872,10 @@ void XrdCpConfig::Usage(int rc)
static const char *Options= "\n"
"Options: [--cksum <args>] [--debug <lvl>] [--coerce] [--dynamic-src]\n"
" [--force] [--help] [--infiles <fn>] [--license] [--nopbar]\n"
" [--path] [--posc] [--proxy <host>:<port>] [--recursive]\n"
" [--retry <n>] [--server] [--silent] [--sources <n>] [--streams <n>]\n"
" [--tpc {first|only}] [--verbose] [--version] [--xrate <rate>]\n"
" [--parallel <n>] [--zip <file>]";
" [--path] [--parallel <n>] [--posc] [--proxy <host>:<port>]\n"
" [--recursive] [--retry <n>] [--server] [--silent] [--sources <n>]\n"
" [--streams <n>] [--tpc [delegate] {first|only}] [--verbose]\n"
" [--version] [--xrate <rate>] [--zip <file>]";

static const char *Syntax2= "\n"
"<src>: [[x]root://<host>[:<port>]/]<path> | -";
Expand Down
3 changes: 3 additions & 0 deletions src/XrdApps/XrdCpConfig.hh
Expand Up @@ -144,6 +144,7 @@ static const int DoStreams = 0x00010000; // -S | --streams
static const int OpTpc = 'T';
static const int DoTpc = 0x00020000; // -T | --tpc {first | only}
static const int DoTpcOnly = 0x00100000; // -T | --tpc only
static const int DoTpcDlgt = 0x00800000; // -T | --tpc delegate ...

static const int OpVerbose = 'v';
static const int DoVerbose = 0x00040000; // -v | --verbose
Expand All @@ -159,6 +160,8 @@ static const int DoParallel = 0x00200000; // --parallel
static const int OpDynaSrc = 'Z';
static const int DoDynaSrc = 0x00400000; // --dynamic-src

// const int DoTpcDlgt = 0x00800000; // Marker to show bit used

static const int OpZip = 'z';
static const int DoZip = 0x01000000;// --zip

Expand Down
3 changes: 2 additions & 1 deletion src/XrdOfs/XrdOfs.cc
Expand Up @@ -562,7 +562,8 @@ int XrdOfsFile::open(const char *path, // In
}

// If this is a third party copy and we are the destination, then validate
// specification at this point and setup to transfer.
// specification at this point and setup to transfer. Note that if the
// call fails and auto removal is enabled, the file we created will be deleted.
//
if (tpcKey && isRW)
{char pfnbuff[MAXPATHLEN+8]; const char *pfnP;
Expand Down
2 changes: 2 additions & 0 deletions src/XrdOfs/XrdOfs.hh
Expand Up @@ -402,6 +402,8 @@ XrdSysMutex ocMutex; // Global mutex for open/close
int ConfigDispFwd(char *buff, struct fwdOpt &Fwd);
int ConfigPosc(XrdSysError &Eroute);
int ConfigRedir(XrdSysError &Eroute, XrdOucEnv *EnvInfo);
int ConfigTPC(XrdSysError &Eroute);
char *ConfigTPCDir(XrdSysError &Eroute, const char *xPath);
const char *Fname(const char *);
int Forward(int &Result, XrdOucErrInfo &Resp, struct fwdOpt &Fwd,
const char *arg1=0, const char *arg2=0,
Expand Down
155 changes: 149 additions & 6 deletions src/XrdOfs/XrdOfsConfig.cc
Expand Up @@ -38,6 +38,7 @@
#include <stdio.h>
#include <netinet/in.h>
#include <sys/param.h>
#include <sys/stat.h>

#include "XrdVersion.hh"

Expand All @@ -57,6 +58,7 @@
#include "XrdOuc/XrdOucEnv.hh"
#include "XrdSys/XrdSysError.hh"
#include "XrdSys/XrdSysHeaders.hh"
#include "XrdOuc/XrdOucNSWalk.hh"
#include "XrdOuc/XrdOucStream.hh"
#include "XrdOuc/XrdOucTrace.hh"
#include "XrdOuc/XrdOucUtils.hh"
Expand All @@ -82,6 +84,13 @@ extern XrdOss *XrdOfsOss;

XrdVERSIONINFO(XrdOfs,XrdOfs);

namespace
{
XrdOfsTPC::iParm Parms; // TPC parameters

int SetMode(const char *path, mode_t mode) {return chmod(path, mode);}
}

/******************************************************************************/
/* d e f i n e s */
/******************************************************************************/
Expand Down Expand Up @@ -235,7 +244,7 @@ int XrdOfs::Configure(XrdSysError &Eroute, XrdOucEnv *EnvInfo) {
// Configure third party copy but only if we are not a manager
//
if ((Options & ThirdPC) && !(Options & isManager))
if (!XrdOfsTPC::Start()) NoGo = 1;
NoGo |= ConfigTPC(Eroute);

// We need to do pre-initialization for event recording as the oss needs some
// environmental information from that initialization to initialize the frm,
Expand Down Expand Up @@ -572,6 +581,101 @@ int XrdOfs::ConfigRedir(XrdSysError &Eroute, XrdOucEnv *EnvInfo)
return 0;
}

/******************************************************************************/
/* C o n f i g T P C */
/******************************************************************************/

int XrdOfs::ConfigTPC(XrdSysError &Eroute)
{

// Check if we need to configure rge credentials directory
//
if (Parms.fCreds)
{char *cpath = Parms.cpath;
if (!(Parms.cpath = ConfigTPCDir(Eroute, cpath))) return 1;
free(cpath);
}

// Initialize the TPC object
//
XrdOfsTPC::Init(Parms);

// Start TPC operations
//
return (XrdOfsTPC::Start() ? 0 : 1);
}

/******************************************************************************/
/* C o n f i g T P C D i r */
/******************************************************************************/

char *XrdOfs::ConfigTPCDir(XrdSysError &Eroute, const char *xPath)
{

const int AMode = S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH; // 775
const int BMode = S_IRWXU| S_IRGRP|S_IXGRP; // 750
const char *iName;
char pBuff[MAXPATHLEN], *aPath;
int rc;

// Construct the proper path to stored credentials
//
iName = XrdOucUtils::InstName(-1);
if (xPath) aPath = XrdOucUtils::genPath(xPath, iName, ".ofs/.tpccreds/");
else {if (!(aPath = getenv("XRDADMINPATH")))
{XrdOucUtils::genPath(pBuff, MAXPATHLEN, "/tmp", iName);
aPath = pBuff;
}
aPath = XrdOucUtils::genPath(aPath, (char *)0, ".ofs/.tpccreds/");
}

// Make sure directory path exists
//
if ((rc = XrdOucUtils::makePath(aPath, AMode)))
{Eroute.Emsg("Config", rc, "create TPC path", aPath);
free(aPath);
return 0;
}

// Protect the last component
//
if (SetMode(aPath, BMode))
{Eroute.Emsg("Config", errno, "protect TPC path", aPath);
free(aPath);
return 0;
}

// list the contents of teh directory
//
XrdOucNSWalk nsWalk(&Eroute, aPath, 0, XrdOucNSWalk::retFile);
XrdOucNSWalk::NSEnt *nsX, *nsP = nsWalk.Index(rc);
if (rc)
{Eroute.Emsg("Config", rc, "list TPC path", aPath);
free(aPath);
return 0;
}

// Remove directory contents of all files
//
bool isBad = false;
while((nsX = nsP))
{nsP = nsP->Next;
if (unlink(nsX->Path))
{Eroute.Emsg("Config", errno, "remove TPC creds", nsX->Path);
isBad = true;
}
delete nsX;
}

// Check if all went well
//
if (isBad) {free(aPath); return 0;}

// All done
//
return aPath;
}

/******************************************************************************/
/* C o n f i g X e q */
/******************************************************************************/
Expand Down Expand Up @@ -1195,9 +1299,12 @@ int XrdOfs::xrole(XrdOucStream &Config, XrdSysError &Eroute)
Purpose: To parse the directive: tpc [cksum <type>] [ttl <dflt> [<max>]]
[logok] [xfr <n>] [allow <parms>]
[require {all|client|dest} <auth>[+]]
[restrict <path>] [streams <num>]
[restrict <path>]
[streams <num>[,<max>]]
[echo] [scan {stderr | stdout}]
[autorm] [pgm <path> [parms]]
[fcreds [?]<auth> =<evar>]
[fcpath <path>]
parms: [dn <name>] [group <grp>] [host <hn>] [vo <vo>]
Expand All @@ -1208,7 +1315,8 @@ int XrdOfs::xrole(XrdOucStream &Config, XrdSysError &Eroute)
allow only allow destinations that match the specified
authentication specification.
<n> maximum number of simultaneous transfers.
<num> the number of TCP streams to use for the copy.
<num> the default number of TCP streams to use for the copy.
<max> The maximum number of TCP streams to use for the copy/
<auth> require that the client, destination, or both (i.e. all)
use the specified authentication protocol. Additional
require statements may be specified to add additional
Expand All @@ -1221,13 +1329,20 @@ int XrdOfs::xrole(XrdOucStream &Config, XrdSysError &Eroute)
default is to scan both.
pgm specifies the transfer command with optional paramaters.
It must be the last parameter on the line.
fcreds Forward destination credentials for protocol <auth>. The
request fails if thee are no credentials for <auth>. If a
question mark preceeds <auth> then if the client has not
forwarded its credentials, the server's credentials are
used. Otherwise, the copy fails.
=<evar> the name of the envar to be set with the path to the
credentials to be forwarded.
fcpath where creds are stored (default <adminpath>/.ofs/.tpccreds).
Output: 0 upon success or !0 upon failure.
*/

int XrdOfs::xtpc(XrdOucStream &Config, XrdSysError &Eroute)
{
XrdOfsTPC::iParm Parms;
char *val, pgm[1024];
int reqType;
*pgm = 0;
Expand Down Expand Up @@ -1305,13 +1420,41 @@ int XrdOfs::xtpc(XrdOucStream &Config, XrdSysError &Eroute)
if (!strcmp(val, "streams"))
{if (!(val = Config.GetWord()))
{Eroute.Emsg("Config","tpc streams value not specified"); return 1;}
if (XrdOuca2x::a2i(Eroute,"tpc streams",val,&Parms.Strm,1)) return 1;
char *comma = index(val,',');
if (comma)
{*comma++ = 0;
if (!(*comma))
{Eroute.Emsg("Config","tpc streams max value missing"); return 1;}
if (XrdOuca2x::a2i(Eroute,"tpc max streams",comma,&Parms.SMax,0,15))
return 1;
}
if (XrdOuca2x::a2i(Eroute,"tpc streams",val,&Parms.Strm,0,15)) return 1;
continue;
}
if (!strcmp(val, "fcreds"))
{char aBuff[64];
Parms.fCreds = 1;
if (!(val = Config.GetWord()) || (*val == '?' && *(val+1) == '\0'))
{Eroute.Emsg("Config","tpc fcreds auth not specified"); return 1;}
if (strlen(val) >= sizeof(aBuff))
{Eroute.Emsg("Config","invalid fcreds auth -", val); return 1;}
strcpy(aBuff, val);
if (!(val = Config.GetWord()) || *val != '=' || *(val+1) == 0)
{Eroute.Emsg("Config","tpc fcreds envar not specified"); return 1;}
const char *emsg = XrdOfsTPC::AddAuth(aBuff,val+1);
if (emsg) {Eroute.Emsg("Config",emsg,"-", val); return 1;}
continue;
}
if (!strcmp(val, "fcpath"))
{if (Parms.cpath) {free(Parms.cpath); Parms.cpath = 0;}
if (!(val = Config.GetWord()))
{Eroute.Emsg("Config","tpc fcpath arg not specified"); return 1;}
Parms.cpath = strdup(val);
continue;
}
Eroute.Say("Config warning: ignoring invalid tpc option '",val,"'.");
}

XrdOfsTPC::Init(Parms);
Options |= ThirdPC;
return 0;
}
Expand Down

0 comments on commit 59f6c2a

Please sign in to comment.