XRootD
Loading...
Searching...
No Matches
XrdCmsRedirLocal.cc
Go to the documentation of this file.
1//------------------------------------------------------------------------------
2// Copyright (c) 2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
3// Author: Paul-Niklas Kramp <p.n.kramp@gsi.de>
4// Jan Knedlik <j.knedlik@gsi.de>
5//------------------------------------------------------------------------------
6// XRootD is free software: you can redistribute it and/or modify
7// it under the terms of the GNU Lesser General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// XRootD is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU Lesser General Public License
17// along with XRootD. If not, see <http://www.gnu.org/licenses/>.
18//------------------------------------------------------------------------------
19
21
22//------------------------------------------------------------------------------
24//------------------------------------------------------------------------------
26 int myPort, XrdOss *theSS) {
27 XrdCmsRedirLocal *plugin = new XrdCmsRedirLocal(Logger, opMode, myPort, theSS);
28 return plugin;
29}
30
31//------------------------------------------------------------------------------
33//------------------------------------------------------------------------------
35 XrdOss *theSS) : XrdCmsClient(amLocal),
36 nativeCmsFinder(new XrdCmsFinderRMT(Logger, opMode, myPort)),
37 readOnlyredirect(true),
38 httpRedirect(false),
39 Say(0,"cms_") {
41}
42//------------------------------------------------------------------------------
44//------------------------------------------------------------------------------
46
47//------------------------------------------------------------------------------
49//------------------------------------------------------------------------------
50int XrdCmsRedirLocal::Configure(const char *cfn, char *Parms, XrdOucEnv *EnvInfo) {
51 loadConfig(cfn);
52 if(localroot.empty())
53 {
54 Say.Emsg("RedirLocal", "oss.localroot (replaced by xrdcmsredirlocal for localredirect) " \
55 "and xrdcmsredirlocal.localroot are undefined, define xrdcmsredirlocal.localroot");
56 return 0;
57 }
58 if(localroot[0] != '/')
59 {
60 Say.Emsg("RedirLocal", "oss.localroot or xrdcmsredirlocal.localroot needs to be an absolute path");
61 return 0;
62 }
64 return nativeCmsFinder->Configure(cfn, Parms, EnvInfo);
65 return 0; // means false
66}
67
68void XrdCmsRedirLocal::loadConfig(const char *filename) {
69 XrdOucStream Config;
70 int cfgFD;
71 char *word;
72
73 if ((cfgFD = open(filename, O_RDONLY, 0)) < 0) {
74 return;
75 }
76 Config.Attach(cfgFD);
77 while ((word = Config.GetFirstWord(true))) { //get word in lower case
78 // search for readonlyredirect,
79 // which only allows read calls to be redirected to local
80 if (strcmp(word, "xrdcmsredirlocal.readonlyredirect") == 0){
81 readOnlyredirect = std::string(Config.GetWord(true)).find("true") != std::string::npos;
82 }
83 // search for httpredirect,
84 // which allows http(s) calls to be redirected to local
85 else if (strcmp(word, "xrdcmsredirlocal.httpredirect") == 0){
86 httpRedirect = std::string(Config.GetWord(true)).find("true") != std::string::npos;
87 }
88 // search for newer localroot, overwrite given oss.localroot if defined,
89 // which manually sets localroot to prepend
90 else if (strcmp(word, "xrdcmsredirlocal.localroot") == 0){
91 localroot = std::string(Config.GetWord(false));
92 }
93 // search for oss.localroot,
94 // which manually sets localroot to prepend
95 else if (strcmp(word, "oss.localroot") == 0 && localroot.empty()){
96 localroot = std::string(Config.GetWord(false));
97 }
98 }
99 Config.Close();
100}
101
102//------------------------------------------------------------------------------
121//------------------------------------------------------------------------------
122int XrdCmsRedirLocal::Locate(XrdOucErrInfo &Resp, const char *path, int flags,
123 XrdOucEnv *EnvInfo) {
124 int rcode = 0;
125 if (nativeCmsFinder) {
126 // check if path contains localroot to know if potential redirection loop
127 // is happening. If yes, remove localroot from path, then rerun default
128 // locate with regular path and return to client
129 // localroot must be larger than 1 to avoid always being triggered by "/"
130 if (localroot.size() > 1 && strncmp(path, localroot.c_str(), localroot.size()) == 0)
131 {
132 // now check if localhost was tried before, to make sure we're handling
133 // the redirection loop
134 int param = 0; // need it to get Env
135 //EnvInfo->Env(param) gets already tried hosts
136 if(strstr(EnvInfo->Env(param), "tried=localhost") != nullptr)
137 {
138 std::string newPath(path);
139 // remove localroot
140 newPath = "//" + newPath.substr(localroot.size());
141 // get regular target host
142 rcode = nativeCmsFinder->Locate(Resp, newPath.c_str(), flags, EnvInfo);
143 // set new error message to full url:port//newPath
144 const std::string errText { std::string(Resp.getErrText()) + ':' + std::to_string(Resp.getErrInfo()) + newPath};
145 Resp.setErrInfo(0, errText.c_str());
146 // now have normal redirection to dataserver at url:port
147 return rcode;
148 }
149 }
150 std::string dialect = EnvInfo->secEnv()->addrInfo->Dialect();
151 // get regular target host
152 rcode = nativeCmsFinder->Locate(Resp, path, flags, EnvInfo);
153
154 // check if http redirect to local filesystem is allowed
155 if (strncmp(dialect.c_str(), "http", 4) == 0 && !httpRedirect)
156 return rcode;
157
158 // define target host from locate result
159 XrdNetAddr target(-1); // port is necessary, but can be any
160 target.Set(Resp.getErrText());
161 // does the target host have a private IP?
162 if (!target.isPrivate())
163 return rcode;
164 // does the client host have a private IP?
165 if (!EnvInfo->secEnv()->addrInfo->isPrivate())
166 return rcode;
167
168 // as we can't rely on the flags from http clients, we do not perform the below
169 if (strncmp(dialect.c_str(), "http", 4) != 0)
170 {
171 // get client url redirect capability
172 int urlRedirSupport = Resp.getUCap();
173 urlRedirSupport &= XrdOucEI::uUrlOK;
174 if (!urlRedirSupport)
175 return rcode;
176
177 // get client localredirect capability
178 int clientLRedirSupport = Resp.getUCap();
179 clientLRedirSupport &= XrdOucEI::uLclF;
180 if (!clientLRedirSupport)
181 return rcode;
182 }
183
184 // http gets SFS_O_STAT flag when opening to read, instead of SFS_O_RDONLY
185 // in case of http dialect and stat, we do not perform the checks below
186 if (!(strncmp(dialect.c_str(), "http", 4) == 0 && flags == 0x20000000))
187 {
188 // only allow simple (but most prominent) operations to avoid complications
189 // RDONLY, WRONLY, RDWR, CREAT, TRUNC are allowed
190 if (flags > 0x202)
191 return rcode;
192 // always use native function if readOnlyredirect is configured and a
193 // non readonly flag is passed
194 if (readOnlyredirect && !(flags == SFS_O_RDONLY))
195 return rcode;
196 }
197 // passed all checks, now to actual business
198 // prepend manually configured localroot
199 std::string ppath = "file://" + localroot + path;
200 if (strncmp(dialect.c_str(), "http", 4) == 0)
201 {
202 // set info which will be sent to client
203 // eliminate the resource name so it is not doubled in XrdHttpReq::Redir.
204 Resp.setErrInfo(-1, ppath.substr(0, ppath.find(path)).c_str());
205 }
206 else{
207 // set info which will be sent to client
208 Resp.setErrInfo(-1, ppath.c_str());
209 }
210 return SFS_REDIRECT;
211 }
212 return rcode;
213}
214
215//------------------------------------------------------------------------------
218//------------------------------------------------------------------------------
219int XrdCmsRedirLocal::Space(XrdOucErrInfo &Resp, const char *path,
220 XrdOucEnv *EnvInfo) {
221 if (nativeCmsFinder)
222 return nativeCmsFinder->Space(Resp, path, EnvInfo);
223 return 0;
224}
225
XrdOucPup XrdCmsParser::Pup & Say
XrdVERSIONINFO(XrdCmsGetClient, XrdCmsRedirLocal)
XrdCmsClient * XrdCmsGetClient(XrdSysLogger *Logger, int opMode, int myPort, XrdOss *theSS)
Necessary implementation for XRootD to get the Plug-in.
static XrdSysLogger Logger
#define open
Definition XrdPosix.hh:76
#define SFS_REDIRECT
#define SFS_O_RDONLY
virtual int Configure(const char *cfn, char *Parms, XrdOucEnv *EnvInfo)=0
virtual int Space(XrdOucErrInfo &Resp, const char *path, XrdOucEnv *Info=0)=0
virtual int Locate(XrdOucErrInfo &Resp, const char *path, int flags, XrdOucEnv *Info=0)=0
int Configure(const char *cfn, char *Parms, XrdOucEnv *EnvInfo)
Configure the nativeCmsFinder.
~XrdCmsRedirLocal()
Destructor.
XrdCmsClient * nativeCmsFinder
used to forward requests to CmsFinder with regular implementation
void loadConfig(const char *filename)
int Locate(XrdOucErrInfo &Resp, const char *path, int flags, XrdOucEnv *EnvInfo)
XrdCmsRedirLocal(XrdSysLogger *Logger, int opMode, int myPort, XrdOss *theSS)
Constructor.
int Space(XrdOucErrInfo &Resp, const char *path, XrdOucEnv *EnvInfo)
const char * Dialect()
const char * Set(const char *hSpec, int pNum=PortInSpec)
char * Env(int &envlen)
Definition XrdOucEnv.hh:48
const XrdSecEntity * secEnv() const
Definition XrdOucEnv.hh:107
const char * getErrText()
int setErrInfo(int code, const char *emsg)
XrdNetAddrInfo * addrInfo
Entity's connection details.
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
XrdSysLogger * logger(XrdSysLogger *lp=0)
static const int uUrlOK
ucap: Supports async responses
static const int uLclF
ucap: Client is on a private net