Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
XrdProofdManager.cxx
Go to the documentation of this file.
1 // @(#)root/proofd:$Id$
2 // Author: G. Ganis June 2007
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 //////////////////////////////////////////////////////////////////////////
13 // //
14 // XrdProofdManager //
15 // //
16 // Author: G. Ganis, CERN, 2007 //
17 // //
18 // Class mapping manager functionality. //
19 // On masters it keeps info about the available worker nodes and allows //
20 // communication with them. //
21 // On workers it handles the communication with the master. //
22 // //
23 //////////////////////////////////////////////////////////////////////////
24 #include "XrdProofdPlatform.h"
25 
26 #include "XrdProofdManager.h"
27 
28 #include "XrdVersion.hh"
29 #include "Xrd/XrdProtocol.hh"
30 #include "XrdOuc/XrdOucEnv.hh"
31 #include "XrdOuc/XrdOucStream.hh"
32 #include "XrdSys/XrdSysPriv.hh"
33 
34 #include "XpdSysPlugin.h"
35 #include "XpdSysTimer.h"
36 #include "XpdSysDNS.h"
37 
38 #include "XrdProofdAdmin.h"
39 #include "XrdProofdClient.h"
40 #include "XrdProofdClientMgr.h"
41 #include "XrdProofdConfig.h"
42 #include "XrdProofdNetMgr.h"
43 #include "XrdProofdPriorityMgr.h"
44 #include "XrdProofdProofServMgr.h"
45 #include "XrdProofdProtocol.h"
46 #include "XrdProofGroup.h"
47 #include "XrdProofSched.h"
48 #include "XrdProofdProofServ.h"
49 #include "XrdProofWorker.h"
50 #include "XrdROOT.h"
51 #include "rpdconn.h"
52 
53 // Tracing utilities
54 #include "XrdProofdTrace.h"
55 
56 #include <grp.h>
57 #include <unistd.h>
58 
59 // Auxilliary sructure used internally to extract list of allowed/denied user names
60 // when running in access control mode
61 typedef struct {
62  XrdOucString allowed;
63  XrdOucString denied;
64 } xpd_acm_lists_t;
65 
66 // Protocol loader; arguments: const char *pname, char *parms, XrdProtocol_Config *pi
67 typedef XrdProtocol *(*XrdProtocolLoader_t)(const char *, char *, XrdProtocol_Config *);
68 
69 #ifdef __sun
70 /*-
71  * Copyright (c) 1991, 1993
72  * The Regents of the University of California. All rights reserved.
73  *
74  * Redistribution and use in source and binary forms, with or without
75  * modification, are permitted provided that the following conditions
76  * are met:
77  * 1. Redistributions of source code must retain the above copyright
78  * notice, this list of conditions and the following disclaimer.
79  * 2. Redistributions in binary form must reproduce the above copyright
80  * notice, this list of conditions and the following disclaimer in the
81  * documentation and/or other materials provided with the distribution.
82  * 3. All advertising materials mentioning features or use of this software
83  * must display the following acknowledgement:
84  * This product includes software developed by the University of
85  * California, Berkeley and its contributors.
86  * 4. Neither the name of the University nor the names of its contributors
87  * may be used to endorse or promote products derived from this software
88  * without specific prior written permission.
89  *
90  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
91  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
92  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
93  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
94  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
95  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
96  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
97  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
98  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
99  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
100  * SUCH DAMAGE.
101  */
102 
103 #if 0
104 #if defined(LIBC_SCCS) && !defined(lint)
105 static char sccsid[] = "@(#)getgrouplist.c 8.2 (Berkeley) 12/8/94";
106 #endif /* LIBC_SCCS and not lint */
107 #include <sys/cdefs.h>
108 __FBSDID("$FreeBSD: src/lib/libc/gen/getgrouplist.c,v 1.14 2005/05/03 16:20:03 delphij Exp $");
109 #endif
110 
111 /*
112  * get credential
113  */
114 #include <sys/types.h>
115 
116 #include <string.h>
117 
118 int
119 getgrouplist(const char *uname, gid_t agroup, gid_t *groups, int *grpcnt)
120 {
121  const struct group *grp;
122  int i, maxgroups, ngroups, ret;
123 
124  ret = 0;
125  ngroups = 0;
126  maxgroups = *grpcnt;
127  /*
128  * When installing primary group, duplicate it;
129  * the first element of groups is the effective gid
130  * and will be overwritten when a setgid file is executed.
131  */
132  groups ? groups[ngroups++] = agroup : ngroups++;
133  if (maxgroups > 1)
134  groups ? groups[ngroups++] = agroup : ngroups++;
135  /*
136  * Scan the group file to find additional groups.
137  */
138  setgrent();
139  while ((grp = getgrent()) != NULL) {
140  if (groups) {
141  for (i = 0; i < ngroups; i++) {
142  if (grp->gr_gid == groups[i])
143  goto skip;
144  }
145  }
146  for (i = 0; grp->gr_mem[i]; i++) {
147  if (!strcmp(grp->gr_mem[i], uname)) {
148  if (ngroups >= maxgroups) {
149  ret = -1;
150  break;
151  }
152  groups ? groups[ngroups++] = grp->gr_gid : ngroups++;
153  break;
154  }
155  }
156 skip:
157  ;
158  }
159  endgrent();
160  *grpcnt = ngroups;
161  return (ret);
162 }
163 #endif
164 
165 //--------------------------------------------------------------------------
166 //
167 // XrdProofdManagerCron
168 //
169 // Function run in separate thread doing regular checks
170 //
171 ////////////////////////////////////////////////////////////////////////////////
172 /// This is an endless loop to periodically check the system
173 
174 void *XrdProofdManagerCron(void *p)
175 {
176  XPDLOC(PMGR, "ManagerCron")
177 
178  XrdProofdManager *mgr = (XrdProofdManager *)p;
179  if (!(mgr)) {
180  TRACE(REQ, "undefined manager: cannot start");
181  return (void *)0;
182  }
183 
184  TRACE(REQ, "started with frequency " << mgr->CronFrequency() << " sec");
185 
186  // Get Midnight time
187  int now = time(0);
188  int mid = XrdSysTimer::Midnight(now);
189  while (mid < now) {
190  mid += 86400;
191  }
192  TRACE(REQ, "midnight in " << (mid - now) << " secs");
193 
194  while (1) {
195  // Do something here
196  TRACE(REQ, "running periodical checks");
197  // Check the log file ownership
198  mgr->CheckLogFileOwnership();
199  // Wait a while
200  int tw = mgr->CronFrequency();
201  now = time(0);
202  if ((mid - now) <= tw) {
203  tw = mid - now + 2; // Always run a check just after midnight
204  mid += 86400;
205  }
206 
207  // Check if reconfiguration of some services is required (triggered by a change
208  // of the configuration file)
209  if (mgr->SessionMgr()) mgr->SessionMgr()->Config(1);
210  if (mgr->GroupsMgr()) mgr->GroupsMgr()->Config(mgr->GroupsMgr()->GetCfgFile());
211 
212  XrdSysTimer::Wait(tw * 1000);
213  }
214 
215  // Should never come here
216  return (void *)0;
217 }
218 
219 ////////////////////////////////////////////////////////////////////////////////
220 /// Constructor
221 
222 XrdProofdManager::XrdProofdManager(char *parms, XrdProtocol_Config *pi, XrdSysError *edest)
223  : XrdProofdConfig(pi->ConfigFN, edest)
224 {
225 
226  fParms = parms; // only used for construction: not to be trusted later on
227  fPi = pi; // only used for construction: not to be trusted later on
228 
229  fSrvType = kXPD_AnyServer;
230  fEffectiveUser = "";
231  fHost = "";
232  fPort = XPD_DEF_PORT;
233  fImage = ""; // image name for these servers
234  fSockPathDir = "";
235  fStageReqRepo = "";
236  fTMPdir = "/tmp";
237  fWorkDir = "";
238  fMUWorkDir = "";
239  fSuperMst = 0;
240  fRemotePLite = 0;
241  fNamespace = "/proofpool";
242  fMastersAllowed.clear();
243  fOperationMode = kXPD_OpModeOpen;
244  fMultiUser = 0;
245  fChangeOwn = 0;
246  fCronFrequency = 30;
247 
248  // Data dir
249  fDataDir = ""; // Default <workdir>/<user>/data
250  fDataDirOpts = ""; // Default: no action
251  fDataDirUrlOpts = ""; // Default: none
252 
253  // Tools to enable xrootd file serving
254  fXrootdLibPath = "<>";
255  fXrootdPlugin = 0;
256 
257  // Proof admin path
258  fAdminPath = pi->AdmPath;
259  fAdminPath += "/.xproofd.";
260 
261  // Lib paths for proofserv
262  fBareLibPath = "";
263  fRemoveROOTLibPaths = 0;
264  fLibPathsToRemove.Purge();
265 
266  // Services
267  fSched = pi->Sched;
268  fAdmin = 0;
269  fClientMgr = 0;
270  fGroupsMgr = 0;
271  fNetMgr = 0;
272  fPriorityMgr = 0;
273  fProofSched = 0;
274  fSessionMgr = 0;
275 
276  // Configuration directives
277  RegisterDirectives();
278 
279  // Admin request handler
280  fAdmin = new XrdProofdAdmin(this, pi, edest);
281 
282  // Client manager
283  fClientMgr = new XrdProofdClientMgr(this, pi, edest);
284 
285  // Network manager
286  fNetMgr = new XrdProofdNetMgr(this, pi, edest);
287 
288  // Priority manager
289  fPriorityMgr = new XrdProofdPriorityMgr(this, pi, edest);
290 
291  // ROOT versions manager
292  fROOTMgr = new XrdROOTMgr(this, pi, edest);
293 
294  // Session manager
295  fSessionMgr = new XrdProofdProofServMgr(this, pi, edest);
296 }
297 
298 ////////////////////////////////////////////////////////////////////////////////
299 /// Destructor
300 
301 XrdProofdManager::~XrdProofdManager()
302 {
303  // Destroy the configuration handler
304  SafeDelete(fAdmin);
305  SafeDelete(fClientMgr);
306  SafeDelete(fNetMgr);
307  SafeDelete(fPriorityMgr);
308  SafeDelete(fProofSched);
309  SafeDelete(fROOTMgr);
310  SafeDelete(fSessionMgr);
311  SafeDelete(fXrootdPlugin);
312 }
313 
314 ////////////////////////////////////////////////////////////////////////////////
315 /// Load the Xrootd protocol, if required
316 
317 XrdProtocol *XrdProofdManager::LoadXrootd(char *parms, XrdProtocol_Config *pi, XrdSysError *edest)
318 {
319  XPDLOC(ALL, "Manager::LoadXrootd")
320 
321  XrdProtocol *xrp = 0;
322 
323  // Create the plug-in instance
324  fXrootdPlugin = new XrdSysPlugin((edest ? edest : (XrdSysError *)0), fXrootdLibPath.c_str());
325  if (!fXrootdPlugin) {
326  TRACE(XERR, "could not create plugin instance for "<<fXrootdLibPath.c_str());
327  return xrp;
328  }
329 
330  // Get the function
331  XrdProtocolLoader_t ep = (XrdProtocolLoader_t) fXrootdPlugin->getPlugin("XrdgetProtocol");
332  if (!ep) {
333  TRACE(XERR, "could not find 'XrdgetProtocol()' in "<<fXrootdLibPath.c_str());
334  return xrp;
335  }
336 
337  // Get the server object
338  if (!(xrp = (*ep)("xrootd", parms, pi))) {
339  TRACE(XERR, "Unable to create xrootd protocol service object via " << fXrootdLibPath.c_str());
340  SafeDelete(fXrootdPlugin);
341  } else {
342  // Notify
343  TRACE(ALL, "xrootd protocol service created");
344  }
345 
346  return xrp;
347 }
348 
349 ////////////////////////////////////////////////////////////////////////////////
350 /// Make sure that the log file belongs to the original effective user
351 
352 void XrdProofdManager::CheckLogFileOwnership()
353 {
354  XPDLOC(ALL, "Manager::CheckLogFileOwnership")
355 
356  // Nothing to do if not priviledged
357  if (getuid()) return;
358 
359  struct stat st;
360  if (fstat(STDERR_FILENO, &st) != 0) {
361  if (errno != ENOENT) {
362  TRACE(XERR, "could not stat log file; errno: " << errno);
363  return;
364  }
365  }
366 
367  TRACE(HDBG, "uid: " << st.st_uid << ", gid: " << st.st_gid);
368 
369  // Get original effective user identity
370  struct passwd *epwd = getpwuid(XrdProofdProtocol::EUidAtStartup());
371  if (!epwd) {
372  TRACE(XERR, "could not get effective user identity; errno: " << errno);
373  return;
374  }
375 
376  // Set ownership of the log file to the effective user
377  if (st.st_uid != epwd->pw_uid || st.st_gid != epwd->pw_gid) {
378  if (fchown(STDERR_FILENO, epwd->pw_uid, epwd->pw_gid) != 0) {
379  TRACE(XERR, "could not set stderr ownership; errno: " << errno);
380  return;
381  }
382  }
383 }
384 
385 ////////////////////////////////////////////////////////////////////////////////
386 /// Check if master 'm' is allowed to connect to this host
387 
388 bool XrdProofdManager::CheckMaster(const char *m)
389 {
390  bool rc = 1;
391 
392  if (fMastersAllowed.size() > 0) {
393  rc = 0;
394  XrdOucString wm(m);
395  std::list<XrdOucString *>::iterator i;
396  for (i = fMastersAllowed.begin(); i != fMastersAllowed.end(); ++i) {
397  if (wm.matches((*i)->c_str())) {
398  rc = 1;
399  break;
400  }
401  }
402  }
403 
404  // We are done
405  return rc;
406 }
407 
408 ////////////////////////////////////////////////////////////////////////////////
409 /// Check if the user is allowed to use the system
410 /// Return 0 if OK, -1 if not.
411 
412 int XrdProofdManager::CheckUser(const char *usr, const char *grp,
413  XrdProofUI &ui, XrdOucString &e, bool &su)
414 {
415  su = 0;
416  // User must be defined
417  if (!usr || strlen(usr) <= 0) {
418  e = "CheckUser: 'usr' string is undefined ";
419  return -1;
420  }
421 
422  // No 'root' logins
423  if (strlen(usr) == 4 && !strcmp(usr, "root")) {
424  e = "CheckUser: 'root' logins not accepted ";
425  return -1;
426  }
427 
428  // Group must be defined
429  if (!grp || strlen(grp) <= 0) {
430  e = "CheckUser: 'grp' string is undefined ";
431  return -1;
432  }
433 
434  XrdSysMutexHelper mtxh(&fMutex);
435 
436  // Here we check if the user is known locally.
437  // If not, we fail for now.
438  // In the future we may try to get a temporary account
439  if (fChangeOwn) {
440  if (XrdProofdAux::GetUserInfo(usr, ui) != 0) {
441  e = "CheckUser: unknown ClientID: ";
442  e += usr;
443  return -1;
444  }
445  } else {
446  // We assign the ui of the effective user
447  if (XrdProofdAux::GetUserInfo(geteuid(), ui) != 0) {
448  e = "CheckUser: problems getting user info for id: ";
449  e += (int)geteuid();
450  return -1;
451  }
452  }
453 
454  // Check if super user
455  if (fSuperUsers.length() > 0) {
456  XrdOucString tkn;
457  int from = 0;
458  while ((from = fSuperUsers.tokenize(tkn, from, ',')) != -1) {
459  if (tkn == usr) {
460  su = 1;
461  break;
462  }
463  }
464  }
465 
466  // If we are in controlled mode we have to check if the user (and possibly
467  // its group) are in the authorized lists; otherwise we fail.
468  // Privileged users are always allowed to connect.
469  if (fOperationMode == kXPD_OpModeControlled) {
470 
471  // Policy: check first the general directive for groups; a user of a specific group
472  // (both UNIX or PROOF groups) can be rejected by prefixing a '-'.
473  // The group check fails if active (the allowedgroups directive has entries) and at
474  // least of the two groups (UNIX or PROOF) are explicitly denied.
475  // The result of the group check is superseeded by any explicit speicification in the
476  // allowedusers, either positive or negative.
477  // UNIX group includes secondary groups; this allows to enable/disable only members of a
478  // specific subgroup
479  //
480  // Examples:
481  // Consider user 'katy' with UNIX group 'alfa' and PROOF group 'student',
482  // users 'jack' and 'john' with UNIX group 'alfa' and PROOF group 'postdoc'.
483  //
484  // 1. xpd.allowedgroups alfa
485  // Users 'katy', 'jack' and 'john' are allowed because part of UNIX group 'alfa' (no 'allowedusers' directive)
486  // 2. xpd.allowedgroups student
487  // User 'katy' is allowed because part of PROOF group 'student';
488  // users 'jack' and 'john' are denied because not part of PROOF group 'student' (no 'allowedusers' directive)
489  // 3. xpd.allowedgroups alfa,-student
490  // User 'katy' is denied because part of PROOF group 'student' which is explicitly denied;
491  // users 'jack' and 'john' are allowed becasue part of UNIX group 'alfa' (no 'allowedusers' directive)
492  // 4. xpd.allowedgroups alfa,-student
493  // xpd.allowedusers katy,-jack
494  // User 'katy' is allowed because explicitly allowed by the 'allowedusers' directive;
495  // user 'jack' is denied because explicitly denied by the 'allowedusers' directive;
496  // user 'john' is allowed because part of 'alfa' and not explicitly denied by the 'allowedusers' directive
497  // (the allowedgroups directive is in this case ignored for users 'katy' and 'jack').
498 
499  bool grpok = 1;
500  // Check unix groups (secondaries included)
501  if (fAllowedGroups.Num() > 0) {
502  // Reset the flag
503  grpok = 0;
504  int ugrpok = 0, pgrpok = 0;
505  // Check UNIX groups info
506  int ngrps = 10, neg, ig = 0;
507 #if defined(__APPLE__)
508  int grps[10];
509 #else
510  gid_t grps[10];
511 #endif
512  XrdOucString g;
513  if ((neg = getgrouplist(usr, ui.fGid, grps, &ngrps)) < 0) neg = 10;
514  if (neg > 0) {
515  for (ig = 0; ig < neg; ig++) {
516  g.form("%d", (int) grps[ig]);
517  int *st = fAllowedGroups.Find(g.c_str());
518  if (st) {
519  if (*st == 1) {
520  ugrpok = 1;
521  } else {
522  e = "Controlled access (UNIX group): user '";
523  e += usr;
524  e = "', UNIX group '";
525  e += g;
526  e += "' denied to connect";
527  ugrpok = -1;
528  break;
529  }
530  }
531  }
532  }
533  // Check PROOF group info
534  int *st = fAllowedGroups.Find(grp);
535  if (st) {
536  if (*st == 1) {
537  pgrpok = 1;
538  } else {
539  if (e.length() <= 0)
540  e = "Controlled access";
541  e += " (PROOF group): user '";
542  e += usr;
543  e += "', PROOF group '";
544  e += grp;
545  e += "' denied to connect";
546  pgrpok = -1;
547  }
548  }
549  // At least one must be explicitly allowed with the other not explicitly denied
550  grpok = ((ugrpok == 1 && pgrpok >= 0) || (ugrpok >= 0 && pgrpok == 1)) ? 1 : 0;
551  }
552  // Check username
553  int usrok = 0;
554  if (fAllowedUsers.Num() > 0) {
555  // If we do not have a group specification we need to explicitly allow the user
556  if (fAllowedGroups.Num() <= 0) usrok = -1;
557  // Look into the hash
558  int *st = fAllowedUsers.Find(usr);
559  if (st) {
560  if (*st == 1) {
561  usrok = 1;
562  } else {
563  e = "Controlled access: user '";
564  e += usr;
565  e += "', PROOF group '";
566  e += grp;
567  e += "' not allowed to connect";
568  usrok = -1;
569  }
570  }
571  }
572  // Super users are always allowed
573  if (su) {
574  usrok = 1;
575  e = "";
576  }
577  // We fail if either the user is explicitly denied or it is not explicitly allowed
578  // and the group is denied
579  if (usrok == -1 || (!grpok && usrok != 1)) return -1;
580  }
581 
582  // OK
583  return 0;
584 }
585 
586 ////////////////////////////////////////////////////////////////////////////////
587 /// Load PROOF scheduler
588 
589 XrdProofSched *XrdProofdManager::LoadScheduler()
590 {
591  XPDLOC(ALL, "Manager::LoadScheduler")
592 
593  XrdProofSched *sched = 0;
594  XrdOucString name, lib, m;
595 
596  const char *cfn = CfgFile();
597 
598  // Locate first the relevant directives in the config file
599  if (cfn && strlen(cfn) > 0) {
600  XrdOucEnv myEnv;
601  XrdOucStream cfg(fEDest, getenv("XRDINSTANCE"), &myEnv);
602  // Open and attach the config file
603  int cfgFD;
604  if ((cfgFD = open(cfn, O_RDONLY, 0)) >= 0) {
605  cfg.Attach(cfgFD);
606  // Process items
607  char *val = 0, *var = 0;
608  while ((var = cfg.GetMyFirstWord())) {
609  if (!(strcmp("xpd.sched", var))) {
610  // Get the name
611  val = cfg.GetWord();
612  if (val && val[0]) {
613  name = val;
614  // Get the lib
615  val = cfg.GetWord();
616  if (val && val[0])
617  lib = val;
618  // We are done
619  break;
620  }
621  }
622  }
623  close(cfgFD);
624  } else {
625  XPDFORM(m, "failure opening config file; errno: %d", errno);
626  TRACE(XERR, m);
627  }
628  }
629 
630  // If undefined or default init a default instance
631  if (name == "default" || !(name.length() > 0 && lib.length() > 0)) {
632  if ((name.length() <= 0 && lib.length() > 0) ||
633  (name.length() > 0 && lib.length() <= 0)) {
634  XPDFORM(m, "missing or incomplete info (name: %s, lib: %s)", name.c_str(), lib.c_str());
635  TRACE(DBG, m);
636  }
637  TRACE(DBG, "instantiating default scheduler");
638  sched = new XrdProofSched("default", this, fGroupsMgr, cfn, fEDest);
639  } else {
640  // Load the required plugin
641  if (lib.beginswith("~") || lib.beginswith("$"))
642  XrdProofdAux::Expand(lib);
643  XrdSysPlugin *h = new XrdSysPlugin(fEDest, lib.c_str());
644  if (!h)
645  return (XrdProofSched *)0;
646  // Get the scheduler object creator
647  XrdProofSchedLoader_t ep = (XrdProofSchedLoader_t) h->getPlugin("XrdgetProofSched", 1);
648  if (!ep) {
649  delete h;
650  return (XrdProofSched *)0;
651  }
652  // Get the scheduler object
653  if (!(sched = (*ep)(cfn, this, fGroupsMgr, cfn, fEDest))) {
654  TRACE(XERR, "unable to create scheduler object from " << lib);
655  delete h;
656  return (XrdProofSched *)0;
657  }
658  delete h;
659  }
660  // Check result
661  if (!(sched->IsValid())) {
662  TRACE(XERR, " unable to instantiate the " << sched->Name() << " scheduler using " << (cfn ? cfn : "<nul>"));
663  delete sched;
664  return (XrdProofSched *)0;
665  }
666  // Notify
667  TRACE(ALL, "scheduler loaded: type: " << sched->Name());
668 
669  // All done
670  return sched;
671 }
672 
673 ////////////////////////////////////////////////////////////////////////////////
674 /// Get a list of workers from the available resource broker
675 
676 int XrdProofdManager::GetWorkers(XrdOucString &lw, XrdProofdProofServ *xps,
677  const char *query)
678 {
679  XPDLOC(ALL, "Manager::GetWorkers")
680 
681  int rc = 0;
682  TRACE(REQ, "enter");
683 
684  // We need the scheduler at this point
685  if (!fProofSched) {
686  TRACE(XERR, "scheduler undefined");
687  return -1;
688  }
689 
690  // Query the scheduler for the list of workers
691  std::list<XrdProofWorker *> wrks, uwrks;
692  if ((rc = fProofSched->GetWorkers(xps, &wrks, query)) < 0) {
693  TRACE(XERR, "error getting list of workers from the scheduler");
694  return -1;
695  }
696  std::list<XrdProofWorker *>::iterator iw, iaw;
697  // If we got a new list we save it into the session object
698  if (rc == 0) {
699 
700  TRACE(DBG, "list size: " << wrks.size());
701 
702  XrdOucString ord;
703  int ii = -1;
704  // If in remote PLite mode, we need to isolate the number of workers
705  // per unique node
706  if (fRemotePLite) {
707  for (iw = wrks.begin(); iw != wrks.end() ; ++iw) {
708  XrdProofWorker *w = *iw;
709  // Do we have it already in the unique list?
710  bool isnew = 1;
711  for (iaw = uwrks.begin(); iaw != uwrks.end() ; ++iaw) {
712  XrdProofWorker *uw = *iaw;
713  if (w->fHost == uw->fHost && w->fPort == uw->fPort) {
714  uw->fNwrks += 1;
715  isnew = 0;
716  break;
717  }
718  }
719  if (isnew) {
720  // Count (fActive is increased inside here)
721  if (ii == -1) {
722  ord = "master";
723  } else {
724  XPDFORM(ord, "%d", ii);
725  }
726  ii++;
727  XrdProofWorker *uw = new XrdProofWorker(*w);
728  uw->fType = 'S';
729  uw->fOrd = ord;
730  uwrks.push_back(uw);
731  // Setup connection with the proofserv using the original
732  xps->AddWorker(ord.c_str(), w);
733  w->AddProofServ(xps);
734  }
735  }
736  for (iw = uwrks.begin(); iw != uwrks.end() ; ++iw) {
737  XrdProofWorker *w = *iw;
738  // Master at the beginning
739  if (w->fType == 'M') {
740  if (lw.length() > 0) lw.insert('&',0);
741  lw.insert(w->Export(), 0);
742  } else {
743  // Add separator if not the first
744  if (lw.length() > 0) lw += '&';
745  // Add export version of the info
746  lw += w->Export(0);
747  }
748  }
749 
750  } else {
751 
752  // The full list
753  for (iw = wrks.begin(); iw != wrks.end() ; ++iw) {
754  XrdProofWorker *w = *iw;
755  // Count (fActive is increased inside here)
756  if (ii == -1)
757  ord = "master";
758  else
759  XPDFORM(ord, "%d", ii);
760  ii++;
761  xps->AddWorker(ord.c_str(), w);
762  // Add proofserv and increase the counter
763  w->AddProofServ(xps);
764  }
765  }
766  }
767 
768  int proto = (xps->ROOT()) ? xps->ROOT()->SrvProtVers() : -1;
769  if (rc != 2 || (proto < 21 && rc == 0)) {
770  // Get the list in exported format
771  if (lw.length() <= 0) xps->ExportWorkers(lw);
772  TRACE(DBG, "from ExportWorkers: " << lw);
773  } else if (proto >= 21) {
774  // Signal enqueing
775  lw = XPD_GW_QueryEnqueued;
776  }
777 
778  if (TRACING(REQ)) fNetMgr->Dump();
779 
780  // Clear the temp list
781  if (!uwrks.empty()) {
782  iw = uwrks.begin();
783  while (iw != uwrks.end()) {
784  XrdProofWorker *w = *iw;
785  iw = uwrks.erase(iw);
786  delete w;
787  }
788  }
789 
790  return rc;
791 }
792 
793 ////////////////////////////////////////////////////////////////////////////////
794 /// Add the key value in the string passed via the void argument
795 
796 static int FillKeyValues(const char *k, int *d, void *s)
797 {
798  xpd_acm_lists_t *ls = (xpd_acm_lists_t *)s;
799 
800  if (ls) {
801  XrdOucString &ss = (*d == 1) ? ls->allowed : ls->denied;
802  // Add the key
803  if (k) {
804  XrdOucString sk;
805  sk += k;
806  if (!sk.isdigit()) {
807  // If not empty add a separation ','
808  if (ss.length() > 0) ss += ",";
809  ss += sk;
810  }
811  }
812  } else {
813  // Not enough info: stop
814  return 1;
815  }
816 
817  // Check next
818  return 0;
819 }
820 
821 ////////////////////////////////////////////////////////////////////////////////
822 /// Add the key value in the string passed via the void argument
823 
824 static int RemoveInvalidUsers(const char *k, int *, void *s)
825 {
826  XrdOucString *ls = (XrdOucString *)s;
827 
828  XrdProofUI ui;
829  if (XrdProofdAux::GetUserInfo(k, ui) != 0) {
830  // Username is unknown to the system: remove it to the list
831  if (ls) {
832  // If not empty add a separation ','
833  if (ls->length() > 0) *ls += ",";
834  // Add the key
835  if (k) *ls += k;
836  }
837  // Negative return removes from the table
838  return -1;
839  }
840 
841  // Check next
842  return 0;
843 }
844 
845 ////////////////////////////////////////////////////////////////////////////////
846 /// Run configuration and parse the entered config directives.
847 /// Return 0 on success, -1 on error
848 
849 int XrdProofdManager::Config(bool rcf)
850 {
851  XPDLOC(ALL, "Manager::Config")
852 
853  XrdSysMutexHelper mtxh(fMutex);
854 
855  // Run first the configurator
856  if (XrdProofdConfig::Config(rcf) != 0) {
857  XPDERR("problems parsing file ");
858  return -1;
859  }
860 
861  XrdOucString msg;
862  msg = (rcf) ? "re-configuring" : "configuring";
863  TRACE(ALL, msg);
864 
865  // Change/DonotChange ownership when logging clients
866  fChangeOwn = (fMultiUser && getuid()) ? 0 : 1;
867 
868  // Notify port
869  XPDFORM(msg, "listening on port %d", fPort);
870  TRACE(ALL, msg);
871 
872  XrdProofUI ui;
873  uid_t effuid = XrdProofdProtocol::EUidAtStartup();
874  if (!rcf) {
875  // Save Effective user
876  if (XrdProofdAux::GetUserInfo(effuid, ui) == 0) {
877  fEffectiveUser = ui.fUser;
878  } else {
879  XPDFORM(msg, "could not resolve effective uid %d (errno: %d)", effuid, errno);
880  XPDERR(msg);
881  return -1;
882  }
883 
884  // Local FQDN
885  char *host = XrdSysDNS::getHostName();
886  fHost = host ? host : "";
887  SafeFree(host);
888 
889  // Notify temporary directory
890  TRACE(ALL, "using temp dir: " << fTMPdir);
891 
892  // Notify role
893  const char *roles[] = { "any", "worker", "submaster", "master" };
894  TRACE(ALL, "role set to: " << roles[fSrvType+1]);
895 
896  // Admin path
897  fAdminPath += fPort;
898  if (XrdProofdAux::AssertDir(fAdminPath.c_str(), ui, fChangeOwn) != 0) {
899  XPDERR("unable to assert the admin path: " << fAdminPath);
900  return -1;
901  }
902  TRACE(ALL, "admin path set to: " << fAdminPath);
903 
904  // Path for Unix sockets
905  if (fSockPathDir.length() <= 0) {
906  // Use default under the admin path
907  XPDFORM(fSockPathDir, "%s/socks", fAdminPath.c_str());
908  }
909  if (XrdProofdAux::AssertDir(fSockPathDir.c_str(), ui, fChangeOwn) != 0) {
910  XPDERR("unable to assert the admin path: " << fSockPathDir);
911  return -1;
912  }
913  if (XrdProofdAux::ChangeMod(fSockPathDir.c_str(), 0777) != 0) {
914  XPDERR("unable to set mode 0777 on: " << fSockPathDir);
915  return -1;
916  }
917  TRACE(ALL, "unix sockets under: " << fSockPathDir);
918 
919  // Create / Update the process ID file under the admin path
920  XrdOucString pidfile(fAdminPath);
921  pidfile += "/xrootd.pid";
922  FILE *fpid = fopen(pidfile.c_str(), "w");
923  if (!fpid) {
924  XPDFORM(msg, "unable to open pid file: %s; errno: %d", pidfile.c_str(), errno);
925  XPDERR(msg);
926  return -1;
927  }
928  fprintf(fpid, "%d", getpid());
929  fclose(fpid);
930  } else {
931  if (XrdProofdAux::GetUserInfo(effuid, ui) == 0) {
932  XPDFORM(msg, "could not resolve effective uid %d (errno: %d)", effuid, errno);
933  XPDERR(msg);
934  }
935  }
936 
937  // Work directory, if specified
938  XrdOucString wdir;
939  if (fWorkDir.length() > 0) {
940  // Make sure it exists
941  if (XrdProofdAux::AssertDir(fWorkDir.c_str(), ui, fChangeOwn) != 0) {
942  XPDERR("unable to assert working dir: " << fWorkDir);
943  return -1;
944  }
945  if (fMUWorkDir.length() > 0) {
946  fMUWorkDir.replace("<workdir>", fWorkDir);
947  int iph = fMUWorkDir.find("<");
948  if (iph != STR_NPOS) {
949  wdir.assign(fMUWorkDir, 0, iph - 2);
950  if (XrdProofdAux::AssertDir(wdir.c_str(), ui, fChangeOwn) != 0) {
951  XPDERR("unable to assert working dir: " << wdir);
952  return -1;
953  }
954  wdir = "";
955  }
956  }
957  }
958  wdir = (fMultiUser && fMUWorkDir.length() > 0) ? fMUWorkDir : fWorkDir;
959  if (wdir.length() > 0) {
960  TRACE(ALL, "working directories under: " << wdir);
961  // Communicate it to the sandbox service
962  XrdProofdSandbox::SetWorkdir(wdir.c_str());
963  }
964 
965  // Data directory, if specified
966  if (fDataDir.length() > 0) {
967  if (fDataDir.endswith('/')) fDataDir.erasefromend(1);
968  if (fDataDirOpts.length() > 0) {
969  // Make sure it exists
970  if (XrdProofdAux::AssertDir(fDataDir.c_str(), ui, fChangeOwn) != 0) {
971  XPDERR("unable to assert data dir: " << fDataDir << " (opts: "<<fDataDirOpts<<")");
972  return -1;
973  }
974  // Get the right privileges now
975  XrdSysPrivGuard pGuard((uid_t)ui.fUid, (gid_t)ui.fGid);
976  if (XpdBadPGuard(pGuard, ui.fUid)) {
977  TRACE(XERR, "could not get privileges to set/change ownership of " << fDataDir);
978  return -1;
979  }
980  if (chmod(fDataDir.c_str(), 0777) != 0) {
981  XPDERR("problems setting permissions 0777 data dir: " << fDataDir);
982  return -1;
983  }
984  }
985  TRACE(ALL, "data directories under: " << fDataDir);
986  }
987 
988  // Notify allow rules
989  if (fSrvType == kXPD_Worker) {
990  if (fMastersAllowed.size() > 0) {
991  std::list<XrdOucString *>::iterator i;
992  for (i = fMastersAllowed.begin(); i != fMastersAllowed.end(); ++i)
993  TRACE(ALL, "masters allowed to connect: " << (*i)->c_str());
994  } else {
995  TRACE(ALL, "masters allowed to connect: any");
996  }
997  }
998 
999  // Pool and namespace
1000  if (fPoolURL.length() <= 0) {
1001  // Default pool entry point is this host
1002  fPoolURL = "root://";
1003  fPoolURL += fHost;
1004  }
1005  TRACE(ALL, "PROOF pool: " << fPoolURL);
1006  TRACE(ALL, "PROOF pool namespace: " << fNamespace);
1007 
1008  // Initialize resource broker (if not worker)
1009  if (fSrvType != kXPD_Worker) {
1010 
1011  // Scheduler instance
1012  if (!(fProofSched = LoadScheduler())) {
1013  XPDERR("scheduler initialization failed");
1014  return 0;
1015  }
1016  const char *st[] = { "disabled", "enabled" };
1017  TRACE(ALL, "user config files are " << st[fNetMgr->WorkerUsrCfg()]);
1018  }
1019 
1020  // If using the PLite optimization notify it
1021  if (fRemotePLite)
1022  TRACE(ALL, "multi-process on nodes handled with proof-lite");
1023 
1024  // Validate dataset sources (if not worker)
1025  fDataSetExp = "";
1026  if (fSrvType != kXPD_Worker && fDataSetSrcs.size() > 0) {
1027  // If first local, add it in front
1028  std::list<XrdProofdDSInfo *>::iterator ii = fDataSetSrcs.begin();
1029  bool goodsrc = 0;
1030  for (ii = fDataSetSrcs.begin(); ii != fDataSetSrcs.end();) {
1031  TRACE(ALL, ">> Defined dataset: " << (*ii)->ToString());
1032  if ((*ii)->fType == "file") {
1033  if (!(goodsrc = ValidateLocalDataSetSrc((*ii)->fUrl, (*ii)->fLocal))) {
1034  XPDERR("source " << (*ii)->fUrl << " could not be validated");
1035  ii = fDataSetSrcs.erase(ii);
1036  } else {
1037  // Check next
1038  ++ii;
1039  }
1040  } else {
1041  // Validate only "file" datasets
1042  TRACE(ALL, "Skipping validation (no \"file\" type dataset source)");
1043  ++ii;
1044  }
1045  }
1046  if (fDataSetSrcs.size() > 0) {
1047  TRACE(ALL, fDataSetSrcs.size() << " dataset sources defined");
1048  for (ii = fDataSetSrcs.begin(); ii != fDataSetSrcs.end(); ++ii) {
1049  TRACE(ALL, ">> Valid dataset: " << (*ii)->ToString());
1050  if ((*ii)->fLocal && (*ii)->fRW) {
1051  if (fDataSetExp.length() > 0) fDataSetExp += ",";
1052  fDataSetExp += ((*ii)->fUrl).c_str();
1053  }
1054  }
1055  } else {
1056  TRACE(ALL, "no dataset sources defined");
1057  }
1058  } else {
1059  TRACE(ALL, "no dataset sources defined");
1060  }
1061 
1062  // Superusers: add the effective user at startup
1063  XrdProofUI sui;
1064  if (XrdProofdAux::GetUserInfo(XrdProofdProtocol::EUidAtStartup(), sui) == 0) {
1065  if (fSuperUsers.find(sui.fUser.c_str()) == STR_NPOS) {
1066  if (fSuperUsers.length() > 0) fSuperUsers += ",";
1067  fSuperUsers += sui.fUser;
1068  }
1069  } else {
1070  XPDFORM(msg, "could not resolve effective uid %d (errno: %d)",
1071  XrdProofdProtocol::EUidAtStartup(), errno);
1072  XPDERR(msg);
1073  }
1074  XPDFORM(msg, "list of superusers: %s", fSuperUsers.c_str());
1075  TRACE(ALL, msg);
1076 
1077  // Notify controlled mode, if such
1078  if (fOperationMode == kXPD_OpModeControlled) {
1079  // Add superusers to the hash list of allowed users
1080  int from = 0;
1081  XrdOucString usr;
1082  while ((from = fSuperUsers.tokenize(usr, from, ',')) != STR_NPOS) {
1083  fAllowedUsers.Add(usr.c_str(), new int(1));
1084  }
1085  // If not in multiuser mode make sure that the users in the allowed list
1086  // are known to the system
1087  if (!fMultiUser) {
1088  XrdOucString ius;
1089  fAllowedUsers.Apply(RemoveInvalidUsers, (void *)&ius);
1090  if (ius.length()) {
1091  XPDFORM(msg, "running in controlled access mode: users removed because"
1092  " unknown to the system: %s", ius.c_str());
1093  TRACE(ALL, msg);
1094  }
1095  }
1096  // Extract now the list of allowed users
1097  xpd_acm_lists_t uls;
1098  fAllowedUsers.Apply(FillKeyValues, (void *)&uls);
1099  if (uls.allowed.length()) {
1100  XPDFORM(msg, "running in controlled access mode: users allowed: %s", uls.allowed.c_str());
1101  TRACE(ALL, msg);
1102  }
1103  if (uls.denied.length()) {
1104  XPDFORM(msg, "running in controlled access mode: users denied: %s", uls.denied.c_str());
1105  TRACE(ALL, msg);
1106  }
1107  // Extract now the list of allowed groups
1108  xpd_acm_lists_t gls;
1109  fAllowedGroups.Apply(FillKeyValues, (void *)&gls);
1110  if (gls.allowed.length()) {
1111  XPDFORM(msg, "running in controlled access mode: UNIX groups allowed: %s", gls.allowed.c_str());
1112  TRACE(ALL, msg);
1113  }
1114  if (gls.denied.length()) {
1115  XPDFORM(msg, "running in controlled access mode: UNIX groups denied: %s", gls.denied.c_str());
1116  TRACE(ALL, msg);
1117  }
1118  }
1119 
1120  // Bare lib path
1121  if (getenv(XPD_LIBPATH)) {
1122  XrdOucString ctrim;
1123  if (fRemoveROOTLibPaths || fLibPathsToRemove.Num() > 0) {
1124  // Try to remove existing ROOT dirs in the path
1125  XrdOucString paths = getenv(XPD_LIBPATH);
1126  XrdOucString ldir;
1127  int from = 0;
1128  while ((from = paths.tokenize(ldir, from, ':')) != STR_NPOS) {
1129  bool remove = 0;
1130  if (ldir.length() > 0) {
1131  if (fLibPathsToRemove.Num() > 0 && fLibPathsToRemove.Find(ldir.c_str())) {
1132  remove = 1;
1133  } else if (fRemoveROOTLibPaths) {
1134  // Check this dir
1135  DIR *dir = opendir(ldir.c_str());
1136  if (dir) {
1137  // Scan the directory
1138  struct dirent *ent = 0;
1139  while ((ent = (struct dirent *)readdir(dir))) {
1140  if (!strncmp(ent->d_name, "libCore", 7)) {
1141  remove = 1;
1142  break;
1143  }
1144  }
1145  // Close the directory
1146  closedir(dir);
1147  }
1148  }
1149  }
1150  if (!remove) {
1151  if (fBareLibPath.length() > 0)
1152  fBareLibPath += ":";
1153  fBareLibPath += ldir;
1154  }
1155  }
1156  ctrim = " (lib paths filter applied)";
1157  } else {
1158  // Full path
1159  ctrim = " (full ";
1160  ctrim += XPD_LIBPATH;
1161  ctrim += ")";
1162  fBareLibPath = getenv(XPD_LIBPATH);
1163  }
1164  TRACE(ALL, "bare lib path for proofserv" << ctrim <<": " << fBareLibPath);
1165  }
1166 
1167  // Groups
1168  if (!fGroupsMgr)
1169  // Create default group, if none explicitly requested
1170  fGroupsMgr = new XrdProofGroupMgr;
1171 
1172  if (fGroupsMgr)
1173  fGroupsMgr->Print(0);
1174 
1175  // Config the admin handler
1176  if (fAdmin && fAdmin->Config(rcf) != 0) {
1177  XPDERR("problems configuring the admin handler");
1178  return -1;
1179  }
1180 
1181  // Config the network manager
1182  if (fNetMgr && fNetMgr->Config(rcf) != 0) {
1183  XPDERR("problems configuring the network manager");
1184  return -1;
1185  }
1186 
1187  // Config the priority manager
1188  if (fPriorityMgr && fPriorityMgr->Config(rcf) != 0) {
1189  XPDERR("problems configuring the priority manager");
1190  return -1;
1191  }
1192 
1193  // Config the ROOT versions manager
1194  if (fROOTMgr) {
1195  fROOTMgr->SetLogDir(fAdminPath.c_str());
1196  if (fROOTMgr && fROOTMgr->Config(rcf) != 0) {
1197  XPDERR("problems configuring the ROOT versions manager");
1198  return -1;
1199  }
1200  }
1201 
1202  // Config the client manager
1203  if (fClientMgr && fClientMgr->Config(rcf) != 0) {
1204  XPDERR("problems configuring the client manager");
1205  return -1;
1206  }
1207 
1208  // Config the session manager
1209  if (fSessionMgr && fSessionMgr->Config(rcf) != 0) {
1210  XPDERR("problems configuring the session manager");
1211  return -1;
1212  }
1213 
1214  // Config the scheduler
1215  if (fProofSched && fProofSched->Config(rcf) != 0) {
1216  XPDERR("problems configuring the scheduler");
1217  return -1;
1218  }
1219 
1220  // Xrootd protocol service
1221  if (!(fXrootd = LoadXrootd(fParms, fPi, fEDest))) {
1222  TRACE(ALL, "file serving (protocol: 'root://') not available");
1223  }
1224 
1225  if (!rcf) {
1226  // Start cron thread
1227  pthread_t tid;
1228  if (XrdSysThread::Run(&tid, XrdProofdManagerCron,
1229  (void *)this, 0, "ProofdManager cron thread") != 0) {
1230  XPDERR("could not start cron thread");
1231  return 0;
1232  }
1233  TRACE(ALL, "manager cron thread started");
1234  }
1235 
1236  // Done
1237  return 0;
1238 }
1239 
1240 ////////////////////////////////////////////////////////////////////////////////
1241 /// Validate local dataset src at URL (check the URL and make the relevant
1242 /// directories).
1243 /// Return 1 if OK, 0 if any problem arises
1244 
1245 bool XrdProofdManager::ValidateLocalDataSetSrc(XrdOucString &url, bool &local)
1246 {
1247  XPDLOC(ALL, "Manager::ValidateLocalDataSetSrc")
1248 
1249  TRACE(ALL, "validating '" << url << "' ...");
1250  local = 0;
1251  bool goodsrc = 1;
1252  if (url.length() > 0) {
1253  // Check if local source
1254  if (url.beginswith("file:")) url.replace("file:", "");
1255  if (url.beginswith("/")) {
1256  local = 1;
1257  goodsrc = 0;
1258  // Make sure the directory exists and has mode 0755
1259  XrdProofUI ui;
1260  XrdProofdAux::GetUserInfo(XrdProofdProtocol::EUidAtStartup(), ui);
1261  if (XrdProofdAux::AssertDir(url.c_str(), ui, ChangeOwn()) == 0) {
1262  goodsrc = 1;
1263  if (XrdProofdAux::ChangeMod(url.c_str(), 0777) != 0) {
1264  TRACE(XERR, "Problems setting permissions 0777 on path '" << url << "'");
1265  }
1266  } else {
1267  TRACE(XERR, "Cannot assert path '" << url << "' - ignoring");
1268  }
1269  if (goodsrc) {
1270  // Assert the file with dataset summaries
1271  XrdOucString fnpath(url.c_str());
1272  fnpath += "/dataset.list";
1273  if (access(fnpath.c_str(), F_OK) != 0) {
1274  FILE *flst = fopen(fnpath.c_str(), "w");
1275  if (!flst) {
1276  TRACE(XERR, "Cannot open file '" << fnpath << "' for the dataset list; errno: " << errno);
1277  goodsrc = 0;
1278  } else {
1279  if (fclose(flst) != 0)
1280  TRACE(XERR, "Problems closing file '" << fnpath << "'; errno: " << errno);
1281  if (XrdProofdAux::ChangeOwn(fnpath.c_str(), ui) != 0) {
1282  TRACE(XERR, "Problems asserting ownership of " << fnpath);
1283  }
1284  }
1285  }
1286  // Make sure that everybody can modify the file for updates
1287  if (goodsrc && XrdProofdAux::ChangeMod(fnpath.c_str(), 0666) != 0) {
1288  TRACE(XERR, "Problems setting permissions to 0666 on file '" << fnpath << "'; errno: " << errno);
1289  goodsrc = 0;
1290  }
1291  // Assert the file with lock file path
1292  if (goodsrc) {
1293  fnpath.replace("/dataset.list", "/lock.location");
1294  FILE *flck = fopen(fnpath.c_str(), "a");
1295  if (!flck) {
1296  TRACE(XERR, "Cannot open file '" << fnpath << "' with the lock file path; errno: " << errno);
1297  } else {
1298  errno = 0;
1299  off_t ofs = lseek(fileno(flck), 0, SEEK_CUR);
1300  if (ofs == 0) {
1301  // New file: write the default lock file path
1302  XrdOucString fnlock(url);
1303  fnlock.replace("/", "%");
1304  fnlock.replace(":", "%");
1305  fnlock.insert("/tmp/", 0);
1306  fprintf(flck, "%s\n", fnlock.c_str());
1307  if (fclose(flck) != 0)
1308  TRACE(XERR, "Problems closing file '" << fnpath << "'; errno: " << errno);
1309  flck = 0;
1310  if (XrdProofdAux::ChangeOwn(fnpath.c_str(), ui) != 0) {
1311  TRACE(XERR, "Problems asserting ownership of " << fnpath);
1312  }
1313  } else if (ofs == (off_t)(-1)) {
1314  TRACE(XERR, "Problems getting current position on file '" << fnpath << "'; errno: " << errno);
1315  }
1316  if (flck && fclose(flck) != 0)
1317  TRACE(XERR, "Problems closing file '" << fnpath << "'; errno: " << errno);
1318  }
1319  }
1320  // Make sure that everybody can modify the file for updates
1321  if (goodsrc && XrdProofdAux::ChangeMod(fnpath.c_str(), 0644) != 0) {
1322  TRACE(XERR, "Problems setting permissions to 0644 on file '" << fnpath << "'; errno: " << errno);
1323  }
1324  }
1325  }
1326  }
1327  else {
1328  TRACE(ALL, "New dataset with no URL!");
1329  }
1330  // Done
1331  return goodsrc;
1332 }
1333 
1334 ////////////////////////////////////////////////////////////////////////////////
1335 /// Register directives for configuration
1336 
1337 void XrdProofdManager::RegisterDirectives()
1338 {
1339  // Register special config directives
1340  Register("trace", new XrdProofdDirective("trace", this, &DoDirectiveClass));
1341  Register("groupfile", new XrdProofdDirective("groupfile", this, &DoDirectiveClass));
1342  Register("multiuser", new XrdProofdDirective("multiuser", this, &DoDirectiveClass));
1343  Register("maxoldlogs", new XrdProofdDirective("maxoldlogs", this, &DoDirectiveClass));
1344  Register("allow", new XrdProofdDirective("allow", this, &DoDirectiveClass));
1345  Register("allowedgroups", new XrdProofdDirective("allowedgroups", this, &DoDirectiveClass));
1346  Register("allowedusers", new XrdProofdDirective("allowedusers", this, &DoDirectiveClass));
1347  Register("role", new XrdProofdDirective("role", this, &DoDirectiveClass));
1348  Register("cron", new XrdProofdDirective("cron", this, &DoDirectiveClass));
1349  Register("port", new XrdProofdDirective("port", this, &DoDirectiveClass));
1350  Register("datadir", new XrdProofdDirective("datadir", this, &DoDirectiveClass));
1351  Register("datasetsrc", new XrdProofdDirective("datasetsrc", this, &DoDirectiveClass));
1352  Register("xrd.protocol", new XrdProofdDirective("xrd.protocol", this, &DoDirectiveClass));
1353  Register("filterlibpaths", new XrdProofdDirective("filterlibpaths", this, &DoDirectiveClass));
1354  Register("xrootd", new XrdProofdDirective("xrootd", this, &DoDirectiveClass));
1355  // Register config directives for strings
1356  Register("tmp", new XrdProofdDirective("tmp", (void *)&fTMPdir, &DoDirectiveString));
1357  Register("poolurl", new XrdProofdDirective("poolurl", (void *)&fPoolURL, &DoDirectiveString));
1358  Register("namespace", new XrdProofdDirective("namespace", (void *)&fNamespace, &DoDirectiveString));
1359  Register("superusers", new XrdProofdDirective("superusers", (void *)&fSuperUsers, &DoDirectiveString));
1360  Register("image", new XrdProofdDirective("image", (void *)&fImage, &DoDirectiveString));
1361  Register("workdir", new XrdProofdDirective("workdir", (void *)&fWorkDir, &DoDirectiveString));
1362  Register("sockpathdir", new XrdProofdDirective("sockpathdir", (void *)&fSockPathDir, &DoDirectiveString));
1363  Register("remoteplite", new XrdProofdDirective("remoteplite", (void *)&fRemotePLite, &DoDirectiveInt));
1364  Register("stagereqrepo", new XrdProofdDirective("stagereqrepo", (void *)&fStageReqRepo, &DoDirectiveString));
1365 }
1366 
1367 ////////////////////////////////////////////////////////////////////////////////
1368 /// Resolve special keywords in 's' for client 'pcl'. Recognized keywords
1369 /// <workdir> root for working dirs
1370 /// <host> local host name
1371 /// <port> daemon port
1372 /// <homedir> user home dir
1373 /// <user> user name
1374 /// <group> user group
1375 /// <uid> user ID
1376 /// <gid> user group ID
1377 /// <effuser> effective user name (for multiuser or user mapping modes)
1378 /// Return the number of keywords resolved.
1379 
1380 int XrdProofdManager::ResolveKeywords(XrdOucString &s, XrdProofdClient *pcl)
1381 {
1382  XPDLOC(ALL, "Manager::ResolveKeywords")
1383 
1384  int nk = 0;
1385 
1386  TRACE(HDBG, "enter: " << s << " - WorkDir(): " << WorkDir());
1387 
1388  // Parse <workdir>
1389  if (s.replace("<workdir>", WorkDir()))
1390  nk++;
1391 
1392  TRACE(HDBG, "after <workdir>: " << s);
1393 
1394  // Parse <host>
1395  if (s.replace("<host>", Host()))
1396  nk++;
1397 
1398  TRACE(HDBG, "after <host>: " << s);
1399 
1400  // Parse <port>
1401  if (s.find("<port>") != STR_NPOS) {
1402  XrdOucString sport;
1403  sport += Port();
1404  if (s.replace("<port>", sport.c_str()))
1405  nk++;
1406  }
1407 
1408  // Parse <effuser> of the process
1409  if (s.find("<effuser>") != STR_NPOS) {
1410  XrdProofUI eui;
1411  if (XrdProofdAux::GetUserInfo(geteuid(), eui) == 0) {
1412  if (s.replace("<effuser>", eui.fUser.c_str()))
1413  nk++;
1414  }
1415  }
1416 
1417  // Parse <user>
1418  if (pcl)
1419  if (s.replace("<user>", pcl->User()))
1420  nk++;
1421 
1422  // Parse <group>
1423  if (pcl)
1424  if (s.replace("<group>", pcl->Group()))
1425  nk++;
1426 
1427  // Parse <homedir>
1428  if (pcl)
1429  if (s.replace("<homedir>", pcl->UI().fHomeDir.c_str()))
1430  nk++;
1431 
1432  // Parse <uid>
1433  if (pcl && (s.find("<uid>") != STR_NPOS)) {
1434  XrdOucString suid;
1435  suid += pcl->UI().fUid;
1436  if (s.replace("<uid>", suid.c_str()))
1437  nk++;
1438  }
1439 
1440  // Parse <gid>
1441  if (pcl && (s.find("<gid>") != STR_NPOS)) {
1442  XrdOucString sgid;
1443  sgid += pcl->UI().fGid;
1444  if (s.replace("<gid>", sgid.c_str()))
1445  nk++;
1446  }
1447 
1448  TRACE(HDBG, "exit: " << s);
1449 
1450  // We are done
1451  return nk;
1452 }
1453 
1454 //
1455 // Special directive processors
1456 
1457 ////////////////////////////////////////////////////////////////////////////////
1458 /// Update the priorities of the active sessions.
1459 
1460 int XrdProofdManager::DoDirective(XrdProofdDirective *d,
1461  char *val, XrdOucStream *cfg, bool rcf)
1462 {
1463  XPDLOC(ALL, "Manager::DoDirective")
1464 
1465  if (!d)
1466  // undefined inputs
1467  return -1;
1468 
1469  if (d->fName == "trace") {
1470  return DoDirectiveTrace(val, cfg, rcf);
1471  } else if (d->fName == "groupfile") {
1472  return DoDirectiveGroupfile(val, cfg, rcf);
1473  } else if (d->fName == "maxoldlogs") {
1474  return DoDirectiveMaxOldLogs(val, cfg, rcf);
1475  } else if (d->fName == "allow") {
1476  return DoDirectiveAllow(val, cfg, rcf);
1477  } else if (d->fName == "allowedgroups") {
1478  return DoDirectiveAllowedGroups(val, cfg, rcf);
1479  } else if (d->fName == "allowedusers") {
1480  return DoDirectiveAllowedUsers(val, cfg, rcf);
1481  } else if (d->fName == "role") {
1482  return DoDirectiveRole(val, cfg, rcf);
1483  } else if (d->fName == "multiuser") {
1484  return DoDirectiveMultiUser(val, cfg, rcf);
1485  } else if (d->fName == "port") {
1486  return DoDirectivePort(val, cfg, rcf);
1487  } else if (d->fName == "datadir") {
1488  return DoDirectiveDataDir(val, cfg, rcf);
1489  } else if (d->fName == "datasetsrc") {
1490  return DoDirectiveDataSetSrc(val, cfg, rcf);
1491  } else if (d->fName == "rootd") {
1492  return DoDirectiveRootd(val, cfg, rcf);
1493  } else if (d->fName == "rootdallow") {
1494  return DoDirectiveRootdAllow(val, cfg, rcf);
1495  } else if (d->fName == "xrd.protocol") {
1496  return DoDirectivePort(val, cfg, rcf);
1497  } else if (d->fName == "filterlibpaths") {
1498  return DoDirectiveFilterLibPaths(val, cfg, rcf);
1499  } else if (d->fName == "xrootd") {
1500  return DoDirectiveXrootd(val, cfg, rcf);
1501  }
1502  TRACE(XERR, "unknown directive: " << d->fName);
1503  return -1;
1504 }
1505 
1506 ////////////////////////////////////////////////////////////////////////////////
1507 /// Scan the config file for tracing settings
1508 
1509 int XrdProofdManager::DoDirectiveTrace(char *val, XrdOucStream *cfg, bool)
1510 {
1511  XPDLOC(ALL, "Manager::DoDirectiveTrace")
1512 
1513  if (!val || !cfg)
1514  // undefined inputs
1515  return -1;
1516 
1517  // Specifies tracing options. This works by levels and domains.
1518  //
1519  // Valid keyword levels are:
1520  // err trace errors [on]
1521  // req trace protocol requests [on]*
1522  // dbg trace details about actions [off]
1523  // hdbg trace more details about actions [off]
1524  // Special forms of 'dbg' (always on if 'dbg' is required) are:
1525  // login trace details about login requests [on]*
1526  // fork trace proofserv forks [on]*
1527  // mem trace mem buffer manager [off]
1528  //
1529  // Valid keyword domains are:
1530  // rsp server replies [off]
1531  // aux aux functions [on]
1532  // cmgr client manager [on]
1533  // smgr session manager [on]
1534  // nmgr network manager [on]
1535  // pmgr priority manager [on]
1536  // gmgr group manager [on]
1537  // sched details about scheduling [on]
1538  //
1539  // Global switches:
1540  // all or dump full tracing of everything
1541  //
1542  // Defaults are shown in brackets; '*' shows the default when the '-d'
1543  // option is passed on the command line. Each option may be
1544  // optionally prefixed by a minus sign to turn off the setting.
1545  // Order matters: 'all' in last position enables everything; in first
1546  // position is corrected by subsequent settings
1547  //
1548  while (val && val[0]) {
1549  bool on = 1;
1550  if (val[0] == '-') {
1551  on = 0;
1552  val++;
1553  }
1554  if (!strcmp(val, "err")) {
1555  TRACESET(XERR, on);
1556  } else if (!strcmp(val, "req")) {
1557  TRACESET(REQ, on);
1558  } else if (!strcmp(val, "dbg")) {
1559  TRACESET(DBG, on);
1560  TRACESET(LOGIN, on);
1561  TRACESET(FORK, on);
1562  TRACESET(MEM, on);
1563  } else if (!strcmp(val, "login")) {
1564  TRACESET(LOGIN, on);
1565  } else if (!strcmp(val, "fork")) {
1566  TRACESET(FORK, on);
1567  } else if (!strcmp(val, "mem")) {
1568  TRACESET(MEM, on);
1569  } else if (!strcmp(val, "hdbg")) {
1570  TRACESET(HDBG, on);
1571  TRACESET(DBG, on);
1572  TRACESET(LOGIN, on);
1573  TRACESET(FORK, on);
1574  TRACESET(MEM, on);
1575  } else if (!strcmp(val, "rsp")) {
1576  TRACESET(RSP, on);
1577  } else if (!strcmp(val, "aux")) {
1578  TRACESET(AUX, on);
1579  } else if (!strcmp(val, "cmgr")) {
1580  TRACESET(CMGR, on);
1581  } else if (!strcmp(val, "smgr")) {
1582  TRACESET(SMGR, on);
1583  } else if (!strcmp(val, "nmgr")) {
1584  TRACESET(NMGR, on);
1585  } else if (!strcmp(val, "pmgr")) {
1586  TRACESET(PMGR, on);
1587  } else if (!strcmp(val, "gmgr")) {
1588  TRACESET(GMGR, on);
1589  } else if (!strcmp(val, "sched")) {
1590  TRACESET(SCHED, on);
1591  } else if (!strcmp(val, "all") || !strcmp(val, "dump")) {
1592  // Everything
1593  TRACE(ALL, "Setting trace: " << on);
1594  XrdProofdTrace->What = (on) ? TRACE_ALL : 0;
1595  }
1596 
1597  // Next
1598  val = cfg->GetWord();
1599  }
1600 
1601  return 0;
1602 }
1603 
1604 ////////////////////////////////////////////////////////////////////////////////
1605 /// Process 'groupfile' directive
1606 
1607 int XrdProofdManager::DoDirectiveGroupfile(char *val, XrdOucStream *cfg, bool rcf)
1608 {
1609  XPDLOC(ALL, "Manager::DoDirectiveGroupfile")
1610 
1611  if (!val)
1612  // undefined inputs
1613  return -1;
1614 
1615  // Check deprecated 'if' directive
1616  if (Host() && cfg)
1617  if (XrdProofdAux::CheckIf(cfg, Host()) == 0)
1618  return 0;
1619 
1620  // Defines file with the group info
1621  if (rcf) {
1622  SafeDelete(fGroupsMgr);
1623  } else if (fGroupsMgr) {
1624  TRACE(XERR, "groups manager already initialized: ignoring ");
1625  return -1;
1626  }
1627  fGroupsMgr = new XrdProofGroupMgr;
1628  fGroupsMgr->Config(val);
1629  return 0;
1630 }
1631 
1632 ////////////////////////////////////////////////////////////////////////////////
1633 /// Process 'maxoldlogs' directive
1634 
1635 int XrdProofdManager::DoDirectiveMaxOldLogs(char *val, XrdOucStream *cfg, bool)
1636 {
1637  if (!val)
1638  // undefined inputs
1639  return -1;
1640 
1641  // Check deprecated 'if' directive
1642  if (Host() && cfg)
1643  if (XrdProofdAux::CheckIf(cfg, Host()) == 0)
1644  return 0;
1645 
1646  // Max number of sessions per user
1647  int maxoldlogs = strtol(val, 0, 10);
1648  XrdProofdSandbox::SetMaxOldSessions(maxoldlogs);
1649  return 0;
1650 }
1651 
1652 ////////////////////////////////////////////////////////////////////////////////
1653 /// Process 'allow' directive
1654 
1655 int XrdProofdManager::DoDirectiveAllow(char *val, XrdOucStream *cfg, bool)
1656 {
1657  if (!val)
1658  // undefined inputs
1659  return -1;
1660 
1661  // Check deprecated 'if' directive
1662  if (Host() && cfg)
1663  if (XrdProofdAux::CheckIf(cfg, Host()) == 0)
1664  return 0;
1665 
1666  // Masters allowed to connect
1667  fMastersAllowed.push_back(new XrdOucString(val));
1668  return 0;
1669 }
1670 
1671 ////////////////////////////////////////////////////////////////////////////////
1672 /// Process 'allowedgroups' directive
1673 
1674 int XrdProofdManager::DoDirectiveAllowedGroups(char *val, XrdOucStream *cfg, bool)
1675 {
1676  if (!val)
1677  // undefined inputs
1678  return -1;
1679 
1680  // Check deprecated 'if' directive
1681  if (Host() && cfg)
1682  if (XrdProofdAux::CheckIf(cfg, Host()) == 0)
1683  return 0;
1684 
1685  // We are in controlled mode
1686  fOperationMode = kXPD_OpModeControlled;
1687 
1688  // Input list (comma separated) of UNIX groups allowed to connect
1689  XrdOucString s = val;
1690  int from = 0;
1691  XrdOucString grp, gid;
1692  XrdProofGI gi;
1693  while ((from = s.tokenize(grp, from, ',')) != STR_NPOS) {
1694  int st = 1;
1695  if (grp.beginswith('-')) {
1696  st = 0;
1697  grp.erasefromstart(1);
1698  }
1699  // Unix or Proof group ?
1700  if (XrdProofdAux::GetGroupInfo(grp.c_str(), gi) == 0) {
1701  // Unix: add name and id
1702  gid.form("%d", (int) gi.fGid);
1703  fAllowedGroups.Add(gid.c_str(), new int(st));
1704  }
1705  // Add it to the list
1706  fAllowedGroups.Add(grp.c_str(), new int(st));
1707  }
1708 
1709  // Done
1710  return 0;
1711 }
1712 
1713 ////////////////////////////////////////////////////////////////////////////////
1714 /// Process 'allowedusers' directive
1715 
1716 int XrdProofdManager::DoDirectiveAllowedUsers(char *val, XrdOucStream *cfg, bool)
1717 {
1718  if (!val)
1719  // undefined inputs
1720  return -1;
1721 
1722  // Check deprecated 'if' directive
1723  if (Host() && cfg)
1724  if (XrdProofdAux::CheckIf(cfg, Host()) == 0)
1725  return 0;
1726 
1727  // We are in controlled mode
1728  fOperationMode = kXPD_OpModeControlled;
1729 
1730  // Input list (comma separated) of users allowed to connect
1731  XrdOucString s = val;
1732  int from = 0;
1733  XrdOucString usr;
1734  XrdProofUI ui;
1735  while ((from = s.tokenize(usr, from, ',')) != STR_NPOS) {
1736  int st = 1;
1737  if (usr.beginswith('-')) {
1738  st = 0;
1739  usr.erasefromstart(1);
1740  }
1741  // Add to the list; we will check later on the existence of the
1742  // user in the password file, depending on the 'multiuser' settings
1743  fAllowedUsers.Add(usr.c_str(), new int(st));
1744  }
1745 
1746  // Done
1747  return 0;
1748 }
1749 
1750 ////////////////////////////////////////////////////////////////////////////////
1751 /// Process 'role' directive
1752 
1753 int XrdProofdManager::DoDirectiveRole(char *val, XrdOucStream *cfg, bool)
1754 {
1755  if (!val)
1756  // undefined inputs
1757  return -1;
1758 
1759  // Check deprecated 'if' directive
1760  if (Host() && cfg)
1761  if (XrdProofdAux::CheckIf(cfg, Host()) == 0)
1762  return 0;
1763 
1764  // Role this server
1765  XrdOucString tval(val);
1766  if (tval == "supermaster") {
1767  fSrvType = kXPD_TopMaster;
1768  fSuperMst = 1;
1769  } else if (tval == "master") {
1770  fSrvType = kXPD_TopMaster;
1771  } else if (tval == "submaster") {
1772  fSrvType = kXPD_Master;
1773  } else if (tval == "worker") {
1774  fSrvType = kXPD_Worker;
1775  } else if (tval == "any") {
1776  fSrvType = kXPD_AnyServer;
1777  }
1778 
1779  return 0;
1780 }
1781 
1782 ////////////////////////////////////////////////////////////////////////////////
1783 /// Process 'xrd.protocol' directive to find the port
1784 
1785 int XrdProofdManager::DoDirectivePort(char *val, XrdOucStream *, bool)
1786 {
1787  if (!val)
1788  // undefined inputs
1789  return -1;
1790 
1791  XrdOucString port(val);
1792  if (port.beginswith("xproofd:")) {
1793  port.replace("xproofd:", "");
1794  }
1795  if (port.length() > 0 && port.isdigit()) {
1796  fPort = strtol(port.c_str(), 0, 10);
1797  }
1798  fPort = (fPort < 0) ? XPD_DEF_PORT : fPort;
1799 
1800  return 0;
1801 }
1802 
1803 ////////////////////////////////////////////////////////////////////////////////
1804 /// Process 'multiuser' directive
1805 
1806 int XrdProofdManager::DoDirectiveMultiUser(char *val, XrdOucStream *cfg, bool)
1807 {
1808  XPDLOC(ALL, "Manager::DoDirectiveMultiUser")
1809 
1810  if (!val)
1811  // undefined inputs
1812  return -1;
1813 
1814  // Multi-user option
1815  int mu = strtol(val, 0, 10);
1816  fMultiUser = (mu == 1) ? 1 : fMultiUser;
1817 
1818  // Check if we need to change the working dir template
1819  val = cfg->GetWord();
1820  if (val) fMUWorkDir = val;
1821 
1822  TRACE(DBG, "fMultiUser: "<< fMultiUser << " work dir template: " << fMUWorkDir);
1823 
1824  return 0;
1825 }
1826 
1827 ////////////////////////////////////////////////////////////////////////////////
1828 /// Process 'datasetsrc' directive
1829 
1830 int XrdProofdManager::DoDirectiveDataSetSrc(char *val, XrdOucStream *cfg, bool)
1831 {
1832  if (!val)
1833  // undefined inputs
1834  return -1;
1835 
1836  // URL for this source
1837  XrdOucString type(val), url, opts, obscure;
1838  bool rw = 0, local = 0, goodsrc = 1;
1839  char *nxt = 0;
1840  while ((nxt = cfg->GetWord())) {
1841  if (!strcmp(nxt, "rw=1") || !strcmp(nxt, "rw:1")) {
1842  rw = 1;
1843  } else if (!strncmp(nxt, "url:", 4)) {
1844  url = nxt + 4;
1845  XrdClientUrlInfo u(url);
1846  if (u.Proto == "" && u.HostWPort == "") local = 1;
1847  } else if (!strncmp(nxt, "opt:", 4)) {
1848  opts = nxt + 4;
1849  } else {
1850  obscure += nxt;
1851  obscure += " ";
1852  }
1853  }
1854 
1855  // Add to the list
1856  if (goodsrc) {
1857  // If first local, add it in front
1858  std::list<XrdProofdDSInfo *>::iterator ii = fDataSetSrcs.begin();
1859  bool haslocal = 0;
1860  for (ii = fDataSetSrcs.begin(); ii != fDataSetSrcs.end(); ++ii) {
1861  if ((*ii)->fLocal) {
1862  haslocal = 1;
1863  break;
1864  }
1865  }
1866  // Default options
1867  if (opts.length() <= 0) {
1868  opts = rw ? "Ar:Av:" : "-Ar:-Av:";
1869  }
1870  XrdProofdDSInfo *dsi = new XrdProofdDSInfo(type.c_str(), url.c_str(),
1871  local, rw, opts.c_str(), obscure.c_str());
1872  if (haslocal || !local) {
1873  fDataSetSrcs.push_back(dsi);
1874  } else {
1875  fDataSetSrcs.push_front(dsi);
1876  }
1877  }
1878  return 0;
1879 }
1880 
1881 ////////////////////////////////////////////////////////////////////////////////
1882 /// Process 'datadir' directive
1883 
1884 int XrdProofdManager::DoDirectiveDataDir(char *val, XrdOucStream *cfg, bool)
1885 {
1886  if (!val)
1887  // undefined inputs
1888  return -1;
1889 
1890  // Data directory and write permissions
1891  fDataDir = val;
1892  fDataDirOpts = "";
1893  fDataDirUrlOpts = "";
1894  XrdOucString opts;
1895  char *nxt = 0;
1896  while ((nxt = cfg->GetWord()) && (opts.length() == 0)) {
1897  opts = nxt;
1898  }
1899  if (opts.length() > 0) fDataDirOpts = opts;
1900  // Check if URL type options have been spcified in the main url
1901  int iq = STR_NPOS;
1902  if ((iq = fDataDir.rfind('?')) != STR_NPOS) {
1903  fDataDirUrlOpts.assign(fDataDir, iq + 1);
1904  fDataDir.erase(iq);
1905  }
1906 
1907  // Done
1908  return 0;
1909 }
1910 
1911 ////////////////////////////////////////////////////////////////////////////////
1912 /// Process 'xrootd' directive
1913 /// xpd.xrootd [path/]libXrdXrootd.so
1914 
1915 int XrdProofdManager::DoDirectiveXrootd(char *val, XrdOucStream *, bool)
1916 {
1917  XPDLOC(ALL, "Manager::DoDirectiveXrootd")
1918 
1919  if (!val)
1920  // undefined inputs
1921  return -1;
1922  TRACE(ALL, "val: "<< val);
1923  // Check version (v3 does not have the plugin, loading v4 may lead to problems)
1924  if (XrdMajorVNUM(XrdVNUMBER) < 4) {
1925  TRACE(ALL, "WARNING: built against an XRootD version without libXrdXrootd.so :");
1926  TRACE(ALL, "WARNING: loading external " << val << " may lead to incompatibilities");
1927  }
1928 
1929  fXrootdLibPath = val;
1930 
1931  // Done
1932  return 0;
1933 }
1934 
1935 ////////////////////////////////////////////////////////////////////////////////
1936 /// Process 'rootd' directive
1937 /// xpd.rootd deny|allow [rootsys:<tag>] [path:abs-path/] [mode:ro|rw]
1938 /// [auth:none|full] [other_rootd_args]
1939 
1940 int XrdProofdManager::DoDirectiveRootd(char *, XrdOucStream *, bool)
1941 {
1942  XPDLOC(ALL, "Manager::DoDirectiveRootd")
1943 
1944  TRACE(ALL, "unsupported!!! ");
1945 
1946  // Done
1947  return 0;
1948 }
1949 
1950 ////////////////////////////////////////////////////////////////////////////////
1951 /// Process 'rootdallow' directive
1952 /// xpd.rootdallow host1,host2 host3
1953 /// Host names may contain the wild card '*'
1954 
1955 int XrdProofdManager::DoDirectiveRootdAllow(char *, XrdOucStream *, bool)
1956 {
1957  XPDLOC(ALL, "Manager::DoDirectiveRootdAllow")
1958 
1959  TRACE(ALL, "unsupported!!! ");
1960 
1961  // Done
1962  return 0;
1963 }
1964 
1965 ////////////////////////////////////////////////////////////////////////////////
1966 /// Process 'filterlibpaths' directive
1967 /// xpd.filterlibpaths 1|0 [path1,path2 path3 path4 ...]
1968 
1969 int XrdProofdManager::DoDirectiveFilterLibPaths(char *val, XrdOucStream *cfg, bool)
1970 {
1971  XPDLOC(ALL, "Manager::DoDirectiveRemoveLibPaths")
1972 
1973  if (!val)
1974  // undefined inputs
1975  return -1;
1976 
1977  // Rebuild arguments list
1978  fLibPathsToRemove.Purge();
1979 
1980  TRACE(ALL, "val: "<< val);
1981 
1982  // Whether to remove ROOT lib paths before adding the effective one
1983  fRemoveROOTLibPaths = (!strcmp(val, "1") || !strcmp(val, "yes")) ? 1 : 0;
1984  if (fRemoveROOTLibPaths)
1985  TRACE(ALL, "Filtering out ROOT lib paths from "<<XPD_LIBPATH);
1986 
1987  // Parse the rest, if any
1988  char *nxt = 0;
1989  while ((nxt = cfg->GetWord())) {
1990  XrdOucString pps(nxt), p;
1991  int from = 0;
1992  while ((from = pps.tokenize(p, from, ',')) != -1) {
1993  if (p.length() > 0) {
1994  fLibPathsToRemove.Add(p.c_str(), 0, 0, Hash_data_is_key);
1995  TRACE(ALL, "Filtering out from "<<XPD_LIBPATH<<" lib path '"<<p<<"'");
1996  }
1997  }
1998  }
1999 
2000  // Done
2001  return 0;
2002 }
2003 
2004 ////////////////////////////////////////////////////////////////////////////////
2005 /// Process manager request
2006 
2007 int XrdProofdManager::Process(XrdProofdProtocol *p)
2008 {
2009  XPDLOC(ALL, "Manager::Process")
2010 
2011  int rc = 0;
2012  XPD_SETRESP(p, "Process");
2013 
2014  TRACEP(p, REQ, "req id: " << p->Request()->header.requestid << " (" <<
2015  XrdProofdAux::ProofRequestTypes(p->Request()->header.requestid) << ")");
2016 
2017  // If the user is not yet logged in, restrict what the user can do
2018  if (!p->Status() || !(p->Status() & XPD_LOGGEDIN)) {
2019  switch (p->Request()->header.requestid) {
2020  case kXP_auth:
2021  return fClientMgr->Auth(p);
2022  case kXP_login:
2023  return fClientMgr->Login(p);
2024  default:
2025  TRACEP(p, XERR, "invalid request: " << p->Request()->header.requestid);
2026  response->Send(kXR_InvalidRequest, "Invalid request; user not logged in");
2027  return p->Link()->setEtext("protocol sequence error 1");
2028  }
2029  }
2030 
2031  // Once logged-in, the user can request the real actions
2032  XrdOucString emsg;
2033  switch (p->Request()->header.requestid) {
2034  case kXP_admin: {
2035  int type = ntohl(p->Request()->proof.int1);
2036  return fAdmin->Process(p, type);
2037  }
2038  case kXP_readbuf:
2039  return fNetMgr->ReadBuffer(p);
2040  case kXP_create:
2041  case kXP_destroy:
2042  case kXP_attach:
2043  case kXP_detach:
2044  return fSessionMgr->Process(p);
2045  default:
2046  emsg += "Invalid request: ";
2047  emsg += p->Request()->header.requestid;
2048  break;
2049  }
2050 
2051  // Notify invalid request
2052  response->Send(kXR_InvalidRequest, emsg.c_str());
2053 
2054  // Done
2055  return 0;
2056 }