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