XRootD
XrdHttpTpcConfigure.cc
Go to the documentation of this file.
1 
2 #include "XrdHttpTpcTPC.hh"
3 
4 #include <dlfcn.h>
5 #include <fcntl.h>
6 
7 #include "XrdOuc/XrdOuca2x.hh"
8 #include "XrdOuc/XrdOucEnv.hh"
9 #include "XrdOuc/XrdOucStream.hh"
10 #include "XrdOuc/XrdOucPinPath.hh"
13 #include "XrdOuc/XrdOucTUtils.hh"
14 
15 using namespace TPC;
16 
17 
18 bool TPCHandler::Configure(const char *configfn, XrdOucEnv *myEnv)
19 {
20  XrdOucEnv cfgEnv;
21  XrdOucStream Config(&m_log, getenv("XRDINSTANCE"), &cfgEnv, "=====> ");
22 
24 
25  // test if XrdEC is used
26  usingEC = getenv("XRDCL_EC")? true : false;
27  // Test if the CRL checking is enabled
28  allowMissingCRL = (bool) myEnv->GetInt("http.allowmissingcrl");
29  std::string authLib;
30  std::string authLibParms;
31  int cfgFD = open(configfn, O_RDONLY, 0);
32  if (cfgFD < 0) {
33  m_log.Emsg("Config", errno, "open config file", configfn);
34  return false;
35  }
36  Config.Attach(cfgFD);
37  static const char *cvec[] = { "*** http tpc plugin config:", 0 };
38  Config.Capture(cvec);
39  const char *val;
40  while ((val = Config.GetMyFirstWord())) {
41  if (!strcmp("http.desthttps", val)) {
42  if (!(val = Config.GetWord())) {
43  Config.Close();
44  m_log.Emsg("Config", "http.desthttps value not specified");
45  return false;
46  }
47  if (!strcmp("1", val) || !strcasecmp("yes", val) || !strcasecmp("true", val)) {
48  m_desthttps = true;
49  } else if (!strcmp("0", val) || !strcasecmp("no", val) || !strcasecmp("false", val)) {
50  m_desthttps = false;
51  } else {
52  Config.Close();
53  m_log.Emsg("Config", "https.desthttps value is invalid", val);
54  return false;
55  }
56  } else if (!strcmp("tpc.allow", val)) {
57  if (!(val = Config.GetWord())) {
58  Config.Close();
59  m_log.Emsg("Config", "tpc.allow value not specified");
60  return false;
61  }
62  if (strcmp(val, "local") == 0) {
63  m_allow_local = true;
64  } else if (strcmp(val, "private") == 0) {
65  m_allow_private = true;
66  } else {
67  Config.Close();
68  m_log.Emsg("Config", "tpc.allow value is invalid", val);
69  return false;
70  }
71  } else if (!strcmp("tpc.deny", val)) {
72  if (!(val = Config.GetWord())) {
73  Config.Close();
74  m_log.Emsg("Config", "tpc.deny value not specified");
75  return false;
76  }
77  if (strcmp(val, "local") == 0) {
78  m_allow_local = false;
79  } else if (strcmp(val, "private") == 0) {
80  m_allow_private = false;
81  } else {
82  Config.Close();
83  m_log.Emsg("Config", "tpc.deny value is invalid", val);
84  return false;
85  }
86  } else if (!strcmp("tpc.trace", val)) {
87  if (!ConfigureLogger(Config)) {
88  Config.Close();
89  return false;
90  }
91  } else if (!strcmp("tpc.fixed_route", val)) {
92  if (!(val = Config.GetWord())) {
93  Config.Close();
94  m_log.Emsg("Config", "tpc.fixed_route value not specified");
95  return false;
96  }
97  if (!strcmp("1", val) || !strcasecmp("yes", val) || !strcasecmp("true", val)) {
98  m_fixed_route= true;
99  } else if (!strcmp("0", val) || !strcasecmp("no", val) || !strcasecmp("false", val)) {
100  m_fixed_route= false;
101  } else {
102  Config.Close();
103  m_log.Emsg("Config", "tpc.fixed_route value is invalid", val);
104  return false;
105  }
106  } else if (!strcmp("tpc.header2cgi",val)) {
107  // header2cgi parsing
108  if(XrdHttpProtocol::parseHeader2CGI(Config,m_log,hdr2cgimap)){
109  Config.Close();
110  return false;
111  }
112  // remove authorization header2cgi parsing as it will anyway be added to the CGI before the file open
113  // by the HTTP/TPC logic
114  auto authHdr = XrdOucTUtils::caseInsensitiveFind(hdr2cgimap,"authorization");
115  if(authHdr != hdr2cgimap.end()) {
116  hdr2cgimap.erase(authHdr);
117  }
118  } else if (!strcmp("tpc.timeout", val)) {
119  if (!(val = Config.GetWord())) {
120  Config.Close();
121  m_log.Emsg("Config","tpc.timeout value not specified."); return false;
122  }
123  if (XrdOuca2x::a2tm(m_log, "timeout value", val, &m_timeout, 0)) return false;
124  // First byte timeout can be set separately from the continuous timeout.
125  if ((val = Config.GetWord())) {
126  if (XrdOuca2x::a2tm(m_log, "first byte timeout value", val, &m_first_timeout, 0)) return false;
127  } else {
128  m_first_timeout = 2*m_timeout;
129  }
130  }
131  }
132  Config.Close();
133 
134  // Internal override: allow xrdtpc to use a different ca dir from the one prepared by the xrootd
135  // framework. meant for exceptional situations where the site might need a specially-prepared set
136  // of cas only for tpc (such as trying out various workarounds for libnss). Explicitly disables
137  // the NSS hack below.
138  auto env_cadir = getenv("XRDTPC_CADIR");
139  if (env_cadir) m_cadir = env_cadir;
140 
141  const char *cadir = nullptr, *cafile = nullptr;
142  if ((cadir = env_cadir ? env_cadir : myEnv->Get("http.cadir"))) {
143  m_cadir = cadir;
144  if (!env_cadir) {
145  m_ca_file.reset(new XrdTlsTempCA(&m_log, m_cadir));
146  if (!m_ca_file->IsValid()) {
147  m_log.Emsg("Config", "CAs / CRL generation for libcurl failed.");
148  return false;
149  }
150  }
151  }
152  if ((cafile = myEnv->Get("http.cafile"))) {
153  m_cafile = cafile;
154  }
155 
156  if (!cadir && !cafile) {
157  // We do not necessary need TLS to perform HTTP TPC transfers, just log that these values were not specified
158  m_log.Emsg("Config", "neither xrd.tls cadir nor certfile value specified; is TLS enabled?");
159  }
160 
161  void *sfs_raw_ptr;
162  if ((sfs_raw_ptr = myEnv->GetPtr("XrdSfsFileSystem*"))) {
163  m_sfs = static_cast<XrdSfsFileSystem*>(sfs_raw_ptr);
164  m_log.Emsg("Config", "Using filesystem object from the framework.");
165  return true;
166  } else {
167  m_log.Emsg("Config", "No filesystem object available to HTTP-TPC subsystem. Internal error.");
168  return false;
169  }
170  return true;
171 }
172 
173 bool TPCHandler::ConfigureLogger(XrdOucStream &config_obj)
174 {
175  char *val = config_obj.GetWord();
176  if (!val || !val[0])
177  {
178  m_log.Emsg("Config", "tpc.trace requires at least one directive [all | error | warning | info | debug | none]");
179  return false;
180  }
181  // If the config option is given, reset the log mask.
182  m_log.setMsgMask(0);
183 
184  do {
185  if (!strcasecmp(val, "all"))
186  {
187  m_log.setMsgMask(m_log.getMsgMask() | LogMask::All);
188  }
189  else if (!strcasecmp(val, "error"))
190  {
191  m_log.setMsgMask(m_log.getMsgMask() | LogMask::Error);
192  }
193  else if (!strcasecmp(val, "warning"))
194  {
195  m_log.setMsgMask(m_log.getMsgMask() | LogMask::Warning);
196  }
197  else if (!strcasecmp(val, "info"))
198  {
199  m_log.setMsgMask(m_log.getMsgMask() | LogMask::Info);
200  }
201  else if (!strcasecmp(val, "debug"))
202  {
203  m_log.setMsgMask(m_log.getMsgMask() | LogMask::Debug);
204  }
205  else if (!strcasecmp(val, "none"))
206  {
207  m_log.setMsgMask(0);
208  }
209  else
210  {
211  m_log.Emsg("Config", "tpc.trace encountered an unknown directive (valid values: [all | error | warning | info | debug | none]):", val);
212  return false;
213  }
214  val = config_obj.GetWord();
215  } while (val);
216 
217  return true;
218 }
A pragmatic implementation of the HTTP/DAV protocol for the Xrd framework.
#define open
Definition: XrdPosix.hh:78
bool Debug
@ Error
static int parseHeader2CGI(XrdOucStream &Config, XrdSysError &err, std::map< std::string, std::string > &header2cgi)
Use this function to parse header2cgi configurations.
long GetInt(const char *varname)
Definition: XrdOucEnv.cc:253
void * GetPtr(const char *varname)
Definition: XrdOucEnv.cc:281
char * Get(const char *varname)
Definition: XrdOucEnv.hh:69
char * GetWord(int lowcase=0)
static std::map< std::string, T >::const_iterator caseInsensitiveFind(const std::map< std::string, T > &m, const std::string &lowerCaseSearchKey)
Definition: XrdOucTUtils.hh:79
static int a2tm(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
Definition: XrdOuca2x.cc:288
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:116
void setMsgMask(int mask)
Definition: XrdSysError.hh:188
int getMsgMask()
Definition: XrdSysError.hh:190
@ Warning
XrdCmsConfig Config