Logo ROOT   6.08/07
Reference Guide
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 
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 
230  fEffectiveUser = "";
231  fHost = "";
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();
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  ////// This is deprecated: see fXrootd below
254  // Rootd file serving enabled by default in readonly mode
255  fRootdExe = "";
256  // Add mandatory arguments
257  fRootdArgs.push_back(XrdOucString("-i"));
258  fRootdArgs.push_back(XrdOucString("-nologin"));
259  fRootdArgs.push_back(XrdOucString("-r")); // Readonly
260  fRootdArgs.push_back(XrdOucString("-noauth")); // No auth
261  // Build the argument list
262  fRootdArgsPtrs = new const char *[fRootdArgs.size() + 2];
263  fRootdArgsPtrs[0] = fRootdExe.c_str();
264  int i = 1;
265  std::list<XrdOucString>::iterator ia = fRootdArgs.begin();
266  while (ia != fRootdArgs.end()) {
267  fRootdArgsPtrs[i] = (*ia).c_str();
268  i++; ia++;
269  }
270  fRootdArgsPtrs[fRootdArgs.size() + 1] = 0;
271  // Started with 'system' (not 'fork')
272  fRootdFork = 0;
273  /////////////////////////////////////////////////////////////////
274 
275  // Tools to enable xrootd file serving
276  fXrootdLibPath = "<>";
277 
278  // Proof admin path
279  fAdminPath = pi->AdmPath;
280  fAdminPath += "/.xproofd.";
281 
282  // Lib paths for proofserv
283  fBareLibPath = "";
285  fLibPathsToRemove.Purge();
286 
287  // Services
288  fSched = pi->Sched;
289  fAdmin = 0;
290  fClientMgr = 0;
291  fGroupsMgr = 0;
292  fNetMgr = 0;
293  fPriorityMgr = 0;
294  fProofSched = 0;
295  fSessionMgr = 0;
296 
297  // Configuration directives
299 
300  // Admin request handler
301  fAdmin = new XrdProofdAdmin(this, pi, edest);
302 
303  // Client manager
304  fClientMgr = new XrdProofdClientMgr(this, pi, edest);
305 
306  // Network manager
307  fNetMgr = new XrdProofdNetMgr(this, pi, edest);
308 
309  // Priority manager
310  fPriorityMgr = new XrdProofdPriorityMgr(this, pi, edest);
311 
312  // ROOT versions manager
313  fROOTMgr = new XrdROOTMgr(this, pi, edest);
314 
315  // Session manager
316  fSessionMgr = new XrdProofdProofServMgr(this, pi, edest);
317 }
318 
319 ////////////////////////////////////////////////////////////////////////////////
320 /// Destructor
321 
323 {
324  // Destroy the configuration handler
333 }
334 
335 ////////////////////////////////////////////////////////////////////////////////
336 /// Load the Xrootd protocol, if required
337 
338 XrdProtocol *XrdProofdManager::LoadXrootd(char *parms, XrdProtocol_Config *pi, XrdSysError *edest)
339 {
340  XPDLOC(ALL, "Manager::LoadXrootd")
341 
342  XrdProtocol *xrp = 0;
343 
344  // Create the plug-in instance
345  XrdSysPlugin *xplg = new XrdSysPlugin((edest ? edest : (XrdSysError *)0), fXrootdLibPath.c_str());
346  if (!xplg) {
347  TRACE(XERR, "could not create plugin instance for "<<fXrootdLibPath.c_str());
348  return xrp;
349  }
350 
351  // Get the function
352  XrdProtocolLoader_t ep = (XrdProtocolLoader_t) xplg->getPlugin("XrdgetProtocol");
353  if (!ep) {
354  TRACE(XERR, "could not find 'XrdgetProtocol()' in "<<fXrootdLibPath.c_str());
355  return xrp;
356  }
357 
358  // Get the server object
359  if (!(xrp = (*ep)("xrootd", parms, pi))) {
360  TRACE(XERR, "Unable to create xrootd protocol service object via " << fXrootdLibPath.c_str());
361  SafeDelete(xplg);
362  } else {
363  // Notify
364  TRACE(ALL, "xrootd protocol service created");
365  }
366 
367  return xrp;
368 }
369 
370 ////////////////////////////////////////////////////////////////////////////////
371 /// Make sure that the log file belongs to the original effective user
372 
374 {
375  XPDLOC(ALL, "Manager::CheckLogFileOwnership")
376 
377  // Nothing to do if not priviledged
378  if (getuid()) return;
379 
380  struct stat st;
381  if (fstat(STDERR_FILENO, &st) != 0) {
382  if (errno != ENOENT) {
383  TRACE(XERR, "could not stat log file; errno: " << errno);
384  return;
385  }
386  }
387 
388  TRACE(HDBG, "uid: " << st.st_uid << ", gid: " << st.st_gid);
389 
390  // Get original effective user identity
391  struct passwd *epwd = getpwuid(XrdProofdProtocol::EUidAtStartup());
392  if (!epwd) {
393  TRACE(XERR, "could not get effective user identity; errno: " << errno);
394  return;
395  }
396 
397  // Set ownership of the log file to the effective user
398  if (st.st_uid != epwd->pw_uid || st.st_gid != epwd->pw_gid) {
399  if (fchown(STDERR_FILENO, epwd->pw_uid, epwd->pw_gid) != 0) {
400  TRACE(XERR, "could not set stderr ownership; errno: " << errno);
401  return;
402  }
403  }
404 }
405 
406 ////////////////////////////////////////////////////////////////////////////////
407 /// Check if master 'm' is allowed to connect to this host
408 
410 {
411  bool rc = 1;
412 
413  if (fMastersAllowed.size() > 0) {
414  rc = 0;
415  XrdOucString wm(m);
416  std::list<XrdOucString *>::iterator i;
417  for (i = fMastersAllowed.begin(); i != fMastersAllowed.end(); ++i) {
418  if (wm.matches((*i)->c_str())) {
419  rc = 1;
420  break;
421  }
422  }
423  }
424 
425  // We are done
426  return rc;
427 }
428 
429 ////////////////////////////////////////////////////////////////////////////////
430 /// Check if the user is allowed to use the system
431 /// Return 0 if OK, -1 if not.
432 
433 int XrdProofdManager::CheckUser(const char *usr, const char *grp,
434  XrdProofUI &ui, XrdOucString &e, bool &su)
435 {
436  su = 0;
437  // User must be defined
438  if (!usr || strlen(usr) <= 0) {
439  e = "CheckUser: 'usr' string is undefined ";
440  return -1;
441  }
442 
443  // No 'root' logins
444  if (strlen(usr) == 4 && !strcmp(usr, "root")) {
445  e = "CheckUser: 'root' logins not accepted ";
446  return -1;
447  }
448 
449  // Group must be defined
450  if (!grp || strlen(grp) <= 0) {
451  e = "CheckUser: 'grp' string is undefined ";
452  return -1;
453  }
454 
455  XrdSysMutexHelper mtxh(&fMutex);
456 
457  // Here we check if the user is known locally.
458  // If not, we fail for now.
459  // In the future we may try to get a temporary account
460  if (fChangeOwn) {
461  if (XrdProofdAux::GetUserInfo(usr, ui) != 0) {
462  e = "CheckUser: unknown ClientID: ";
463  e += usr;
464  return -1;
465  }
466  } else {
467  // We assign the ui of the effective user
468  if (XrdProofdAux::GetUserInfo(geteuid(), ui) != 0) {
469  e = "CheckUser: problems getting user info for id: ";
470  e += (int)geteuid();
471  return -1;
472  }
473  }
474 
475  // Check if super user
476  if (fSuperUsers.length() > 0) {
477  XrdOucString tkn;
478  int from = 0;
479  while ((from = fSuperUsers.tokenize(tkn, from, ',')) != -1) {
480  if (tkn == usr) {
481  su = 1;
482  break;
483  }
484  }
485  }
486 
487  // If we are in controlled mode we have to check if the user (and possibly
488  // its group) are in the authorized lists; otherwise we fail.
489  // Privileged users are always allowed to connect.
491 
492  // Policy: check first the general directive for groups; a user of a specific group
493  // (both UNIX or PROOF groups) can be rejected by prefixing a '-'.
494  // The group check fails if active (the allowedgroups directive has entries) and at
495  // least of the two groups (UNIX or PROOF) are explicitly denied.
496  // The result of the group check is superseeded by any explicit speicification in the
497  // allowedusers, either positive or negative.
498  // UNIX group includes secondary groups; this allows to enable/disable only members of a
499  // specific subgroup
500  //
501  // Examples:
502  // Consider user 'katy' with UNIX group 'alfa' and PROOF group 'student',
503  // users 'jack' and 'john' with UNIX group 'alfa' and PROOF group 'postdoc'.
504  //
505  // 1. xpd.allowedgroups alfa
506  // Users 'katy', 'jack' and 'john' are allowed because part of UNIX group 'alfa' (no 'allowedusers' directive)
507  // 2. xpd.allowedgroups student
508  // User 'katy' is allowed because part of PROOF group 'student';
509  // users 'jack' and 'john' are denied because not part of PROOF group 'student' (no 'allowedusers' directive)
510  // 3. xpd.allowedgroups alfa,-student
511  // User 'katy' is denied because part of PROOF group 'student' which is explicitly denied;
512  // users 'jack' and 'john' are allowed becasue part of UNIX group 'alfa' (no 'allowedusers' directive)
513  // 4. xpd.allowedgroups alfa,-student
514  // xpd.allowedusers katy,-jack
515  // User 'katy' is allowed because explicitly allowed by the 'allowedusers' directive;
516  // user 'jack' is denied because explicitly denied by the 'allowedusers' directive;
517  // user 'john' is allowed because part of 'alfa' and not explicitly denied by the 'allowedusers' directive
518  // (the allowedgroups directive is in this case ignored for users 'katy' and 'jack').
519 
520  bool grpok = 1;
521  // Check unix groups (secondaries included)
522  if (fAllowedGroups.Num() > 0) {
523  // Reset the flag
524  grpok = 0;
525  int ugrpok = 0, pgrpok = 0;
526  // Check UNIX groups info
527  int ngrps = 10, neg, ig = 0;
528 #if defined(__APPLE__)
529  int grps[10];
530 #else
531  gid_t grps[10];
532 #endif
533  XrdOucString g;
534  if ((neg = getgrouplist(usr, ui.fGid, grps, &ngrps)) < 0) neg = 10;
535  if (neg > 0) {
536  for (ig = 0; ig < neg; ig++) {
537  g.form("%d", (int) grps[ig]);
538  int *st = fAllowedGroups.Find(g.c_str());
539  if (st) {
540  if (*st == 1) {
541  ugrpok = 1;
542  } else {
543  e = "Controlled access (UNIX group): user '";
544  e += usr;
545  e = "', UNIX group '";
546  e += g;
547  e += "' denied to connect";
548  ugrpok = -1;
549  break;
550  }
551  }
552  }
553  }
554  // Check PROOF group info
555  int *st = fAllowedGroups.Find(grp);
556  if (st) {
557  if (*st == 1) {
558  pgrpok = 1;
559  } else {
560  if (e.length() <= 0)
561  e = "Controlled access";
562  e += " (PROOF group): user '";
563  e += usr;
564  e += "', PROOF group '";
565  e += grp;
566  e += "' denied to connect";
567  pgrpok = -1;
568  }
569  }
570  // At least one must be explicitly allowed with the other not explicitly denied
571  grpok = ((ugrpok == 1 && pgrpok >= 0) || (ugrpok >= 0 && pgrpok == 1)) ? 1 : 0;
572  }
573  // Check username
574  int usrok = 0;
575  if (fAllowedUsers.Num() > 0) {
576  // If we do not have a group specification we need to explicitly allow the user
577  if (fAllowedGroups.Num() <= 0) usrok = -1;
578  // Look into the hash
579  int *st = fAllowedUsers.Find(usr);
580  if (st) {
581  if (*st == 1) {
582  usrok = 1;
583  } else {
584  e = "Controlled access: user '";
585  e += usr;
586  e += "', PROOF group '";
587  e += grp;
588  e += "' not allowed to connect";
589  usrok = -1;
590  }
591  }
592  }
593  // Super users are always allowed
594  if (su) {
595  usrok = 1;
596  e = "";
597  }
598  // We fail if either the user is explicitly denied or it is not explicitly allowed
599  // and the group is denied
600  if (usrok == -1 || (!grpok && usrok != 1)) return -1;
601  }
602 
603  // OK
604  return 0;
605 }
606 
607 ////////////////////////////////////////////////////////////////////////////////
608 /// Load PROOF scheduler
609 
611 {
612  XPDLOC(ALL, "Manager::LoadScheduler")
613 
614  XrdProofSched *sched = 0;
615  XrdOucString name, lib, m;
616 
617  const char *cfn = CfgFile();
618 
619  // Locate first the relevant directives in the config file
620  if (cfn && strlen(cfn) > 0) {
621  XrdOucEnv myEnv;
622  XrdOucStream cfg(fEDest, getenv("XRDINSTANCE"), &myEnv);
623  // Open and attach the config file
624  int cfgFD;
625  if ((cfgFD = open(cfn, O_RDONLY, 0)) >= 0) {
626  cfg.Attach(cfgFD);
627  // Process items
628  char *val = 0, *var = 0;
629  while ((var = cfg.GetMyFirstWord())) {
630  if (!(strcmp("xpd.sched", var))) {
631  // Get the name
632  val = cfg.GetWord();
633  if (val && val[0]) {
634  name = val;
635  // Get the lib
636  val = cfg.GetWord();
637  if (val && val[0])
638  lib = val;
639  // We are done
640  break;
641  }
642  }
643  }
644  close(cfgFD);
645  } else {
646  XPDFORM(m, "failure opening config file; errno: %d", errno);
647  TRACE(XERR, m);
648  }
649  }
650 
651  // If undefined or default init a default instance
652  if (name == "default" || !(name.length() > 0 && lib.length() > 0)) {
653  if ((name.length() <= 0 && lib.length() > 0) ||
654  (name.length() > 0 && lib.length() <= 0)) {
655  XPDFORM(m, "missing or incomplete info (name: %s, lib: %s)", name.c_str(), lib.c_str());
656  TRACE(DBG, m);
657  }
658  TRACE(DBG, "instantiating default scheduler");
659  sched = new XrdProofSched("default", this, fGroupsMgr, cfn, fEDest);
660  } else {
661  // Load the required plugin
662  if (lib.beginswith("~") || lib.beginswith("$"))
664  XrdSysPlugin *h = new XrdSysPlugin(fEDest, lib.c_str());
665  if (!h)
666  return (XrdProofSched *)0;
667  // Get the scheduler object creator
668  XrdProofSchedLoader_t ep = (XrdProofSchedLoader_t) h->getPlugin("XrdgetProofSched", 1);
669  if (!ep) {
670  delete h;
671  return (XrdProofSched *)0;
672  }
673  // Get the scheduler object
674  if (!(sched = (*ep)(cfn, this, fGroupsMgr, cfn, fEDest))) {
675  TRACE(XERR, "unable to create scheduler object from " << lib);
676  delete h;
677  return (XrdProofSched *)0;
678  }
679  delete h;
680  }
681  // Check result
682  if (!(sched->IsValid())) {
683  TRACE(XERR, " unable to instantiate the " << sched->Name() << " scheduler using " << (cfn ? cfn : "<nul>"));
684  delete sched;
685  return (XrdProofSched *)0;
686  }
687  // Notify
688  TRACE(ALL, "scheduler loaded: type: " << sched->Name());
689 
690  // All done
691  return sched;
692 }
693 
694 ////////////////////////////////////////////////////////////////////////////////
695 /// Get a list of workers from the available resource broker
696 
698  const char *query)
699 {
700  XPDLOC(ALL, "Manager::GetWorkers")
701 
702  int rc = 0;
703  TRACE(REQ, "enter");
704 
705  // We need the scheduler at this point
706  if (!fProofSched) {
707  TRACE(XERR, "scheduler undefined");
708  return -1;
709  }
710 
711  // Query the scheduler for the list of workers
712  std::list<XrdProofWorker *> wrks, uwrks;
713  if ((rc = fProofSched->GetWorkers(xps, &wrks, query)) < 0) {
714  TRACE(XERR, "error getting list of workers from the scheduler");
715  return -1;
716  }
717  std::list<XrdProofWorker *>::iterator iw, iaw;
718  // If we got a new list we save it into the session object
719  if (rc == 0) {
720 
721  TRACE(DBG, "list size: " << wrks.size());
722 
723  XrdOucString ord;
724  int ii = -1;
725  // If in remote PLite mode, we need to isolate the number of workers
726  // per unique node
727  if (fRemotePLite) {
728  for (iw = wrks.begin(); iw != wrks.end() ; iw++) {
729  XrdProofWorker *w = *iw;
730  // Do we have it already in the unique list?
731  bool isnew = 1;
732  for (iaw = uwrks.begin(); iaw != uwrks.end() ; iaw++) {
733  XrdProofWorker *uw = *iaw;
734  if (w->fHost == uw->fHost && w->fPort == uw->fPort) {
735  uw->fNwrks += 1;
736  isnew = 0;
737  break;
738  }
739  }
740  if (isnew) {
741  // Count (fActive is increased inside here)
742  if (ii == -1) {
743  ord = "master";
744  } else {
745  XPDFORM(ord, "%d", ii);
746  }
747  ii++;
748  XrdProofWorker *uw = new XrdProofWorker(*w);
749  uw->fType = 'S';
750  uw->fOrd = ord;
751  uwrks.push_back(uw);
752  // Setup connection with the proofserv using the original
753  xps->AddWorker(ord.c_str(), w);
754  w->AddProofServ(xps);
755  }
756  }
757  for (iw = uwrks.begin(); iw != uwrks.end() ; iw++) {
758  XrdProofWorker *w = *iw;
759  // Master at the beginning
760  if (w->fType == 'M') {
761  if (lw.length() > 0) lw.insert('&',0);
762  lw.insert(w->Export(), 0);
763  } else {
764  // Add separator if not the first
765  if (lw.length() > 0) lw += '&';
766  // Add export version of the info
767  lw += w->Export(0);
768  }
769  }
770 
771  } else {
772 
773  // The full list
774  for (iw = wrks.begin(); iw != wrks.end() ; iw++) {
775  XrdProofWorker *w = *iw;
776  // Count (fActive is increased inside here)
777  if (ii == -1)
778  ord = "master";
779  else
780  XPDFORM(ord, "%d", ii);
781  ii++;
782  xps->AddWorker(ord.c_str(), w);
783  // Add proofserv and increase the counter
784  w->AddProofServ(xps);
785  }
786  }
787  }
788 
789  int proto = (xps->ROOT()) ? xps->ROOT()->SrvProtVers() : -1;
790  if (rc != 2 || (proto < 21 && rc == 0)) {
791  // Get the list in exported format
792  if (lw.length() <= 0) xps->ExportWorkers(lw);
793  TRACE(DBG, "from ExportWorkers: " << lw);
794  } else if (proto >= 21) {
795  // Signal enqueing
797  }
798 
799  if (TRACING(REQ)) fNetMgr->Dump();
800 
801  // Clear the temp list
802  if (uwrks.size() > 0) {
803  iw = uwrks.begin();
804  while (iw != uwrks.end()) {
805  XrdProofWorker *w = *iw;
806  iw = uwrks.erase(iw);
807  delete w;
808  }
809  }
810 
811  return rc;
812 }
813 
814 ////////////////////////////////////////////////////////////////////////////////
815 /// Add the key value in the string passed via the void argument
816 
817 static int FillKeyValues(const char *k, int *d, void *s)
818 {
819  xpd_acm_lists_t *ls = (xpd_acm_lists_t *)s;
820 
821  if (ls) {
822  XrdOucString &ss = (*d == 1) ? ls->allowed : ls->denied;
823  // Add the key
824  if (k) {
825  XrdOucString sk;
826  sk += k;
827  if (!sk.isdigit()) {
828  // If not empty add a separation ','
829  if (ss.length() > 0) ss += ",";
830  ss += sk;
831  }
832  }
833  } else {
834  // Not enough info: stop
835  return 1;
836  }
837 
838  // Check next
839  return 0;
840 }
841 
842 ////////////////////////////////////////////////////////////////////////////////
843 /// Add the key value in the string passed via the void argument
844 
845 static int RemoveInvalidUsers(const char *k, int *, void *s)
846 {
847  XrdOucString *ls = (XrdOucString *)s;
848 
849  XrdProofUI ui;
850  if (XrdProofdAux::GetUserInfo(k, ui) != 0) {
851  // Username is unknown to the system: remove it to the list
852  if (ls) {
853  // If not empty add a separation ','
854  if (ls->length() > 0) *ls += ",";
855  // Add the key
856  if (k) *ls += k;
857  }
858  // Negative return removes from the table
859  return -1;
860  }
861 
862  // Check next
863  return 0;
864 }
865 
866 ////////////////////////////////////////////////////////////////////////////////
867 /// Run configuration and parse the entered config directives.
868 /// Return 0 on success, -1 on error
869 
871 {
872  XPDLOC(ALL, "Manager::Config")
873 
875 
876  // Run first the configurator
877  if (XrdProofdConfig::Config(rcf) != 0) {
878  XPDERR("problems parsing file ");
879  return -1;
880  }
881 
882  XrdOucString msg;
883  msg = (rcf) ? "re-configuring" : "configuring";
884  TRACE(ALL, msg);
885 
886  // Change/DonotChange ownership when logging clients
887  fChangeOwn = (fMultiUser && getuid()) ? 0 : 1;
888 
889  // Notify port
890  XPDFORM(msg, "listening on port %d", fPort);
891  TRACE(ALL, msg);
892 
893  XrdProofUI ui;
894  uid_t effuid = XrdProofdProtocol::EUidAtStartup();
895  if (!rcf) {
896  // Save Effective user
897  if (XrdProofdAux::GetUserInfo(effuid, ui) == 0) {
898  fEffectiveUser = ui.fUser;
899  } else {
900  XPDFORM(msg, "could not resolve effective uid %d (errno: %d)", effuid, errno);
901  XPDERR(msg);
902  return -1;
903  }
904 
905  // Local FQDN
906  char *host = XrdSysDNS::getHostName();
907  fHost = host ? host : "";
908  SafeFree(host);
909 
910  // Notify temporary directory
911  TRACE(ALL, "using temp dir: " << fTMPdir);
912 
913  // Notify role
914  const char *roles[] = { "any", "worker", "submaster", "master" };
915  TRACE(ALL, "role set to: " << roles[fSrvType+1]);
916 
917  // Admin path
918  fAdminPath += fPort;
919  if (XrdProofdAux::AssertDir(fAdminPath.c_str(), ui, fChangeOwn) != 0) {
920  XPDERR("unable to assert the admin path: " << fAdminPath);
921  return -1;
922  }
923  TRACE(ALL, "admin path set to: " << fAdminPath);
924 
925  // Path for Unix sockets
926  if (fSockPathDir.length() <= 0) {
927  // Use default under the admin path
928  XPDFORM(fSockPathDir, "%s/socks", fAdminPath.c_str());
929  }
930  if (XrdProofdAux::AssertDir(fSockPathDir.c_str(), ui, fChangeOwn) != 0) {
931  XPDERR("unable to assert the admin path: " << fSockPathDir);
932  return -1;
933  }
934  if (XrdProofdAux::ChangeMod(fSockPathDir.c_str(), 0777) != 0) {
935  XPDERR("unable to set mode 0777 on: " << fSockPathDir);
936  return -1;
937  }
938  TRACE(ALL, "unix sockets under: " << fSockPathDir);
939 
940  // Create / Update the process ID file under the admin path
941  XrdOucString pidfile(fAdminPath);
942  pidfile += "/xrootd.pid";
943  FILE *fpid = fopen(pidfile.c_str(), "w");
944  if (!fpid) {
945  XPDFORM(msg, "unable to open pid file: %s; errno: %d", pidfile.c_str(), errno);
946  XPDERR(msg);
947  return -1;
948  }
949  fprintf(fpid, "%d", getpid());
950  fclose(fpid);
951  } else {
952  if (XrdProofdAux::GetUserInfo(effuid, ui) == 0) {
953  XPDFORM(msg, "could not resolve effective uid %d (errno: %d)", effuid, errno);
954  XPDERR(msg);
955  }
956  }
957 
958  // Work directory, if specified
959  XrdOucString wdir;
960  if (fWorkDir.length() > 0) {
961  // Make sure it exists
962  if (XrdProofdAux::AssertDir(fWorkDir.c_str(), ui, fChangeOwn) != 0) {
963  XPDERR("unable to assert working dir: " << fWorkDir);
964  return -1;
965  }
966  if (fMUWorkDir.length() > 0) {
967  fMUWorkDir.replace("<workdir>", fWorkDir);
968  int iph = fMUWorkDir.find("<");
969  if (iph != STR_NPOS) {
970  wdir.assign(fMUWorkDir, 0, iph - 2);
971  if (XrdProofdAux::AssertDir(wdir.c_str(), ui, fChangeOwn) != 0) {
972  XPDERR("unable to assert working dir: " << wdir);
973  return -1;
974  }
975  wdir = "";
976  }
977  }
978  }
979  wdir = (fMultiUser && fMUWorkDir.length() > 0) ? fMUWorkDir : fWorkDir;
980  if (wdir.length() > 0) {
981  TRACE(ALL, "working directories under: " << wdir);
982  // Communicate it to the sandbox service
983  XrdProofdSandbox::SetWorkdir(wdir.c_str());
984  }
985 
986  // Data directory, if specified
987  if (fDataDir.length() > 0) {
988  if (fDataDir.endswith('/')) fDataDir.erasefromend(1);
989  if (fDataDirOpts.length() > 0) {
990  // Make sure it exists
991  if (XrdProofdAux::AssertDir(fDataDir.c_str(), ui, fChangeOwn) != 0) {
992  XPDERR("unable to assert data dir: " << fDataDir << " (opts: "<<fDataDirOpts<<")");
993  return -1;
994  }
995  // Get the right privileges now
996  XrdSysPrivGuard pGuard((uid_t)ui.fUid, (gid_t)ui.fGid);
997  if (XpdBadPGuard(pGuard, ui.fUid)) {
998  TRACE(XERR, "could not get privileges to set/change ownership of " << fDataDir);
999  return -1;
1000  }
1001  if (chmod(fDataDir.c_str(), 0777) != 0) {
1002  XPDERR("problems setting permissions 0777 data dir: " << fDataDir);
1003  return -1;
1004  }
1005  }
1006  TRACE(ALL, "data directories under: " << fDataDir);
1007  }
1008 
1009  // Notify allow rules
1010  if (fSrvType == kXPD_Worker) {
1011  if (fMastersAllowed.size() > 0) {
1012  std::list<XrdOucString *>::iterator i;
1013  for (i = fMastersAllowed.begin(); i != fMastersAllowed.end(); ++i)
1014  TRACE(ALL, "masters allowed to connect: " << (*i)->c_str());
1015  } else {
1016  TRACE(ALL, "masters allowed to connect: any");
1017  }
1018  }
1019 
1020  // Pool and namespace
1021  if (fPoolURL.length() <= 0) {
1022  // Default pool entry point is this host
1023  fPoolURL = "root://";
1024  fPoolURL += fHost;
1025  }
1026  TRACE(ALL, "PROOF pool: " << fPoolURL);
1027  TRACE(ALL, "PROOF pool namespace: " << fNamespace);
1028 
1029  // Initialize resource broker (if not worker)
1030  if (fSrvType != kXPD_Worker) {
1031 
1032  // Scheduler instance
1033  if (!(fProofSched = LoadScheduler())) {
1034  XPDERR("scheduler initialization failed");
1035  return 0;
1036  }
1037  const char *st[] = { "disabled", "enabled" };
1038  TRACE(ALL, "user config files are " << st[fNetMgr->WorkerUsrCfg()]);
1039  }
1040 
1041  // If using the PLite optimization notify it
1042  if (fRemotePLite)
1043  TRACE(ALL, "multi-process on nodes handled with proof-lite");
1044 
1045  // Validate dataset sources (if not worker)
1046  fDataSetExp = "";
1047  if (fSrvType != kXPD_Worker && fDataSetSrcs.size() > 0) {
1048  // If first local, add it in front
1049  std::list<XrdProofdDSInfo *>::iterator ii = fDataSetSrcs.begin();
1050  bool goodsrc = 0;
1051  for (ii = fDataSetSrcs.begin(); ii != fDataSetSrcs.end();) {
1052  TRACE(ALL, ">> Defined dataset: " << (*ii)->ToString());
1053  if ((*ii)->fType == "file") {
1054  if (!(goodsrc = ValidateLocalDataSetSrc((*ii)->fUrl, (*ii)->fLocal))) {
1055  XPDERR("source " << (*ii)->fUrl << " could not be validated");
1056  ii = fDataSetSrcs.erase(ii);
1057  } else {
1058  // Check next
1059  ii++;
1060  }
1061  } else {
1062  // Validate only "file" datasets
1063  TRACE(ALL, "Skipping validation (no \"file\" type dataset source)");
1064  ii++;
1065  }
1066  }
1067  if (fDataSetSrcs.size() > 0) {
1068  TRACE(ALL, fDataSetSrcs.size() << " dataset sources defined");
1069  for (ii = fDataSetSrcs.begin(); ii != fDataSetSrcs.end(); ii++) {
1070  TRACE(ALL, ">> Valid dataset: " << (*ii)->ToString());
1071  if ((*ii)->fLocal && (*ii)->fRW) {
1072  if (fDataSetExp.length() > 0) fDataSetExp += ",";
1073  fDataSetExp += ((*ii)->fUrl).c_str();
1074  }
1075  }
1076  } else {
1077  TRACE(ALL, "no dataset sources defined");
1078  }
1079  } else {
1080  TRACE(ALL, "no dataset sources defined");
1081  }
1082 
1083  // Superusers: add the effective user at startup
1084  XrdProofUI sui;
1086  if (fSuperUsers.find(sui.fUser.c_str()) == STR_NPOS) {
1087  if (fSuperUsers.length() > 0) fSuperUsers += ",";
1088  fSuperUsers += sui.fUser;
1089  }
1090  } else {
1091  XPDFORM(msg, "could not resolve effective uid %d (errno: %d)",
1093  XPDERR(msg);
1094  }
1095  XPDFORM(msg, "list of superusers: %s", fSuperUsers.c_str());
1096  TRACE(ALL, msg);
1097 
1098  // Notify controlled mode, if such
1100  // Add superusers to the hash list of allowed users
1101  int from = 0;
1102  XrdOucString usr;
1103  while ((from = fSuperUsers.tokenize(usr, from, ',')) != STR_NPOS) {
1104  fAllowedUsers.Add(usr.c_str(), new int(1));
1105  }
1106  // If not in multiuser mode make sure that the users in the allowed list
1107  // are known to the system
1108  if (!fMultiUser) {
1109  XrdOucString ius;
1110  fAllowedUsers.Apply(RemoveInvalidUsers, (void *)&ius);
1111  if (ius.length()) {
1112  XPDFORM(msg, "running in controlled access mode: users removed because"
1113  " unknown to the system: %s", ius.c_str());
1114  TRACE(ALL, msg);
1115  }
1116  }
1117  // Extract now the list of allowed users
1118  xpd_acm_lists_t uls;
1119  fAllowedUsers.Apply(FillKeyValues, (void *)&uls);
1120  if (uls.allowed.length()) {
1121  XPDFORM(msg, "running in controlled access mode: users allowed: %s", uls.allowed.c_str());
1122  TRACE(ALL, msg);
1123  }
1124  if (uls.denied.length()) {
1125  XPDFORM(msg, "running in controlled access mode: users denied: %s", uls.denied.c_str());
1126  TRACE(ALL, msg);
1127  }
1128  // Extract now the list of allowed groups
1129  xpd_acm_lists_t gls;
1130  fAllowedGroups.Apply(FillKeyValues, (void *)&gls);
1131  if (gls.allowed.length()) {
1132  XPDFORM(msg, "running in controlled access mode: UNIX groups allowed: %s", gls.allowed.c_str());
1133  TRACE(ALL, msg);
1134  }
1135  if (gls.denied.length()) {
1136  XPDFORM(msg, "running in controlled access mode: UNIX groups denied: %s", gls.denied.c_str());
1137  TRACE(ALL, msg);
1138  }
1139  }
1140 
1141  // Bare lib path
1142  if (getenv(XPD_LIBPATH)) {
1143  XrdOucString ctrim;
1144  if (fRemoveROOTLibPaths || fLibPathsToRemove.Num() > 0) {
1145  // Try to remove existing ROOT dirs in the path
1146  XrdOucString paths = getenv(XPD_LIBPATH);
1147  XrdOucString ldir;
1148  int from = 0;
1149  while ((from = paths.tokenize(ldir, from, ':')) != STR_NPOS) {
1150  bool remove = 0;
1151  if (ldir.length() > 0) {
1152  if (fLibPathsToRemove.Num() > 0 && fLibPathsToRemove.Find(ldir.c_str())) {
1153  remove = 1;
1154  } else if (fRemoveROOTLibPaths) {
1155  // Check this dir
1156  DIR *dir = opendir(ldir.c_str());
1157  if (dir) {
1158  // Scan the directory
1159  struct dirent *ent = 0;
1160  while ((ent = (struct dirent *)readdir(dir))) {
1161  if (!strncmp(ent->d_name, "libCore", 7)) {
1162  remove = 1;
1163  break;
1164  }
1165  }
1166  // Close the directory
1167  closedir(dir);
1168  }
1169  }
1170  }
1171  if (!remove) {
1172  if (fBareLibPath.length() > 0)
1173  fBareLibPath += ":";
1174  fBareLibPath += ldir;
1175  }
1176  }
1177  ctrim = " (lib paths filter applied)";
1178  } else {
1179  // Full path
1180  ctrim = " (full ";
1181  ctrim += XPD_LIBPATH;
1182  ctrim += ")";
1183  fBareLibPath = getenv(XPD_LIBPATH);
1184  }
1185  TRACE(ALL, "bare lib path for proofserv" << ctrim <<": " << fBareLibPath);
1186  }
1187 
1188  // Groups
1189  if (!fGroupsMgr)
1190  // Create default group, if none explicitly requested
1192 
1193  if (fGroupsMgr)
1194  fGroupsMgr->Print(0);
1195 
1196  // Config the admin handler
1197  if (fAdmin && fAdmin->Config(rcf) != 0) {
1198  XPDERR("problems configuring the admin handler");
1199  return -1;
1200  }
1201 
1202  // Config the network manager
1203  if (fNetMgr && fNetMgr->Config(rcf) != 0) {
1204  XPDERR("problems configuring the network manager");
1205  return -1;
1206  }
1207 
1208  // Config the priority manager
1209  if (fPriorityMgr && fPriorityMgr->Config(rcf) != 0) {
1210  XPDERR("problems configuring the priority manager");
1211  return -1;
1212  }
1213 
1214  // Config the ROOT versions manager
1215  if (fROOTMgr) {
1216  fROOTMgr->SetLogDir(fAdminPath.c_str());
1217  if (fROOTMgr && fROOTMgr->Config(rcf) != 0) {
1218  XPDERR("problems configuring the ROOT versions manager");
1219  return -1;
1220  }
1221  }
1222 
1223  // Config the client manager
1224  if (fClientMgr && fClientMgr->Config(rcf) != 0) {
1225  XPDERR("problems configuring the client manager");
1226  return -1;
1227  }
1228 
1229  // Config the session manager
1230  if (fSessionMgr && fSessionMgr->Config(rcf) != 0) {
1231  XPDERR("problems configuring the session manager");
1232  return -1;
1233  }
1234 
1235  // Config the scheduler
1236  if (fProofSched && fProofSched->Config(rcf) != 0) {
1237  XPDERR("problems configuring the scheduler");
1238  return -1;
1239  }
1240 
1241  // Xrootd protocol service
1242  if ((fXrootd = LoadXrootd(fParms, fPi, fEDest))) {
1243  // If enabled, Xrootd takes precedence
1244  fRootdExe = "";
1245  }
1246 
1247  // File server
1248  if (fRootdExe.length() > 0) {
1249  // Absolute or relative?
1250  if (!fRootdExe.beginswith("/")) {
1251  if (fROOTMgr) {
1252  XrdOucString rtag;
1253  if (fRootdExe.beginswith("<") && fRootdExe.endswith(">")) {
1254  if (fRootdExe.length() > 2) rtag.assign(fRootdExe, 1, fRootdExe.length() - 2);
1255  fRootdExe = "rootd";
1256  fRootdArgsPtrs[0] = fRootdExe.c_str();
1257  }
1258  XrdROOT *roo = 0;
1259  if (rtag.length() <= 0 || !(roo = fROOTMgr->GetVersion(rtag.c_str())))
1260  roo = fROOTMgr->DefaultVersion();
1261  if (roo && strlen(roo->BinDir()) > 0) {
1262  XrdOucString bindir(roo->BinDir());
1263  if (!bindir.endswith("/")) bindir += "/";
1264  fRootdExe.insert(bindir, 0);
1265  fRootdArgsPtrs[0] = fRootdExe.c_str();
1266  }
1267  }
1268  }
1269  // Create unix socket where to accepts callbacks from rootd launchers
1270  XrdOucString sockpath;
1271  XPDFORM(sockpath, "%s/xpd.%d.%d.rootd", fSockPathDir.c_str(), fPort, getpid());
1272  fRootdUnixSrv = new rpdunixsrv(sockpath.c_str());
1273  if (!fRootdUnixSrv || (fRootdUnixSrv && !fRootdUnixSrv->isvalid(0))) {
1274  XPDERR("could not start unix server connection on path "<<
1275  sockpath<<" - errno: "<<(int)errno);
1276  fRootdExe = "";
1277  return -1;
1278  }
1279  TRACE(ALL, "unix socket path for rootd call backs: "<<sockpath);
1280  // Check if access is controlled
1281  if (fRootdAllow.size() > 0) {
1282  XrdOucString hhs;
1283  std::list<XrdOucString>::iterator ia = fRootdAllow.begin();
1284  while (ia != fRootdAllow.end()) {
1285  if (hhs.length() > 0) hhs += ",";
1286  hhs += (*ia).c_str();
1287  ia++;
1288  }
1289  TRACE(ALL, "serving files with: '" << fRootdExe <<"' (protocol: 'rootd://') to ALLOWED hosts");
1290  TRACE(ALL, "rootd-allowed hosts: "<< hhs);
1291  } else {
1292  TRACE(ALL, "serving files with: '" << fRootdExe <<"' (protocol: 'rootd://') to ALL hosts");
1293  }
1294 
1295  } else {
1296  TRACE(ALL, "file serving (protocol: 'rootd://') explicitly disabled");
1297  }
1298 
1299  if (!rcf) {
1300  // Start cron thread
1301  pthread_t tid;
1302  if (XrdSysThread::Run(&tid, XrdProofdManagerCron,
1303  (void *)this, 0, "ProofdManager cron thread") != 0) {
1304  XPDERR("could not start cron thread");
1305  return 0;
1306  }
1307  TRACE(ALL, "manager cron thread started");
1308  }
1309 
1310  // Done
1311  return 0;
1312 }
1313 
1314 ////////////////////////////////////////////////////////////////////////////////
1315 /// Validate local dataset src at URL (check the URL and make the relevant
1316 /// directories).
1317 /// Return 1 if OK, 0 if any problem arises
1318 
1319 bool XrdProofdManager::ValidateLocalDataSetSrc(XrdOucString &url, bool &local)
1320 {
1321  XPDLOC(ALL, "Manager::ValidateLocalDataSetSrc")
1322 
1323  TRACE(ALL, "validating '" << url << "' ...");
1324  local = 0;
1325  bool goodsrc = 1;
1326  if (url.length() > 0) {
1327  // Check if local source
1328  if (url.beginswith("file:")) url.replace("file:", "");
1329  if (url.beginswith("/")) {
1330  local = 1;
1331  goodsrc = 0;
1332  // Make sure the directory exists and has mode 0755
1333  XrdProofUI ui;
1335  if (XrdProofdAux::AssertDir(url.c_str(), ui, ChangeOwn()) == 0) {
1336  goodsrc = 1;
1337  if (XrdProofdAux::ChangeMod(url.c_str(), 0777) != 0) {
1338  TRACE(XERR, "Problems setting permissions 0777 on path '" << url << "'");
1339  }
1340  } else {
1341  TRACE(XERR, "Cannot assert path '" << url << "' - ignoring");
1342  }
1343  if (goodsrc) {
1344  // Assert the file with dataset summaries
1345  XrdOucString fnpath(url.c_str());
1346  fnpath += "/dataset.list";
1347  if (access(fnpath.c_str(), F_OK) != 0) {
1348  FILE *flst = fopen(fnpath.c_str(), "w");
1349  if (!flst) {
1350  TRACE(XERR, "Cannot open file '" << fnpath << "' for the dataset list; errno: " << errno);
1351  goodsrc = 0;
1352  } else {
1353  if (fclose(flst) != 0)
1354  TRACE(XERR, "Problems closing file '" << fnpath << "'; errno: " << errno);
1355  if (XrdProofdAux::ChangeOwn(fnpath.c_str(), ui) != 0) {
1356  TRACE(XERR, "Problems asserting ownership of " << fnpath);
1357  }
1358  }
1359  }
1360  // Make sure that everybody can modify the file for updates
1361  if (goodsrc && XrdProofdAux::ChangeMod(fnpath.c_str(), 0666) != 0) {
1362  TRACE(XERR, "Problems setting permissions to 0666 on file '" << fnpath << "'; errno: " << errno);
1363  goodsrc = 0;
1364  }
1365  // Assert the file with lock file path
1366  if (goodsrc) {
1367  fnpath.replace("/dataset.list", "/lock.location");
1368  FILE *flck = fopen(fnpath.c_str(), "a");
1369  if (!flck) {
1370  TRACE(XERR, "Cannot open file '" << fnpath << "' with the lock file path; errno: " << errno);
1371  } else {
1372  errno = 0;
1373  off_t ofs = lseek(fileno(flck), 0, SEEK_CUR);
1374  if (ofs == 0) {
1375  // New file: write the default lock file path
1376  XrdOucString fnlock(url);
1377  fnlock.replace("/", "%");
1378  fnlock.replace(":", "%");
1379  fnlock.insert("/tmp/", 0);
1380  fprintf(flck, "%s\n", fnlock.c_str());
1381  if (fclose(flck) != 0)
1382  TRACE(XERR, "Problems closing file '" << fnpath << "'; errno: " << errno);
1383  flck = 0;
1384  if (XrdProofdAux::ChangeOwn(fnpath.c_str(), ui) != 0) {
1385  TRACE(XERR, "Problems asserting ownership of " << fnpath);
1386  }
1387  } else if (ofs == (off_t)(-1)) {
1388  TRACE(XERR, "Problems getting current position on file '" << fnpath << "'; errno: " << errno);
1389  }
1390  if (flck && fclose(flck) != 0)
1391  TRACE(XERR, "Problems closing file '" << fnpath << "'; errno: " << errno);
1392  }
1393  }
1394  // Make sure that everybody can modify the file for updates
1395  if (goodsrc && XrdProofdAux::ChangeMod(fnpath.c_str(), 0644) != 0) {
1396  TRACE(XERR, "Problems setting permissions to 0644 on file '" << fnpath << "'; errno: " << errno);
1397  }
1398  }
1399  }
1400  }
1401  else {
1402  TRACE(ALL, "New dataset with no URL!");
1403  }
1404  // Done
1405  return goodsrc;
1406 }
1407 
1408 ////////////////////////////////////////////////////////////////////////////////
1409 /// Register directives for configuration
1410 
1412 {
1413  // Register special config directives
1414  Register("trace", new XrdProofdDirective("trace", this, &DoDirectiveClass));
1415  Register("groupfile", new XrdProofdDirective("groupfile", this, &DoDirectiveClass));
1416  Register("multiuser", new XrdProofdDirective("multiuser", this, &DoDirectiveClass));
1417  Register("maxoldlogs", new XrdProofdDirective("maxoldlogs", this, &DoDirectiveClass));
1418  Register("allow", new XrdProofdDirective("allow", this, &DoDirectiveClass));
1419  Register("allowedgroups", new XrdProofdDirective("allowedgroups", this, &DoDirectiveClass));
1420  Register("allowedusers", new XrdProofdDirective("allowedusers", this, &DoDirectiveClass));
1421  Register("role", new XrdProofdDirective("role", this, &DoDirectiveClass));
1422  Register("cron", new XrdProofdDirective("cron", this, &DoDirectiveClass));
1423  Register("port", new XrdProofdDirective("port", this, &DoDirectiveClass));
1424  Register("datadir", new XrdProofdDirective("datadir", this, &DoDirectiveClass));
1425  Register("datasetsrc", new XrdProofdDirective("datasetsrc", this, &DoDirectiveClass));
1426  Register("rootd", new XrdProofdDirective("rootd", this, &DoDirectiveClass));
1427  Register("rootdallow", new XrdProofdDirective("rootdallow", this, &DoDirectiveClass));
1428  Register("xrd.protocol", new XrdProofdDirective("xrd.protocol", this, &DoDirectiveClass));
1429  Register("filterlibpaths", new XrdProofdDirective("filterlibpaths", this, &DoDirectiveClass));
1430  Register("xrootd", new XrdProofdDirective("xrootd", this, &DoDirectiveClass));
1431  // Register config directives for strings
1432  Register("tmp", new XrdProofdDirective("tmp", (void *)&fTMPdir, &DoDirectiveString));
1433  Register("poolurl", new XrdProofdDirective("poolurl", (void *)&fPoolURL, &DoDirectiveString));
1434  Register("namespace", new XrdProofdDirective("namespace", (void *)&fNamespace, &DoDirectiveString));
1435  Register("superusers", new XrdProofdDirective("superusers", (void *)&fSuperUsers, &DoDirectiveString));
1436  Register("image", new XrdProofdDirective("image", (void *)&fImage, &DoDirectiveString));
1437  Register("workdir", new XrdProofdDirective("workdir", (void *)&fWorkDir, &DoDirectiveString));
1438  Register("sockpathdir", new XrdProofdDirective("sockpathdir", (void *)&fSockPathDir, &DoDirectiveString));
1439  Register("remoteplite", new XrdProofdDirective("remoteplite", (void *)&fRemotePLite, &DoDirectiveInt));
1440  Register("stagereqrepo", new XrdProofdDirective("stagereqrepo", (void *)&fStageReqRepo, &DoDirectiveString));
1441 }
1442 
1443 ////////////////////////////////////////////////////////////////////////////////
1444 /// Resolve special keywords in 's' for client 'pcl'. Recognized keywords
1445 /// <workdir> root for working dirs
1446 /// <host> local host name
1447 /// <port> daemon port
1448 /// <homedir> user home dir
1449 /// <user> user name
1450 /// <group> user group
1451 /// <uid> user ID
1452 /// <gid> user group ID
1453 /// <effuser> effective user name (for multiuser or user mapping modes)
1454 /// Return the number of keywords resolved.
1455 
1457 {
1458  XPDLOC(ALL, "Manager::ResolveKeywords")
1459 
1460  int nk = 0;
1461 
1462  TRACE(HDBG, "enter: " << s << " - WorkDir(): " << WorkDir());
1463 
1464  // Parse <workdir>
1465  if (s.replace("<workdir>", WorkDir()))
1466  nk++;
1467 
1468  TRACE(HDBG, "after <workdir>: " << s);
1469 
1470  // Parse <host>
1471  if (s.replace("<host>", Host()))
1472  nk++;
1473 
1474  TRACE(HDBG, "after <host>: " << s);
1475 
1476  // Parse <port>
1477  if (s.find("<port>") != STR_NPOS) {
1478  XrdOucString sport;
1479  sport += Port();
1480  if (s.replace("<port>", sport.c_str()))
1481  nk++;
1482  }
1483 
1484  // Parse <effuser> of the process
1485  if (s.find("<effuser>") != STR_NPOS) {
1486  XrdProofUI eui;
1487  if (XrdProofdAux::GetUserInfo(geteuid(), eui) == 0) {
1488  if (s.replace("<effuser>", eui.fUser.c_str()))
1489  nk++;
1490  }
1491  }
1492 
1493  // Parse <user>
1494  if (pcl)
1495  if (s.replace("<user>", pcl->User()))
1496  nk++;
1497 
1498  // Parse <group>
1499  if (pcl)
1500  if (s.replace("<group>", pcl->Group()))
1501  nk++;
1502 
1503  // Parse <homedir>
1504  if (pcl)
1505  if (s.replace("<homedir>", pcl->UI().fHomeDir.c_str()))
1506  nk++;
1507 
1508  // Parse <uid>
1509  if (pcl && (s.find("<uid>") != STR_NPOS)) {
1510  XrdOucString suid;
1511  suid += pcl->UI().fUid;
1512  if (s.replace("<uid>", suid.c_str()))
1513  nk++;
1514  }
1515 
1516  // Parse <gid>
1517  if (pcl && (s.find("<gid>") != STR_NPOS)) {
1518  XrdOucString sgid;
1519  sgid += pcl->UI().fGid;
1520  if (s.replace("<gid>", sgid.c_str()))
1521  nk++;
1522  }
1523 
1524  TRACE(HDBG, "exit: " << s);
1525 
1526  // We are done
1527  return nk;
1528 }
1529 
1530 //
1531 // Special directive processors
1532 
1533 ////////////////////////////////////////////////////////////////////////////////
1534 /// Update the priorities of the active sessions.
1535 
1537  char *val, XrdOucStream *cfg, bool rcf)
1538 {
1539  XPDLOC(ALL, "Manager::DoDirective")
1540 
1541  if (!d)
1542  // undefined inputs
1543  return -1;
1544 
1545  if (d->fName == "trace") {
1546  return DoDirectiveTrace(val, cfg, rcf);
1547  } else if (d->fName == "groupfile") {
1548  return DoDirectiveGroupfile(val, cfg, rcf);
1549  } else if (d->fName == "maxoldlogs") {
1550  return DoDirectiveMaxOldLogs(val, cfg, rcf);
1551  } else if (d->fName == "allow") {
1552  return DoDirectiveAllow(val, cfg, rcf);
1553  } else if (d->fName == "allowedgroups") {
1554  return DoDirectiveAllowedGroups(val, cfg, rcf);
1555  } else if (d->fName == "allowedusers") {
1556  return DoDirectiveAllowedUsers(val, cfg, rcf);
1557  } else if (d->fName == "role") {
1558  return DoDirectiveRole(val, cfg, rcf);
1559  } else if (d->fName == "multiuser") {
1560  return DoDirectiveMultiUser(val, cfg, rcf);
1561  } else if (d->fName == "port") {
1562  return DoDirectivePort(val, cfg, rcf);
1563  } else if (d->fName == "datadir") {
1564  return DoDirectiveDataDir(val, cfg, rcf);
1565  } else if (d->fName == "datasetsrc") {
1566  return DoDirectiveDataSetSrc(val, cfg, rcf);
1567  } else if (d->fName == "rootd") {
1568  return DoDirectiveRootd(val, cfg, rcf);
1569  } else if (d->fName == "rootdallow") {
1570  return DoDirectiveRootdAllow(val, cfg, rcf);
1571  } else if (d->fName == "xrd.protocol") {
1572  return DoDirectivePort(val, cfg, rcf);
1573  } else if (d->fName == "filterlibpaths") {
1574  return DoDirectiveFilterLibPaths(val, cfg, rcf);
1575  } else if (d->fName == "xrootd") {
1576  return DoDirectiveXrootd(val, cfg, rcf);
1577  }
1578  TRACE(XERR, "unknown directive: " << d->fName);
1579  return -1;
1580 }
1581 
1582 ////////////////////////////////////////////////////////////////////////////////
1583 /// Scan the config file for tracing settings
1584 
1585 int XrdProofdManager::DoDirectiveTrace(char *val, XrdOucStream *cfg, bool)
1586 {
1587  XPDLOC(ALL, "Manager::DoDirectiveTrace")
1588 
1589  if (!val || !cfg)
1590  // undefined inputs
1591  return -1;
1592 
1593  // Specifies tracing options. This works by levels and domains.
1594  //
1595  // Valid keyword levels are:
1596  // err trace errors [on]
1597  // req trace protocol requests [on]*
1598  // dbg trace details about actions [off]
1599  // hdbg trace more details about actions [off]
1600  // Special forms of 'dbg' (always on if 'dbg' is required) are:
1601  // login trace details about login requests [on]*
1602  // fork trace proofserv forks [on]*
1603  // mem trace mem buffer manager [off]
1604  //
1605  // Valid keyword domains are:
1606  // rsp server replies [off]
1607  // aux aux functions [on]
1608  // cmgr client manager [on]
1609  // smgr session manager [on]
1610  // nmgr network manager [on]
1611  // pmgr priority manager [on]
1612  // gmgr group manager [on]
1613  // sched details about scheduling [on]
1614  //
1615  // Global switches:
1616  // all or dump full tracing of everything
1617  //
1618  // Defaults are shown in brackets; '*' shows the default when the '-d'
1619  // option is passed on the command line. Each option may be
1620  // optionally prefixed by a minus sign to turn off the setting.
1621  // Order matters: 'all' in last position enables everything; in first
1622  // position is corrected by subsequent settings
1623  //
1624  while (val && val[0]) {
1625  bool on = 1;
1626  if (val[0] == '-') {
1627  on = 0;
1628  val++;
1629  }
1630  if (!strcmp(val, "err")) {
1631  TRACESET(XERR, on);
1632  } else if (!strcmp(val, "req")) {
1633  TRACESET(REQ, on);
1634  } else if (!strcmp(val, "dbg")) {
1635  TRACESET(DBG, on);
1636  TRACESET(LOGIN, on);
1637  TRACESET(FORK, on);
1638  TRACESET(MEM, on);
1639  } else if (!strcmp(val, "login")) {
1640  TRACESET(LOGIN, on);
1641  } else if (!strcmp(val, "fork")) {
1642  TRACESET(FORK, on);
1643  } else if (!strcmp(val, "mem")) {
1644  TRACESET(MEM, on);
1645  } else if (!strcmp(val, "hdbg")) {
1646  TRACESET(HDBG, on);
1647  TRACESET(DBG, on);
1648  TRACESET(LOGIN, on);
1649  TRACESET(FORK, on);
1650  TRACESET(MEM, on);
1651  } else if (!strcmp(val, "rsp")) {
1652  TRACESET(RSP, on);
1653  } else if (!strcmp(val, "aux")) {
1654  TRACESET(AUX, on);
1655  } else if (!strcmp(val, "cmgr")) {
1656  TRACESET(CMGR, on);
1657  } else if (!strcmp(val, "smgr")) {
1658  TRACESET(SMGR, on);
1659  } else if (!strcmp(val, "nmgr")) {
1660  TRACESET(NMGR, on);
1661  } else if (!strcmp(val, "pmgr")) {
1662  TRACESET(PMGR, on);
1663  } else if (!strcmp(val, "gmgr")) {
1664  TRACESET(GMGR, on);
1665  } else if (!strcmp(val, "sched")) {
1666  TRACESET(SCHED, on);
1667  } else if (!strcmp(val, "all") || !strcmp(val, "dump")) {
1668  // Everything
1669  TRACE(ALL, "Setting trace: " << on);
1670  XrdProofdTrace->What = (on) ? TRACE_ALL : 0;
1671  }
1672 
1673  // Next
1674  val = cfg->GetWord();
1675  }
1676 
1677  return 0;
1678 }
1679 
1680 ////////////////////////////////////////////////////////////////////////////////
1681 /// Process 'groupfile' directive
1682 
1683 int XrdProofdManager::DoDirectiveGroupfile(char *val, XrdOucStream *cfg, bool rcf)
1684 {
1685  XPDLOC(ALL, "Manager::DoDirectiveGroupfile")
1686 
1687  if (!val)
1688  // undefined inputs
1689  return -1;
1690 
1691  // Check deprecated 'if' directive
1692  if (Host() && cfg)
1693  if (XrdProofdAux::CheckIf(cfg, Host()) == 0)
1694  return 0;
1695 
1696  // Defines file with the group info
1697  if (rcf) {
1699  } else if (fGroupsMgr) {
1700  TRACE(XERR, "groups manager already initialized: ignoring ");
1701  return -1;
1702  }
1704  fGroupsMgr->Config(val);
1705  return 0;
1706 }
1707 
1708 ////////////////////////////////////////////////////////////////////////////////
1709 /// Process 'maxoldlogs' directive
1710 
1711 int XrdProofdManager::DoDirectiveMaxOldLogs(char *val, XrdOucStream *cfg, bool)
1712 {
1713  if (!val)
1714  // undefined inputs
1715  return -1;
1716 
1717  // Check deprecated 'if' directive
1718  if (Host() && cfg)
1719  if (XrdProofdAux::CheckIf(cfg, Host()) == 0)
1720  return 0;
1721 
1722  // Max number of sessions per user
1723  int maxoldlogs = strtol(val, 0, 10);
1725  return 0;
1726 }
1727 
1728 ////////////////////////////////////////////////////////////////////////////////
1729 /// Process 'allow' directive
1730 
1731 int XrdProofdManager::DoDirectiveAllow(char *val, XrdOucStream *cfg, bool)
1732 {
1733  if (!val)
1734  // undefined inputs
1735  return -1;
1736 
1737  // Check deprecated 'if' directive
1738  if (Host() && cfg)
1739  if (XrdProofdAux::CheckIf(cfg, Host()) == 0)
1740  return 0;
1741 
1742  // Masters allowed to connect
1743  fMastersAllowed.push_back(new XrdOucString(val));
1744  return 0;
1745 }
1746 
1747 ////////////////////////////////////////////////////////////////////////////////
1748 /// Process 'allowedgroups' directive
1749 
1750 int XrdProofdManager::DoDirectiveAllowedGroups(char *val, XrdOucStream *cfg, bool)
1751 {
1752  if (!val)
1753  // undefined inputs
1754  return -1;
1755 
1756  // Check deprecated 'if' directive
1757  if (Host() && cfg)
1758  if (XrdProofdAux::CheckIf(cfg, Host()) == 0)
1759  return 0;
1760 
1761  // We are in controlled mode
1763 
1764  // Input list (comma separated) of UNIX groups allowed to connect
1765  XrdOucString s = val;
1766  int from = 0;
1767  XrdOucString grp, gid;
1768  XrdProofGI gi;
1769  while ((from = s.tokenize(grp, from, ',')) != STR_NPOS) {
1770  int st = 1;
1771  if (grp.beginswith('-')) {
1772  st = 0;
1773  grp.erasefromstart(1);
1774  }
1775  // Unix or Proof group ?
1776  if (XrdProofdAux::GetGroupInfo(grp.c_str(), gi) == 0) {
1777  // Unix: add name and id
1778  gid.form("%d", (int) gi.fGid);
1779  fAllowedGroups.Add(gid.c_str(), new int(st));
1780  }
1781  // Add it to the list
1782  fAllowedGroups.Add(grp.c_str(), new int(st));
1783  }
1784 
1785  // Done
1786  return 0;
1787 }
1788 
1789 ////////////////////////////////////////////////////////////////////////////////
1790 /// Process 'allowedusers' directive
1791 
1792 int XrdProofdManager::DoDirectiveAllowedUsers(char *val, XrdOucStream *cfg, bool)
1793 {
1794  if (!val)
1795  // undefined inputs
1796  return -1;
1797 
1798  // Check deprecated 'if' directive
1799  if (Host() && cfg)
1800  if (XrdProofdAux::CheckIf(cfg, Host()) == 0)
1801  return 0;
1802 
1803  // We are in controlled mode
1805 
1806  // Input list (comma separated) of users allowed to connect
1807  XrdOucString s = val;
1808  int from = 0;
1809  XrdOucString usr;
1810  XrdProofUI ui;
1811  while ((from = s.tokenize(usr, from, ',')) != STR_NPOS) {
1812  int st = 1;
1813  if (usr.beginswith('-')) {
1814  st = 0;
1815  usr.erasefromstart(1);
1816  }
1817  // Add to the list; we will check later on the existence of the
1818  // user in the password file, depending on the 'multiuser' settings
1819  fAllowedUsers.Add(usr.c_str(), new int(st));
1820  }
1821 
1822  // Done
1823  return 0;
1824 }
1825 
1826 ////////////////////////////////////////////////////////////////////////////////
1827 /// Process 'role' directive
1828 
1829 int XrdProofdManager::DoDirectiveRole(char *val, XrdOucStream *cfg, bool)
1830 {
1831  if (!val)
1832  // undefined inputs
1833  return -1;
1834 
1835  // Check deprecated 'if' directive
1836  if (Host() && cfg)
1837  if (XrdProofdAux::CheckIf(cfg, Host()) == 0)
1838  return 0;
1839 
1840  // Role this server
1841  XrdOucString tval(val);
1842  if (tval == "supermaster") {
1844  fSuperMst = 1;
1845  } else if (tval == "master") {
1847  } else if (tval == "submaster") {
1849  } else if (tval == "worker") {
1851  } else if (tval == "any") {
1853  }
1854 
1855  return 0;
1856 }
1857 
1858 ////////////////////////////////////////////////////////////////////////////////
1859 /// Process 'xrd.protocol' directive to find the port
1860 
1861 int XrdProofdManager::DoDirectivePort(char *val, XrdOucStream *, bool)
1862 {
1863  if (!val)
1864  // undefined inputs
1865  return -1;
1866 
1867  XrdOucString port(val);
1868  if (port.beginswith("xproofd:")) {
1869  port.replace("xproofd:", "");
1870  }
1871  if (port.length() > 0 && port.isdigit()) {
1872  fPort = strtol(port.c_str(), 0, 10);
1873  }
1874  fPort = (fPort < 0) ? XPD_DEF_PORT : fPort;
1875 
1876  return 0;
1877 }
1878 
1879 ////////////////////////////////////////////////////////////////////////////////
1880 /// Process 'multiuser' directive
1881 
1882 int XrdProofdManager::DoDirectiveMultiUser(char *val, XrdOucStream *cfg, bool)
1883 {
1884  XPDLOC(ALL, "Manager::DoDirectiveMultiUser")
1885 
1886  if (!val)
1887  // undefined inputs
1888  return -1;
1889 
1890  // Multi-user option
1891  int mu = strtol(val, 0, 10);
1892  fMultiUser = (mu == 1) ? 1 : fMultiUser;
1893 
1894  // Check if we need to change the working dir template
1895  val = cfg->GetWord();
1896  if (val) fMUWorkDir = val;
1897 
1898  TRACE(DBG, "fMultiUser: "<< fMultiUser << " work dir template: " << fMUWorkDir);
1899 
1900  return 0;
1901 }
1902 
1903 ////////////////////////////////////////////////////////////////////////////////
1904 /// Process 'datasetsrc' directive
1905 
1906 int XrdProofdManager::DoDirectiveDataSetSrc(char *val, XrdOucStream *cfg, bool)
1907 {
1908  if (!val)
1909  // undefined inputs
1910  return -1;
1911 
1912  // URL for this source
1913  XrdOucString type(val), url, opts, obscure;
1914  bool rw = 0, local = 0, goodsrc = 1;
1915  char *nxt = 0;
1916  while ((nxt = cfg->GetWord())) {
1917  if (!strcmp(nxt, "rw=1") || !strcmp(nxt, "rw:1")) {
1918  rw = 1;
1919  } else if (!strncmp(nxt, "url:", 4)) {
1920  url = nxt + 4;
1921  XrdClientUrlInfo u(url);
1922  if (u.Proto == "" && u.HostWPort == "") local = 1;
1923  } else if (!strncmp(nxt, "opt:", 4)) {
1924  opts = nxt + 4;
1925  } else {
1926  obscure += nxt;
1927  obscure += " ";
1928  }
1929  }
1930 
1931  // Add to the list
1932  if (goodsrc) {
1933  // If first local, add it in front
1934  std::list<XrdProofdDSInfo *>::iterator ii = fDataSetSrcs.begin();
1935  bool haslocal = 0;
1936  for (ii = fDataSetSrcs.begin(); ii != fDataSetSrcs.end(); ii++) {
1937  if ((*ii)->fLocal) {
1938  haslocal = 1;
1939  break;
1940  }
1941  }
1942  // Default options
1943  if (opts.length() <= 0) {
1944  opts = rw ? "Ar:Av:" : "-Ar:-Av:";
1945  }
1946  XrdProofdDSInfo *dsi = new XrdProofdDSInfo(type.c_str(), url.c_str(),
1947  local, rw, opts.c_str(), obscure.c_str());
1948  if (haslocal || !local) {
1949  fDataSetSrcs.push_back(dsi);
1950  } else {
1951  fDataSetSrcs.push_front(dsi);
1952  }
1953  }
1954  return 0;
1955 }
1956 
1957 ////////////////////////////////////////////////////////////////////////////////
1958 /// Process 'datadir' directive
1959 
1960 int XrdProofdManager::DoDirectiveDataDir(char *val, XrdOucStream *cfg, bool)
1961 {
1962  if (!val)
1963  // undefined inputs
1964  return -1;
1965 
1966  // Data directory and write permissions
1967  fDataDir = val;
1968  fDataDirOpts = "";
1969  fDataDirUrlOpts = "";
1970  XrdOucString opts;
1971  char *nxt = 0;
1972  while ((nxt = cfg->GetWord()) && (opts.length() == 0)) {
1973  opts = nxt;
1974  }
1975  if (opts.length() > 0) fDataDirOpts = opts;
1976  // Check if URL type options have been spcified in the main url
1977  int iq = STR_NPOS;
1978  if ((iq = fDataDir.rfind('?')) != STR_NPOS) {
1979  fDataDirUrlOpts.assign(fDataDir, iq + 1);
1980  fDataDir.erase(iq);
1981  }
1982 
1983  // Done
1984  return 0;
1985 }
1986 
1987 ////////////////////////////////////////////////////////////////////////////////
1988 /// Process 'xrootd' directive
1989 /// xpd.xrootd [path/]libXrdXrootd.so
1990 
1991 int XrdProofdManager::DoDirectiveXrootd(char *val, XrdOucStream *, bool)
1992 {
1993  XPDLOC(ALL, "Manager::DoDirectiveXrootd")
1994 
1995  if (!val)
1996  // undefined inputs
1997  return -1;
1998  TRACE(ALL, "val: "<< val);
1999  // Check version (v3 does not have the plugin, loading v4 may lead to problems)
2000  if (XrdMajorVNUM(XrdVNUMBER) < 4) {
2001  TRACE(ALL, "WARNING: built against an XRootD version without libXrdXrootd.so :");
2002  TRACE(ALL, "WARNING: loading external " << val << " may lead to incompatibilities");
2003  }
2004 
2005  fXrootdLibPath = val;
2006 
2007  // Done
2008  return 0;
2009 }
2010 
2011 ////////////////////////////////////////////////////////////////////////////////
2012 /// Process 'rootd' directive
2013 /// xpd.rootd deny|allow [rootsys:<tag>] [path:abs-path/] [mode:ro|rw]
2014 /// [auth:none|full] [other_rootd_args]
2015 
2016 int XrdProofdManager::DoDirectiveRootd(char *val, XrdOucStream *cfg, bool)
2017 {
2018  XPDLOC(ALL, "Manager::DoDirectiveRootd")
2019 
2020  if (!val)
2021  // undefined inputs
2022  return -1;
2023 
2024  // Rebuild arguments list
2025  fRootdArgs.clear();
2027 
2028  TRACE(ALL, "val: "<< val);
2029 
2030  // Parse directive
2031  XrdOucString mode("ro"), auth("none"), fork("0");
2032  bool denied = 1;
2033  char *nxt = val;
2034  do {
2035  if (!strcmp(nxt, "deny") || !strcmp(nxt, "disable") || !strcmp(nxt, "off")) {
2036  denied = 1;
2037  fRootdExe = "";
2038  } else if (!strcmp(nxt, "allow") || !strcmp(nxt, "enable") || !strcmp(nxt, "on")) {
2039  denied = 0;
2040  fRootdExe = "<>";
2041  TRACE(ALL, "Use of this directive is deprecated: use xpd.xrootd instead");
2042  } else if (!strncmp(nxt, "mode:", 5)) {
2043  mode = nxt + 5;
2044  } else if (!strncmp(nxt, "auth:", 5)) {
2045  auth = nxt + 5;
2046  } else if (!strncmp(nxt, "fork:", 5)) {
2047  fork = nxt + 5;
2048  } else {
2049  // Assume rootd argument
2050  fRootdArgs.push_back(XrdOucString(nxt));
2051  }
2052  } while ((nxt = cfg->GetWord()));
2053 
2054  if (!denied) {
2055  // If no exec given assume 'rootd' in the default path
2056  if (fRootdExe.length() <= 0) fRootdExe = "<>";
2057  // Add mandatory arguments
2058  fRootdArgs.push_back(XrdOucString("-i"));
2059  fRootdArgs.push_back(XrdOucString("-nologin"));
2060  if (mode == "ro") fRootdArgs.push_back(XrdOucString("-r"));
2061  if (auth == "none") fRootdArgs.push_back(XrdOucString("-noauth"));
2062  fRootdFork = (fork == "1" || fork == "yes") ? 1 : 0;
2063  } else {
2064  // Nothing else to do, if denied
2065  return 0;
2066  }
2067 
2068  // Build the argument list
2069  fRootdArgsPtrs = new const char *[fRootdArgs.size() + 2];
2070  fRootdArgsPtrs[0] = fRootdExe.c_str();
2071  int i = 1;
2072  std::list<XrdOucString>::iterator ia = fRootdArgs.begin();
2073  while (ia != fRootdArgs.end()) {
2074  fRootdArgsPtrs[i] = (*ia).c_str();
2075  i++; ia++;
2076  }
2077  fRootdArgsPtrs[fRootdArgs.size() + 1] = 0;
2078 
2079  // Done
2080  return 0;
2081 }
2082 
2083 ////////////////////////////////////////////////////////////////////////////////
2084 /// Process 'rootdallow' directive
2085 /// xpd.rootdallow host1,host2 host3
2086 /// Host names may contain the wild card '*'
2087 
2088 int XrdProofdManager::DoDirectiveRootdAllow(char *val, XrdOucStream *cfg, bool)
2089 {
2090  XPDLOC(ALL, "Manager::DoDirectiveRootdAllow")
2091 
2092  if (!val)
2093  // undefined inputs
2094  return -1;
2095 
2096  TRACE(ALL, "Use of this and 'xpd.rootd' directives is deprecated: use xpd.xrootd instead");
2097 
2098  TRACE(ALL, "val: "<< val);
2099 
2100  // Parse directive
2101  XrdOucString hosts, h;
2102  char *nxt = val;
2103  do {
2104  hosts = nxt;
2105  int from = 0;
2106  while ((from = hosts.tokenize(h, from, ',')) != -1) {
2107  if (h.length() > 0) fRootdAllow.push_back(h);
2108  }
2109  } while ((nxt = cfg->GetWord()));
2110 
2111  // Done
2112  return 0;
2113 }
2114 
2115 ////////////////////////////////////////////////////////////////////////////////
2116 /// Process 'filterlibpaths' directive
2117 /// xpd.filterlibpaths 1|0 [path1,path2 path3 path4 ...]
2118 
2119 int XrdProofdManager::DoDirectiveFilterLibPaths(char *val, XrdOucStream *cfg, bool)
2120 {
2121  XPDLOC(ALL, "Manager::DoDirectiveRemoveLibPaths")
2122 
2123  if (!val)
2124  // undefined inputs
2125  return -1;
2126 
2127  // Rebuild arguments list
2128  fLibPathsToRemove.Purge();
2129 
2130  TRACE(ALL, "val: "<< val);
2131 
2132  // Whether to remove ROOT lib paths before adding the effective one
2133  fRemoveROOTLibPaths = (!strcmp(val, "1") || !strcmp(val, "yes")) ? 1 : 0;
2134  if (fRemoveROOTLibPaths)
2135  TRACE(ALL, "Filtering out ROOT lib paths from "<<XPD_LIBPATH);
2136 
2137  // Parse the rest, if any
2138  char *nxt = 0;
2139  while ((nxt = cfg->GetWord())) {
2140  XrdOucString pps(nxt), p;
2141  int from = 0;
2142  while ((from = pps.tokenize(p, from, ',')) != -1) {
2143  if (p.length() > 0) {
2144  fLibPathsToRemove.Add(p.c_str(), 0, 0, Hash_data_is_key);
2145  TRACE(ALL, "Filtering out from "<<XPD_LIBPATH<<" lib path '"<<p<<"'");
2146  }
2147  }
2148  }
2149 
2150  // Done
2151  return 0;
2152 }
2153 
2154 ////////////////////////////////////////////////////////////////////////////////
2155 /// Check if 'host' is allowed to access files via rootd
2156 
2157 bool XrdProofdManager::IsRootdAllowed(const char *host)
2158 {
2159  XPDLOC(ALL, "Manager::IsRootdAllowed")
2160 
2161  // Check if access is controlled
2162  if (fRootdAllow.size() <= 0) return 1;
2163 
2164  // Need an host name
2165  if (!host || strlen(host) <= 0) return 0;
2166 
2167  TRACE(DBG, "checking host: "<< host);
2168 
2169  XrdOucString h(host);
2170  std::list<XrdOucString>::iterator ia = fRootdAllow.begin();
2171  while (ia != fRootdAllow.end()) {
2172  if (h.matches((*ia).c_str(), '*') > 0) return 1;
2173  ia++;
2174  }
2175 
2176  // Done
2177  return 0;
2178 }
2179 
2180 ////////////////////////////////////////////////////////////////////////////////
2181 /// Process manager request
2182 
2184 {
2185  XPDLOC(ALL, "Manager::Process")
2186 
2187  int rc = 0;
2188  XPD_SETRESP(p, "Process");
2189 
2190  TRACEP(p, REQ, "req id: " << p->Request()->header.requestid << " (" <<
2191  XrdProofdAux::ProofRequestTypes(p->Request()->header.requestid) << ")");
2192 
2193  // If the user is not yet logged in, restrict what the user can do
2194  if (!p->Status() || !(p->Status() & XPD_LOGGEDIN)) {
2195  switch (p->Request()->header.requestid) {
2196  case kXP_auth:
2197  return fClientMgr->Auth(p);
2198  case kXP_login:
2199  return fClientMgr->Login(p);
2200  default:
2201  TRACEP(p, XERR, "invalid request: " << p->Request()->header.requestid);
2202  response->Send(kXR_InvalidRequest, "Invalid request; user not logged in");
2203  return p->Link()->setEtext("protocol sequence error 1");
2204  }
2205  }
2206 
2207  // Once logged-in, the user can request the real actions
2208  XrdOucString emsg;
2209  switch (p->Request()->header.requestid) {
2210  case kXP_admin: {
2211  int type = ntohl(p->Request()->proof.int1);
2212  return fAdmin->Process(p, type);
2213  }
2214  case kXP_readbuf:
2215  return fNetMgr->ReadBuffer(p);
2216  case kXP_create:
2217  case kXP_destroy:
2218  case kXP_attach:
2219  case kXP_detach:
2220  return fSessionMgr->Process(p);
2221  default:
2222  emsg += "Invalid request: ";
2223  emsg += p->Request()->header.requestid;
2224  break;
2225  }
2226 
2227  // Notify invalid request
2228  response->Send(kXR_InvalidRequest, emsg.c_str());
2229 
2230  // Done
2231  return 0;
2232 }
int Auth(XrdProofdProtocol *xp)
Analyse client authentication info.
XrdProofdProofServMgr * fSessionMgr
const char * WorkDir() const
static int FillKeyValues(const char *k, int *d, void *s)
Add the key value in the string passed via the void argument.
const char * Export(const char *ord=0)
Export current content in a form understood by parsing algorithms inside the PROOF session...
int DoDirectiveXrootd(char *, XrdOucStream *, bool)
Process &#39;xrootd&#39; directive xpd.xrootd [path/]libXrdXrootd.so.
int DoDirectiveRootdAllow(char *, XrdOucStream *, bool)
Process &#39;rootdallow&#39; directive xpd.rootdallow host1,host2 host3 Host names may contain the wild card ...
int pw_uid
Definition: TWinNTSystem.h:52
#define XPD_LOGGEDIN
void SetLogDir(const char *d)
Set the log dir.
Definition: XrdROOT.cxx:334
#define XPD_LIBPATH
int DoDirectiveFilterLibPaths(char *, XrdOucStream *, bool)
Process &#39;filterlibpaths&#39; directive xpd.filterlibpaths 1|0 [path1,path2 path3 path4 ...
#define kXPD_TopMaster
XrdProofdClientMgr * fClientMgr
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t mid
Definition: TRolke.cxx:630
int GetWorkers(XrdOucString &workers, XrdProofdProofServ *, const char *)
Get a list of workers from the available resource broker.
XrdOucString fDataDir
#define TRACING(x)
XrdProofdProofServMgr * SessionMgr() const
int DoDirectiveRole(char *, XrdOucStream *, bool)
Process &#39;role&#39; directive.
int Process(XrdProofdProtocol *p)
Process manager request.
XrdOucString fSuperUsers
const double pi
std::list< XrdOucString * > fMastersAllowed
static int GetUserInfo(const char *usr, XrdProofUI &ui)
Get information about user &#39;usr&#39; in a thread safe way.
int gr_gid
Definition: TWinNTSystem.h:64
XrdLink * Link() const
const char * Group() const
XrdROOT * DefaultVersion() const
Definition: XrdROOT.h:118
#define kXPD_OpModeControlled
void AddWorker(const char *o, XrdProofWorker *w)
Add a worker assigned to this session with label &#39;o&#39;.
int Process(XrdProofdProtocol *p, int type)
Process admin request.
int DoDirectiveClass(XrdProofdDirective *, char *val, XrdOucStream *cfg, bool rcf)
Generic class directive processor.
TH1 * h
Definition: legend2.C:5
static void SetWorkdir(const char *wdir)
int Config(bool rcf=0)
Run configuration and parse the entered config directives.
#define TRACE(Flag, Args)
Definition: TGHtml.h:124
const char *const XPD_GW_QueryEnqueued
XrdROOTMgr * fROOTMgr
virtual ~XrdProofdManager()
Destructor.
int Process(XrdProofdProtocol *p)
Process manager request.
R__EXTERN XrdOucTrace * XrdProofdTrace
int DoDirectiveInt(XrdProofdDirective *, char *val, XrdOucStream *cfg, bool rcf)
Process directive for an integer.
XrdOucString fPoolURL
XrdOucHash< int > fAllowedUsers
XrdProtocol * fXrootd
XrdOucString HostWPort
XrdProofdManager(char *parms, XrdProtocol_Config *pi, XrdSysError *edest)
Constructor.
const char * GetCfgFile() const
XrdScheduler * fSched
bool ChangeOwn() const
kXR_int16 SrvProtVers() const
Definition: XrdROOT.h:82
virtual int GetWorkers(XrdProofdProofServ *xps, std::list< XrdProofWorker *> *, const char *)
Get a list of workers that can be used by session &#39;xps&#39;.
XrdSysRecMutex fMutex
XrdProofdPriorityMgr * fPriorityMgr
struct ClientRequestHdr header
#define SafeDelete(p)
Definition: RConfig.h:507
int DoDirectiveRootd(char *, XrdOucStream *, bool)
Process &#39;rootd&#39; directive xpd.rootd deny|allow [rootsys:<tag>] [path:abs-path/] [mode:ro|rw] [auth:no...
XrdProofSched * LoadScheduler()
Load PROOF scheduler.
XrdProofGroupMgr * fGroupsMgr
int DoDirective(XrdProofdDirective *d, char *val, XrdOucStream *cfg, bool rcf)
Update the priorities of the active sessions.
void AddProofServ(XrdProofdProofServ *xps)
XrdProofGroupMgr * GroupsMgr() const
const char * User() const
XrdOucString fEffectiveUser
#define SafeDelArray(x)
Definition: XrdProofdAux.h:338
const char * Name() const
Definition: XrdProofSched.h:98
XrdOucString fStageReqRepo
bool WorkerUsrCfg() const
int DoDirectiveAllowedGroups(char *, XrdOucStream *, bool)
Process &#39;allowedgroups&#39; directive.
void ExportWorkers(XrdOucString &wrks)
Export the assigned workers in the format understood by proofserv.
static int EUidAtStartup()
XrdOucString fUser
Definition: XrdProofdAux.h:40
XrdSysError * fEDest
XrdOucString fMUWorkDir
#define XPDLOC(d, x)
int Login(XrdProofdProtocol *xp)
Process a login request.
virtual int Config(bool rcf=0)
Configure this instance using the content of file &#39;cfn&#39;.
int DoDirectiveTrace(char *, XrdOucStream *, bool)
Scan the config file for tracing settings.
int DoDirectiveDataDir(char *, XrdOucStream *, bool)
Process &#39;datadir&#39; directive.
int Config(bool rcf=0)
Run configuration and parse the entered config directives.
bool CheckMaster(const char *m)
Check if master &#39;m&#39; is allowed to connect to this host.
#define XPDERR(x)
XrdProofSched * fProofSched
XrdOucString fBareLibPath
#define TRACESET(act, on)
static int RemoveInvalidUsers(const char *k, int *, void *s)
Add the key value in the string passed via the void argument.
#define kXPD_OpModeOpen
int DoDirectiveAllow(char *, XrdOucStream *, bool)
Process &#39;allow&#39; directive.
static const char * ProofRequestTypes(int type)
Translates the proof request type in a human readable string.
std::list< XrdProofdDSInfo * > fDataSetSrcs
XrdROOT * GetVersion(const char *tag)
Return pointer to the ROOT version corresponding to &#39;tag&#39; or 0 if not found.
Definition: XrdROOT.cxx:730
#define XrdSysMutexHelper
Definition: XrdSysToOuc.h:17
std::list< XrdOucString > fRootdArgs
struct XPClientProofRequest proof
bool IsRootdAllowed(const char *host)
Check if &#39;host&#39; is allowed to access files via rootd.
const char * Host() const
int CheckUser(const char *usr, const char *grp, XrdProofUI &ui, XrdOucString &e, bool &su)
Check if the user is allowed to use the system Return 0 if OK, -1 if not.
#define XrdSysError
Definition: XpdSysError.h:8
XrdOucString fHost
XrdOucString fDataDirUrlOpts
#define XrdSysPlugin
Definition: XpdSysPlugin.h:8
#define TRACEP(p, act, x)
TMarker * m
Definition: textangle.C:8
int Config(bool rcf=0)
Run configuration and parse the entered config directives.
XrdOucString fNamespace
#define XpdBadPGuard(g, u)
Definition: XrdProofdAux.h:368
XrdProtocol_Config * fPi
rpdunixsrv * fRootdUnixSrv
#define TRACE_ALL
XrdOucString fRootdExe
XrdOucString fImage
XrdOucString Proto
int ReadBuffer(XrdProofdProtocol *p)
Process a readbuf request.
#define kXPD_AnyServer
static int GetGroupInfo(const char *grp, XrdProofGI &gi)
Get information about group with &#39;gid&#39; in a thread safe way.
virtual bool IsValid()
Definition: XrdProofSched.h:96
void RegisterDirectives()
Register directives for configuration.
static int AssertDir(const char *path, XrdProofUI ui, bool changeown)
Make sure that &#39;path&#39; exists and is owned by the entity described by &#39;ui&#39;.
int Config(bool rcf=0)
Run configuration and parse the entered config directives.
#define XPDFORM
Definition: XrdProofdAux.h:381
#define kXPD_Worker
XrdOucHash< int > fAllowedGroups
const char ** fRootdArgsPtrs
static int CheckIf(XrdOucStream *s, const char *h)
Check existence and match condition of an &#39;if&#39; directive If none (valid) is found, return -1.
int ResolveKeywords(XrdOucString &s, XrdProofdClient *pcl)
Resolve special keywords in &#39;s&#39; for client &#39;pcl&#39;.
XrdOucString fDataSetExp
static char * Expand(char *p)
Expand path &#39;p&#39; relative to: $HOME if begins with ~/ <user>&#39;s $HOME if begins with ~<user>/ $PWD if d...
int DoDirectiveString(XrdProofdDirective *, char *val, XrdOucStream *cfg, bool rcf)
Process directive for a string.
std::list< XrdOucString > fRootdAllow
int Config(bool rcf=0)
Run configuration and parse the entered config directives.
Definition: XrdROOT.cxx:356
XrdOucHash< XrdOucString > fLibPathsToRemove
int type
Definition: TGX11.cxx:120
#define SafeFree(x)
Definition: XrdProofdAux.h:341
XrdROOT * ROOT() const
int Config(bool rcf=0)
Run configuration and parse the entered config directives.
int Config(bool rcf=0)
Run configuration and parse the entered config directives.
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
XrdProtocol * LoadXrootd(char *parms, XrdProtocol_Config *pi, XrdSysError *edest)
Load the Xrootd protocol, if required.
static int ChangeMod(const char *path, unsigned int mode)
Change the permission mode of &#39;path&#39; to &#39;mode&#39;.
XrdOucString fDataDirOpts
XrdProofdNetMgr * fNetMgr
XrdProofdAdmin * fAdmin
int DoDirectiveGroupfile(char *, XrdOucStream *, bool)
Process &#39;groupfile&#39; directive.
#define XPD_SETRESP(p, x)
int pw_gid
Definition: TWinNTSystem.h:53
int DoDirectivePort(char *, XrdOucStream *, bool)
Process &#39;xrd.protocol&#39; directive to find the port.
int DoDirectiveMultiUser(char *, XrdOucStream *, bool)
Process &#39;multiuser&#39; directive.
XrdProtocol *(* XrdProtocolLoader_t)(const char *, char *, XrdProtocol_Config *)
XrdOucString fWorkDir
XrdOucString fName
Definition: XrdProofdAux.h:111
XrdProofSched *(* XrdProofSchedLoader_t)(const char *, XrdProofdManager *, XrdProofGroupMgr *, const char *, XrdSysError *)
void Dump()
Dump status.
XrdOucString fHomeDir
Definition: XrdProofdAux.h:42
#define XPD_DEF_PORT
void CheckLogFileOwnership()
Make sure that the log file belongs to the original effective user.
XrdOucString fOrd
XrdProofUI UI() const
const char * CfgFile() const
#define NULL
Definition: Rtypes.h:82
const char * proto
Definition: civetweb.c:11652
int DoDirectiveDataSetSrc(char *, XrdOucStream *, bool)
Process &#39;datasetsrc&#39; directive.
XrdOucString fXrootdLibPath
#define kXPD_Master
int * iq
Definition: THbookFile.cxx:86
static int ChangeOwn(const char *path, XrdProofUI ui)
Change the ownership of &#39;path&#39; to the entity described by &#39;ui&#39;.
int Config(const char *fn)
(Re-)configure the group info using the file &#39;fn&#39;.
static void SetMaxOldSessions(int mxses)
int DoDirectiveMaxOldLogs(char *, XrdOucStream *, bool)
Process &#39;maxoldlogs&#39; directive.
XrdOucString fSockPathDir
XrdOucString fAdminPath
bool ValidateLocalDataSetSrc(XrdOucString &url, bool &local)
Validate local dataset src at URL (check the URL and make the relevant directories).
const char * BinDir() const
Definition: XrdROOT.h:66
void * XrdProofdManagerCron(void *p)
This is an endless loop to periodically check the system.
virtual int Config(bool rcf=0)
static char * skip(char **buf, const char *delimiters)
Definition: civetweb.c:2039
void Print(const char *grp)
Return a string describing the group.
char name[80]
Definition: TGX11.cxx:109
void Register(const char *dname, XrdProofdDirective *d)
XPClientRequest * Request() const
if(line.BeginsWith("/*"))
Definition: HLFactory.cxx:443
int DoDirectiveAllowedUsers(char *, XrdOucStream *, bool)
Process &#39;allowedusers&#39; directive.
XrdOucString fTMPdir
char ** gr_mem
Definition: TWinNTSystem.h:65
XrdOucString fHost