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