Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
XrdProofdClientMgr.cxx
Go to the documentation of this file.
1// @(#)root/proofd:$Id$
2// Author: G. Ganis Jan 2008
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// XrdProofdClientMgr //
15// //
16// Author: G. Ganis, CERN, 2008 //
17// //
18// Class managing clients. //
19// //
20//////////////////////////////////////////////////////////////////////////
21#include "XrdProofdPlatform.h"
22
23#include "XrdProofdXrdVers.h"
24#if ROOTXRDVERS < ROOT_OldXrdOuc
25# define XPD_LOG_01 OUC_LOG_01
26#else
27# define XPD_LOG_01 SYS_LOG_01
28#endif
29
30#include "XpdSysError.h"
31
32#include "Xrd/XrdBuffer.hh"
33#ifdef ROOT_XrdFour
34#include "XrdNet/XrdNetAddrInfo.hh"
35#endif
36#include "XrdOuc/XrdOucErrInfo.hh"
37#include "XrdOuc/XrdOucStream.hh"
38#include "XrdSec/XrdSecInterface.hh"
39#include "XrdSys/XrdSysPlugin.hh"
40
41#include "XrdProofdClient.h"
42#include "XrdProofdClientMgr.h"
43#include "XrdProofdManager.h"
44#include "XrdProofdProtocol.h"
45#include "XrdProofGroup.h"
46#include "XrdProofdProofServ.h"
48#include "XrdROOT.h"
49
50// Tracing utilities
51#include "XrdProofdTrace.h"
52
54
55// Security handle
56typedef XrdSecService *(*XrdSecServLoader_t)(XrdSysLogger *, const char *cfn);
57
58//--------------------------------------------------------------------------
59//
60// XrdProofdClientCron
61//
62// Client manager thread
63//
64////////////////////////////////////////////////////////////////////////////////
65/// This is an endless loop to check the system periodically or when
66/// triggered via a message in a dedicated pipe
67
69{
70 XPDLOC(CMGR, "ClientCron")
71
74 if (!(mgr)) {
75 TRACE(REQ, "undefined client manager: cannot start");
76 return (void *)0;
77 }
79 if (!(smgr)) {
80 TRACE(REQ, "undefined session manager: cannot start");
81 return (void *)0;
82 }
83
84 // Time of last session check
85 int lastcheck = time(0), ckfreq = mgr->CheckFrequency(), deltat = 0;
86 while(1) {
87 // We wait for processes to communicate a session status change
88 if ((deltat = ckfreq - (time(0) - lastcheck)) <= 0)
89 deltat = ckfreq;
90 int pollRet = mgr->Pipe()->Poll(deltat);
91
92 if (pollRet > 0) {
93 // Read message
94 XpdMsg msg;
95 int rc = 0;
96 if ((rc = mgr->Pipe()->Recv(msg)) != 0) {
97 XPDERR("problems receiving message; errno: "<<-rc);
98 continue;
99 }
100 // Parse type
101 //XrdOucString buf;
103 // obsolete
104 TRACE(XERR, "obsolete type: XrdProofdClientMgr::kClientDisconnect");
105 } else {
106 TRACE(XERR, "unknown type: "<<msg.Type());
107 continue;
108 }
109 } else {
110 // Run regular checks
111 mgr->CheckClients();
112 // Remember when ...
113 lastcheck = time(0);
114 }
115 }
116
117 // Should never come here
118 return (void *)0;
119}
120
121////////////////////////////////////////////////////////////////////////////////
122/// Constructor
123
125 XrdProtocol_Config *pi, XrdSysError *e)
126 : XrdProofdConfig(pi->ConfigFN, e), fSecPlugin(0)
127{
128 XPDLOC(CMGR, "XrdProofdClientMgr")
129
131 fMgr = mgr;
132 fCIA = 0;
133 fNDisconnected = 0;
134 fReconnectTimeOut = 300;
135 // Defaults can be changed via 'clientmgr'
136 fActivityTimeOut = 1200;
137 fCheckFrequency = 60;
138
139 // Init pipe for manager thread
140 if (!fPipe.IsValid()) {
141 TRACE(XERR, "unable to generate the pipe");
142 return;
143 }
144
145 // Configuration directives
147}
148
149////////////////////////////////////////////////////////////////////////////////
150/// Register directives for configuration
151
153{
154 Register("clientmgr", new XrdProofdDirective("clientmgr", this, &DoDirectiveClass));
155 Register("seclib", new XrdProofdDirective("seclib",
156 (void *)&fSecLib, &DoDirectiveString, 0));
157 Register("reconnto", new XrdProofdDirective("reconnto",
159}
160
161////////////////////////////////////////////////////////////////////////////////
162/// Update the priorities of the active sessions.
163
165 char *val, XrdOucStream *cfg, bool rcf)
166{
167 XPDLOC(SMGR, "ClientMgr::DoDirective")
168
169 if (!d)
170 // undefined inputs
171 return -1;
172
173 if (d->fName == "clientmgr") {
174 return DoDirectiveClientMgr(val, cfg, rcf);
175 }
176 TRACE(XERR,"unknown directive: "<<d->fName);
177 return -1;
178}
179
180////////////////////////////////////////////////////////////////////////////////
181/// Process 'clientmgr' directive
182/// eg: xpd.clientmgr checkfq:120 activityto:600
183
184int XrdProofdClientMgr::DoDirectiveClientMgr(char *val, XrdOucStream *cfg, bool)
185{
186 XPDLOC(SMGR, "ClientMgr::DoDirectiveClientMgr")
187
188 if (!val || !cfg)
189 // undefined inputs
190 return -1;
191
192 int checkfq = -1;
193 int activityto = -1;
194
195 while (val) {
196 XrdOucString tok(val);
197 if (tok.beginswith("checkfq:")) {
198 tok.replace("checkfq:", "");
199 checkfq = strtol(tok.c_str(), 0, 10);
200 } else if (tok.beginswith("activityto:")) {
201 tok.replace("activityto:", "");
202 activityto = strtol(tok.c_str(), 0, 10);
203 }
204 // Get next
205 val = cfg->GetWord();
206 }
207
208 // Check deprecated 'if' directive
209 if (fMgr->Host() && cfg)
210 if (XrdProofdAux::CheckIf(cfg, fMgr->Host()) == 0)
211 return 0;
212
213 // Set the values
214 fCheckFrequency = (XPD_LONGOK(checkfq) && checkfq > 0) ? checkfq : fCheckFrequency;
215 fActivityTimeOut = (XPD_LONGOK(activityto) && activityto > 0) ? activityto : fActivityTimeOut;
216
217 XrdOucString msg;
218 XPDFORM(msg, "checkfq: %d s, activityto: %d s", fCheckFrequency, fActivityTimeOut);
219 TRACE(ALL, msg);
220
221 return 0;
222}
223
224////////////////////////////////////////////////////////////////////////////////
225/// Run configuration and parse the entered config directives.
226/// Return 0 on success, -1 on error
227
229{
230 XPDLOC(CMGR, "ClientMgr::Config")
231
232 // Run first the configurator
233 if (XrdProofdConfig::Config(rcf) != 0) {
234 XPDERR("problems parsing file ");
235 return -1;
236 }
237
238 XrdOucString msg;
239 msg = (rcf) ? "re-configuring" : "configuring";
240 TRACE(ALL, msg.c_str());
241
242 // Admin paths
244 fClntAdminPath += "/clients";
245
246 // Make sure they exist
247 XrdProofUI ui;
249 if (XrdProofdAux::AssertDir(fClntAdminPath.c_str(), ui, 1) != 0) {
250 XPDERR("unable to assert the clients admin path: "<<fClntAdminPath);
251 fClntAdminPath = "";
252 return -1;
253 }
254 TRACE(ALL, "clients admin path set to: "<<fClntAdminPath);
255
256 // Init place holders for previous active clients, if any
257 if (ParsePreviousClients(msg) != 0) {
258 XPDERR("problems parsing previous active clients: "<<msg);
259 }
260
261 // Initialize the security system if this is wanted
262 if (!rcf) {
263 if (fSecLib.length() <= 0) {
264 TRACE(ALL, "XRD seclib not specified; strong authentication disabled");
265 } else {
266 if (!(fCIA = LoadSecurity())) {
267 XPDERR("unable to load security system.");
268 return -1;
269 }
270 TRACE(ALL, "security library loaded");
271 }
272 }
273
274 if (rcf) {
275 // Re-assign groups
276 if (fMgr->GroupsMgr() && fMgr->GroupsMgr()->Num() > 0) {
277 std::list<XrdProofdClient *>::iterator pci;
278 for (pci = fProofdClients.begin(); pci != fProofdClients.end(); ++pci)
279 (*pci)->SetGroup(fMgr->GroupsMgr()->GetUserGroup((*pci)->User())->Name());
280 }
281 }
282
283 if (!rcf) {
284 // Start cron thread
285 pthread_t tid;
286 // Fill manager pointers structure
289 if (XrdSysThread::Run(&tid, XrdProofdClientCron,
290 (void *)&fManagerCron, 0, "ClientMgr cron thread") != 0) {
291 XPDERR("could not start cron thread");
292 return 0;
293 }
294 TRACE(ALL, "cron thread started");
295 }
296
297 // Done
298 return 0;
299}
300
301////////////////////////////////////////////////////////////////////////////////
302/// Process a login request
303
305{
306 XPDLOC(CMGR, "ClientMgr::Login")
307
308 int rc = 0;
309 XPD_SETRESP(p, "Login");
310
311 TRACEP(p, HDBG, "enter");
312
313 // If this server is explicitly required to be a worker node or a
314 // submaster, check whether the requesting host is allowed to connect
315 if (p->Request()->login.role[0] != 'i' &&
317 if (!fMgr->CheckMaster(p->Link()->Host())) {
318 TRACEP(p, XERR,"master not allowed to connect - "
319 "ignoring request ("<<p->Link()->Host()<<")");
320 response->Send(kXR_InvalidRequest,
321 "master not allowed to connect - request ignored");
322 return 0;
323 }
324 }
325
326 // Get user and group names for the entity requiring to login
327 int i, pid;
328 XrdOucString uname, gname, emsg;
329
330 // If this is the second call (after authentication) we just need mapping
331 if (p->Status() == XPD_NEED_MAP) {
332
333 // Finalize the login, checking the if username is allowed to use the facility.
334 // The username could have been set as part of the authentication process (for
335 // example via a user mapping funtion or a grid-map file), so these checks have
336 // to be done at this level.
337 // (The XrdProofdClient instance is created in here, if everything else goes well)
338 int rccc = 0;
339 if ((rccc = CheckClient(p, 0, emsg)) != 0) {
340 TRACEP(p, XERR, emsg);
341 XErrorCode rcode = (rccc == -2) ? (XErrorCode) kXR_NotAuthorized
342 : (XErrorCode) kXR_InvalidRequest;
343 response->Send(rcode, emsg.c_str());
344 response->Send(kXR_InvalidRequest, emsg.c_str());
345 return 0;
346 }
347
348 // Acknowledge the client
349 response->Send();
350 p->SetStatus(XPD_LOGGEDIN);
351 return MapClient(p, 0);
352 }
353
354 // Make sure the user is not already logged in
355 if ((p->Status() & XPD_LOGGEDIN)) {
356 response->Send(kXR_InvalidRequest, "duplicate login; already logged in");
357 return 0;
358 }
359
360 TRACE(ALL," hostname: '"<<p->Link()->Host()<<"'");
361 //
362 // Check if in any-server mode (localhost connections always are)
363 bool anyserver = (fMgr->SrvType() == kXPD_AnyServer ||
364 !strcmp(p->Link()->Host(), "localhost") ||
365 !strcmp(p->Link()->Host(), "127.0.0.0")) ? 1 : 0;
366
367 // Find out the connection type: 'i', internal, means this is a proofsrv calling back.
368 bool needauth = 0;
369 bool ismaster = (fMgr->SrvType() == kXPD_TopMaster || fMgr->SrvType() == kXPD_Master) ? 1 : 0;
370 switch (p->Request()->login.role[0]) {
371 case 'A':
372 p->SetConnType(kXPD_Admin);
373 response->SetTag("adm");
374 break;
375 case 'i':
376 p->SetConnType(kXPD_Internal);
377 response->SetTag("int");
378 break;
379 case 'M':
380 if (anyserver || ismaster) {
381 p->SetConnType(kXPD_ClientMaster);
382 needauth = 1;
383 response->SetTag("m2c");
384 } else {
385 TRACEP(p, XERR,"top master mode not allowed - ignoring request");
386 response->Send(kXR_InvalidRequest,
387 "Server not allowed to be top master - ignoring request");
388 return 0;
389 }
390 break;
391 case 'm':
392 if (anyserver || ismaster) {
393 p->SetConnType(kXPD_MasterMaster);
394 needauth = 1;
395 response->SetTag("m2m");
396 } else {
397 TRACEP(p, XERR,"submaster mode not allowed - ignoring request");
398 response->Send(kXR_InvalidRequest,
399 "Server not allowed to be submaster - ignoring request");
400 return 0;
401 }
402 break;
403 case 'L':
404 if (fMgr->SrvType() == kXPD_AnyServer || fMgr->RemotePLite()) {
405 p->SetConnType(kXPD_MasterMaster);
406 needauth = 1;
407 response->SetTag("m2l");
408 p->Request()->login.role[0] = 'm';
409 } else {
410 TRACEP(p, XERR,"PLite submaster mode not allowed - ignoring request");
411 response->Send(kXR_InvalidRequest,
412 "Server not allowed to be PLite submaster - ignoring request");
413 return 0;
414 }
415 break;
416 case 's':
417 if (anyserver || fMgr->SrvType() == kXPD_MasterWorker) {
418 p->SetConnType(kXPD_MasterWorker);
419 needauth = 1;
420 response->SetTag("w2m");
421 } else {
422 TRACEP(p, XERR,"worker mode not allowed - ignoring request");
423 response->Send(kXR_InvalidRequest,
424 "Server not allowed to be worker - ignoring request");
425 return 0;
426 }
427 break;
428 default:
429 TRACEP(p, XERR, "unknown mode: '" << p->Request()->login.role[0] <<"'");
430 response->Send(kXR_InvalidRequest, "Server type: invalide mode");
431 return rc;
432 }
433 response->SetTraceID();
434
435 // Unmarshall the data: process ID
436 pid = (int)ntohl(p->Request()->login.pid);
437 p->SetPid(pid);
438
439 // Username
440 char un[9];
441 for (i = 0; i < (int)sizeof(un)-1; i++) {
442 if (p->Request()->login.username[i] == '\0' || p->Request()->login.username[i] == ' ')
443 break;
444 un[i] = p->Request()->login.username[i];
445 }
446 un[i] = '\0';
447 uname = un;
448
449 // Longer usernames are in the attached buffer
450 if (uname == "?>buf") {
451 // Attach to buffer
452 char *buf = p->Argp()->buff;
453 int len = p->Request()->login.dlen;
454 // Extract username
455 uname.assign(buf,0,len-1);
456 int iusr = uname.find("|usr:");
457 if (iusr == -1) {
458 TRACEP(p, XERR,"long user name not found");
459 response->Send(kXR_InvalidRequest, "long user name not found");
460 return 0;
461 }
462 uname.erase(0,iusr+5);
463 uname.erase(uname.find("|"));
464 }
465
466 // Extract group name, if specified (syntax is uname[:gname])
467 int ig = uname.find(":");
468 if (ig != -1) {
469 gname.assign(uname, ig+1);
470 uname.erase(ig);
471 TRACEP(p, DBG, "requested group: "<<gname);
472 // Save the requested group info in the protocol instance
473 p->SetGroupIn(gname.c_str());
474 }
475
476 // Save the incoming username setting in the protocol instance
477 p->SetUserIn(uname.c_str());
478
479 // Establish IDs for this link
480 p->Link()->setID(uname.c_str(), pid);
481 p->SetTraceID();
482 response->SetTraceID();
483 p->SetClntCapVer(p->Request()->login.capver[0]);
484
485 // Get the security token for this link. We will either get a token, a null
486 // string indicating host-only authentication, or a null indicating no
487 // authentication. We can then optimize of each case.
488 if (needauth && fCIA) {
489#ifdef ROOT_XrdFour
490 const char *pp = fCIA->getParms(i, (XrdNetAddrInfo *) p->Link()->NetAddr());
491#else
492 const char *pp = fCIA->getParms(i, p->Link()->Name());
493#endif
494 if (pp && i ) {
495 response->SendI((kXR_int32)XPROOFD_VERSBIN, (void *)pp, i);
496 p->SetStatus((XPD_NEED_MAP | XPD_NEED_AUTH));
497 return 0;
498 } else if (pp) {
499 p->SetAuthEntity();
500 }
501 }
502 // Check the client at this point; the XrdProofdClient instance is created
503 // in here, if everything else goes well
504 int rccc = 0;
505 if ((rccc = CheckClient(p, p->UserIn(), emsg)) != 0) {
506 TRACEP(p, XERR, emsg);
507 XErrorCode rcode = (rccc == -2) ? (XErrorCode) kXR_NotAuthorized
508 : (XErrorCode) kXR_InvalidRequest;
509 response->Send(rcode, emsg.c_str());
510 return 0;
511 }
512 rc = response->SendI((kXR_int32)XPROOFD_VERSBIN);
513 p->SetStatus(XPD_LOGGEDIN);
514
515 // Map the client
516 return MapClient(p, 1);
517}
518
519////////////////////////////////////////////////////////////////////////////////
520/// Perform checks on the client username. In case authentication is required
521/// this is called afetr authentication.
522/// Return 0 on success; on error, return -1 .
523
525 const char *user, XrdOucString &emsg)
526{
527 XPDLOC(CMGR, "ClientMgr::CheckClient")
528
529 if (!p) {
530 emsg = "protocol object undefined!";
531 return -1;
532 }
533
534 XrdOucString uname(user), gname(p->GroupIn());
535 if (!user) {
536 if (p && p->AuthProt() && strlen(p->AuthProt()->Entity.name) > 0) {
537 uname = p->AuthProt()->Entity.name;
538 } else {
539 emsg = "username not passed and not available in the protocol security entity - failing";
540 return -1;
541 }
542 }
543
544 // Check if user belongs to a group
545 XrdProofGroup *g = 0;
546 if (fMgr->GroupsMgr() && fMgr->GroupsMgr()->Num() > 0) {
547 if (gname.length() > 0) {
548 g = fMgr->GroupsMgr()->GetGroup(gname.c_str());
549 if (!g) {
550 XPDFORM(emsg, "group unknown: %s", gname.c_str());
551 return -1;
552 } else if (strncmp(g->Name(),"default",7) &&
553 !g->HasMember(uname.c_str())) {
554 XPDFORM(emsg, "user %s is not member of group %s", uname.c_str(), gname.c_str());
555 return -1;
556 } else {
557 if (TRACING(DBG)) {
558 TRACEP(p, DBG,"group: "<<gname<<" found");
559 g->Print();
560 }
561 }
562 } else {
563 g = fMgr->GroupsMgr()->GetUserGroup(uname.c_str());
564 gname = g ? g->Name() : "default";
565 }
566 }
567
568 // Here we check if the user is allowed to use the system
569 // If not, we fail.
570 XrdProofUI ui;
571 bool su;
572 if (fMgr->CheckUser(uname.c_str(), gname.c_str(), ui, emsg, su) != 0) {
573 if (emsg.length() <= 0)
574 XPDFORM(emsg, "Controlled access: user '%s', group '%s' not allowed to connect",
575 uname.c_str(), gname.c_str());
576 return -2;
577 }
578 if (su) {
579 // Update superuser flag
580 p->SetSuperUser(su);
581 TRACEP(p, DBG, "request from entity: "<<uname<<":"<<gname<<" (privileged)");
582 } else {
583 TRACEP(p, DBG, "request from entity: "<<uname<<":"<<gname);
584 }
585
586 // Attach-to / Create the XrdProofdClient instance for this user: if login
587 // fails this will be removed at a later stage
588 XrdProofdClient *c = GetClient(uname.c_str(), gname.c_str());
589 if (c) {
590 if (!c->ROOT())
591 c->SetROOT(fMgr->ROOTMgr()->DefaultVersion());
592 if (c->IsValid()) {
593 // Set the group, if any
594 c->SetGroup(gname.c_str());
595 }
596 } else {
597 emsg = "unable to instantiate object for client ";
598 emsg += uname;
599 return -1;
600 }
601 // Save into the protocol instance
602 p->SetClient(c);
603
604 // Done
605 return 0;
606}
607
608////////////////////////////////////////////////////////////////////////////////
609/// Process a login request
610
612{
613 XPDLOC(CMGR, "ClientMgr::MapClient")
614
615 int rc = 0;
616 XPD_SETRESP(p, "MapClient");
617
618 XrdOucString msg;
619
620 TRACEP(p, HDBG, "all: "<< all);
621
622 // Attach to the client
623 XrdProofdClient *pc = p->Client();
624
625 // Map the existing session, if found
626 if (!pc || !pc->IsValid()) {
627 if (pc) {
628 { // Remove from the list
630 fProofdClients.remove(pc);
631 }
632 SafeDelete(pc);
633 p->SetClient(0);
634 }
635 TRACEP(p, DBG, "cannot find valid instance of XrdProofdClient");
636 response->Send(kXP_ServerError,
637 "MapClient: cannot find valid instance of XrdProofdClient");
638 return 0;
639 }
640
641 // Flag for internal connections
642 bool proofsrv = ((p->ConnType() == kXPD_Internal) && all) ? 1 : 0;
643
644 // If call back from proofsrv, find out the target session
645 short int psid = -1;
646 char protver = -1;
647 short int clientvers = -1;
648 if (proofsrv) {
649 memcpy(&psid, (const void *)&(p->Request()->login.reserved[0]), 2);
650 if (psid < 0) {
651 TRACEP(p, XERR, "proofsrv callback: sent invalid session id");
652 response->Send(kXR_InvalidRequest,
653 "MapClient: proofsrv callback: sent invalid session id");
654 return 0;
655 }
656 protver = p->Request()->login.capver[0];
657 TRACEP(p, DBG, "proofsrv callback for session: " <<psid);
658 } else {
659 // Get PROOF version run by client
660 memcpy(&clientvers, (const void *)&(p->Request()->login.reserved[0]), 2);
661 TRACEP(p, DBG, "PROOF version run by client: " <<clientvers);
662 }
663
664 // If proofsrv, locate the target session
665 if (proofsrv) {
666 XrdProofdProofServ *psrv = pc->GetServer(psid);
667 if (!psrv) {
668 TRACEP(p, XERR, "proofsrv callback: wrong target session: "<<psid<<" : protocol error");
669 response->Send(kXP_nosession, "MapClient: proofsrv callback:"
670 " wrong target session: protocol error");
671 return -1;
672 } else {
673 // Set the protocol version
674 psrv->SetProtVer(protver);
675 // Assign this link to it
676 XrdProofdResponse *resp = p->Response(1);
677 if (!resp) {
678 TRACEP(p, XERR, "proofsrv callback: could not get XrdProofdResponse object");
679 response->Send(kXP_nosession, "MapClient: proofsrv callback: memory issue?");
680 return -1;
681 }
682 psrv->SetConnection(resp);
683 psrv->SetValid(1);
684 // Set Trace ID
685 XrdOucString tid;
686 XPDFORM(tid, "xrd->%s", psrv->Ordinal());
687 resp->SetTag(tid.c_str());
688 resp->SetTraceID();
689 TRACEI(resp->TraceID(), DBG, "proofsrv callback: link assigned to target session "<<psid);
690 }
691 } else {
692
693 // Only one instance of this client can map at a time
694 XrdSysMutexHelper mhc(pc->Mutex());
695
696 // Make sure that the version is filled correctly (if an admin operation
697 // was run before this may still be -1 on workers)
698 p->SetProofProtocol(clientvers);
699
700 // Check if we have already an ID for this client from a previous connection
701 XrdOucString cpath;
702 int cid = -1;
703 if ((cid = CheckAdminPath(p, cpath, msg)) >= 0) {
704 // Assign the slot
705 pc->SetClientID(cid, p);
706 // The index of the next free slot will be the unique ID
707 p->SetCID(cid);
708 // Remove the file indicating that this client was still disconnected
709 XrdOucString discpath(cpath, 0, cpath.rfind("/cid"));
710 discpath += "/disconnected";
711 if (unlink(discpath.c_str()) != 0) {
712 XPDFORM(msg, "warning: could not remove %s (errno: %d)", discpath.c_str(), errno);
713 TRACEP(p, XERR, msg.c_str());
714 }
715 // Update counters
717
718 } else {
719 // The index of the next free slot will be the unique ID
720 p->SetCID(pc->GetClientID(p));
721 // Create the client directory in the admin path
722 if (CreateAdminPath(p, cpath, msg) != 0) {
723 TRACEP(p, XERR, msg.c_str());
724 fProofdClients.remove(pc);
725 SafeDelete(pc);
726 p->SetClient(0);
727 response->Send(kXP_ServerError, msg.c_str());
728 return 0;
729 }
730 }
731 p->SetAdminPath(cpath.c_str());
732 XPDFORM(msg, "client ID and admin paths created: %s", cpath.c_str());
733 TRACEP(p, DBG, msg.c_str());
734
735 TRACEP(p, DBG, "CID: "<<p->CID()<<", size: "<<pc->Size());
736 }
737
738 // Document this login
739 if (!(p->Status() & XPD_NEED_AUTH)) {
740 const char *srvtype[6] = {"ANY", "MasterWorker", "MasterMaster",
741 "ClientMaster", "Internal", "Admin"};
742 XPDFORM(msg, "user %s logged-in%s; type: %s", pc->User(),
743 p->SuperUser() ? " (privileged)" : "", srvtype[p->ConnType()+1]);
744 TRACEP(p, LOGIN, msg);
745 }
746
747 // Done
748 return 0;
749}
750
751////////////////////////////////////////////////////////////////////////////////
752/// Create the client directory in the admin path
753
755 XrdOucString &cpath, XrdOucString &emsg)
756{
757 if (!p || !p->Link()) {
758 XPDFORM(emsg, "invalid inputs (p: %p)", p);
759 return -1;
760 }
761
762 // Create link ID
763 XrdOucString lid;
764 XPDFORM(lid, "%s.%d", p->Link()->Host(), p->Pid());
765
766 // Create the path now
767 XPDFORM(cpath, "%s/%s", p->Client()->AdminPath(), lid.c_str());
768 XrdProofUI ui;
770 if (XrdProofdAux::AssertDir(cpath.c_str(), ui, 1) != 0) {
771 XPDFORM(emsg, "error creating client admin path: %s", cpath.c_str());
772 return -1;
773 }
774 // Save client ID for full recovery
775 cpath += "/cid";
776 FILE *fcid = fopen(cpath.c_str(), "w");
777 if (fcid) {
778 fprintf(fcid, "%d", p->CID());
779 fclose(fcid);
780 } else {
781 XPDFORM(emsg, "error creating file for client id: %s", cpath.c_str());
782 return -1;
783 }
784 // Done
785 return 0;
786}
787
788////////////////////////////////////////////////////////////////////////////////
789/// Check the old-clients admin for an existing entry for this client and
790/// read the client ID;
791
793 XrdOucString &cidpath, XrdOucString &emsg)
794{
795 emsg = "";
796 if (!p) {
797 XPDFORM(emsg, "CheckAdminPath: invalid inputs (p: %p)", p);
798 return -1;
799 }
800
801 // Create link ID
802 XrdOucString lid;
803 XPDFORM(lid, "%s.%d", p->Link()->Host(), p->Pid());
804
805 // Create the path now
806 XPDFORM(cidpath, "%s/%s/cid", p->Client()->AdminPath(), lid.c_str());
807
808 // Create disconnected path
809 XrdOucString discpath;
810 XPDFORM(discpath, "%s/%s/disconnected", p->Client()->AdminPath(), lid.c_str());
811
812 // Check last access time of disconnected if available, otherwise cid
813 bool expired = false;
814 struct stat st;
815 int rc = stat(discpath.c_str(), &st);
816 if (rc != 0) rc = stat(cidpath.c_str(), &st);
817 if (rc != 0 || (expired = ((int)(time(0) - st.st_atime) > fReconnectTimeOut))) {
818 if (expired || (rc != 0 && errno != ENOENT)) {
819 // Remove the file
820 cidpath.replace("/cid", "");
821 if (expired)
822 XPDFORM(emsg, "CheckAdminPath: reconnection timeout expired: remove %s ",
823 cidpath.c_str());
824 else
825 XPDFORM(emsg, "CheckAdminPath: problems stat'ing %s (errno: %d): remove ",
826 cidpath.c_str(), errno);
827 if (XrdProofdAux::RmDir(cidpath.c_str()) != 0)
828 emsg += ": failure!";
829 } else {
830 XPDFORM(emsg, "CheckAdminPath: no such file %s", cidpath.c_str());
831 }
832 return -1;
833 }
834
835 // Get the client ID for full recovery
836 return XrdProofdAux::GetIDFromPath(cidpath.c_str(), emsg);
837}
838
839////////////////////////////////////////////////////////////////////////////////
840/// Client entries for the clients still connected when the daemon terminated
841
843{
844 XPDLOC(CMGR, "ClientMgr::ParsePreviousClients")
845
846 emsg = "";
847
848 // Open dir
849 DIR *dir = opendir(fClntAdminPath.c_str());
850 if (!dir) {
851 TRACE(XERR, "cannot open dir "<<fClntAdminPath<<" ; error: "<<errno);
852 return -1;
853 }
854 TRACE(DBG, "creating holders for active clients ...");
855
856 // Scan the active sessions admin path
857 XrdOucString usrpath, cidpath, discpath, usr, grp;
858 struct dirent *ent = 0;
859 while ((ent = (struct dirent *)readdir(dir))) {
860 // Skip the basic entries
861 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue;
862 XPDFORM(usrpath, "%s/%s", fClntAdminPath.c_str(), ent->d_name);
863 bool rm = 0;
864 struct stat st;
865 if (stat(usrpath.c_str(), &st) == 0) {
866 usr = ent->d_name;
867 grp = usr;
868 usr.erase(usr.find('.'));
869 grp.erase(0, grp.find('.')+1);
870 TRACE(DBG, "found usr: "<<usr<<", grp: "<<grp);
871 // Get client instance
872 XrdProofdClient *c = GetClient(usr.c_str(), grp.c_str());
873 if (!c) {
874 XPDFORM(emsg, "ParsePreviousClients: could not get client instance"
875 " for {%s, %s}", usr.c_str(), grp.c_str());
876 rm = 1;
877 }
878 // Open user sub-dir
879 DIR *subdir = 0;
880 if (!rm && !(subdir = opendir(usrpath.c_str()))) {
881 TRACE(XERR, "cannot open dir "<<usrpath<<" ; error: "<<errno);
882 rm = 1;
883 }
884 if (!rm) {
885 bool xrm = 0;
886 struct dirent *sent = 0;
887 while ((sent = (struct dirent *)readdir(subdir))) {
888 // Skip the basic entries
889 if (!strcmp(sent->d_name, ".") || !strcmp(sent->d_name, "..")) continue;
890 if (!strcmp(sent->d_name, "xpdsock")) continue;
891 XPDFORM(cidpath, "%s/%s/cid", usrpath.c_str(), sent->d_name);
892 // Check last access time
893 if (stat(cidpath.c_str(), &st) != 0 ||
894 (int)(time(0) - st.st_atime) > fReconnectTimeOut) {
895 xrm = 1;
896 }
897 // Read the client ID and and reserve an entry in the related vector
898 int cid = (!xrm) ? XrdProofdAux::GetIDFromPath(cidpath.c_str(), emsg) : -1;
899 if (cid < 0)
900 xrm = 1;
901 // Reserve an entry in the related vector
902 if (!xrm && c->ReserveClientID(cid) != 0)
903 xrm = 1;
904 // Flag this as disconnected
905 if (!xrm) {
906 XPDFORM(discpath, "%s/%s/disconnected", usrpath.c_str(), sent->d_name);
907 FILE *fd = fopen(discpath.c_str(), "w");
908 if (!fd) {
909 TRACE(XERR, "unable to create path: " <<discpath);
910 xrm = 1;
911 } else {
912 fclose(fd);
913 }
914 if (!xrm)
916 }
917 // If it did not work remove the entry
918 if (xrm) {
919 TRACE(DBG, "removing path: " <<cidpath);
920 cidpath.replace("/cid", "");
921 XPDFORM(emsg, "ParsePreviousClients: failure: remove %s ", cidpath.c_str());
922 if (XrdProofdAux::RmDir(cidpath.c_str()) != 0)
923 emsg += ": failure!";
924 }
925 }
926 }
927 if (subdir)
928 closedir(subdir);
929 } else {
930 rm = 1;
931 }
932 // If it did not work remove the entry
933 if (rm) {
934 TRACE(DBG, "removing path: " <<usrpath);
935 XPDFORM(emsg, "ParsePreviousClients: failure: remove %s ", usrpath.c_str());
936 if (XrdProofdAux::RmDir(usrpath.c_str()) != 0)
937 emsg += ": failure!";
938 }
939 }
940 // Close the directory
941 closedir(dir);
942
943 // Notify the number of previously active clients now offline
944 TRACE(DBG, "found "<<fNDisconnected<<" active clients");
945
946 // Done
947 return 0;
948}
949
950////////////////////////////////////////////////////////////////////////////////
951/// Regular checks of the client admin path; run by the cron job
952
954{
955 XPDLOC(CMGR, "ClientMgr::CheckClients")
956
957 // Open dir
958 DIR *dir = opendir(fClntAdminPath.c_str());
959 if (!dir) {
960 TRACE(XERR, "cannot open dir "<<fClntAdminPath<<" ; error: "<<errno);
961 return -1;
962 }
963 TRACE(REQ, "checking active clients ...");
964
965 // Scan the active sessions admin path
966 int rc = 0;
967 XrdOucString usrpath, cidpath, discpath;
968 struct dirent *ent = 0;
969 while ((ent = (struct dirent *)readdir(dir))) {
970 // Skip the basic entries
971 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue;
972 XPDFORM(usrpath, "%s/%s", fClntAdminPath.c_str(), ent->d_name);
973 bool rm = 0;
974 XrdProofdClient *c = 0;
975 struct stat st, xst;
976 if (stat(usrpath.c_str(), &xst) == 0) {
977 // Find client instance
978 XrdOucString usr, grp;
979 XrdProofdAux::ParseUsrGrp(ent->d_name, usr, grp);
980 if (!(c = GetClient(usr.c_str(), grp.c_str(), 0))) {
981 TRACE(XERR, "instance for client "<<ent->d_name<<" not found!");
982 rm = 1;
983 }
984 // Open user sub-dir
985 DIR *subdir = 0;
986 if (!rm && !(subdir = opendir(usrpath.c_str()))) {
987 TRACE(XERR, "cannot open dir "<<usrpath<<" ; error: "<<errno);
988 rm = 1;
989 }
990 if (!rm) {
991 bool xrm = 0, xclose = 0;
992 struct dirent *sent = 0;
993 while ((sent = (struct dirent *)readdir(subdir))) {
994 // Skip the basic entries
995 if (!strcmp(sent->d_name, ".") || !strcmp(sent->d_name, "..")) continue;
996 if (!strcmp(sent->d_name, "xpdsock")) continue;
997 XPDFORM(discpath, "%s/%s/disconnected", usrpath.c_str(), sent->d_name);
998 // Client admin path
999 XPDFORM(cidpath, "%s/%s/cid", usrpath.c_str(), sent->d_name);
1000 // Check last access time
1001 if (stat(cidpath.c_str(), &st) == 0) {
1002 // If in disconnected state, check if it needs to be cleaned
1003 if (stat(discpath.c_str(), &xst) == 0) {
1004 if ((int)(time(0) - st.st_atime) > fReconnectTimeOut) {
1005 xrm = 1;
1006 }
1007 } else {
1008 // If required, check the recent activity; if inactive since too long
1009 // we ask the client to proof its vitality; but only once: next time
1010 // we close the link
1011 if (fActivityTimeOut > 0 &&
1012 (int)(time(0) - st.st_atime) > fActivityTimeOut) {
1013 if (c->Touch() == 1) {
1014 // The client was already asked to proof its vitality
1015 // during last cycle and it did not do it, so we close
1016 // the link
1017 xclose = 1;
1018 }
1019 }
1020 }
1021 } else {
1022 // No id info, clean
1023 xrm = 1;
1024 }
1025 // If inactive since too long, close the associated link
1026 if (xclose) {
1027 // Get the client id
1028 XrdOucString emsg;
1029 int cid = XrdProofdAux::GetIDFromPath(cidpath.c_str(), emsg);
1030 if (cid >= 0) {
1031 // Get the XrdProofdProtocol instance
1032 XrdProofdProtocol *p = c->GetProtocol(cid);
1033 if (p && p->Link()) {
1034 // This client will try to reconnect, if alive, so give it
1035 // some time by skipping the next sessions check
1036 c->SkipSessionsCheck(0, emsg);
1037 // Close the associated link; Recycle is called from there
1038 p->Link()->Close();
1039 } else {
1040 TRACE(XERR, "protocol or link associated with ID "<<cid<<" are invalid");
1041 xrm = 1;
1042 }
1043 } else {
1044 TRACE(XERR, "could not resolve client id from "<<cidpath);
1045 xrm = 1;
1046 }
1047 }
1048 // If too old remove the entry
1049 if (xrm) {
1050 discpath.replace("/disconnected", "");
1051 TRACE(DBG, "removing path "<<discpath);
1052 if ((rc = XrdProofdAux::RmDir(discpath.c_str())) != 0) {
1053 TRACE(XERR, "problems removing "<<discpath<<"; error: "<<-rc);
1054 }
1055 }
1056 }
1057 }
1058 if (subdir)
1059 closedir(subdir);
1060 } else {
1061 rm = 1;
1062 }
1063 // If it did not work remove the entry
1064 if (rm) {
1065 TRACE(DBG, "removing path: " <<usrpath);
1066 if ((rc = XrdProofdAux::RmDir(usrpath.c_str())) != 0) {
1067 TRACE(XERR, "problems removing "<<usrpath<<"; error: "<<-rc);
1068 }
1069 }
1070 }
1071 // Close the directory
1072 closedir(dir);
1073
1074 // Done
1075 return 0;
1076}
1077
1078////////////////////////////////////////////////////////////////////////////////
1079/// Analyse client authentication info
1080
1082{
1083 XPDLOC(CMGR, "ClientMgr::Auth")
1084
1085 XrdSecCredentials cred;
1086 XrdSecParameters *parm = 0;
1087 XrdOucErrInfo eMsg;
1088 const char *eText;
1089 int rc = 1;
1090 XPD_SETRESP(p, "Auth");
1091
1092 TRACEP(p, REQ, "enter");
1093
1094 // Ignore authenticate requests if security turned off
1095 if (!fCIA)
1096 return response->Send();
1097 cred.size = p->Request()->header.dlen;
1098 cred.buffer = p->Argp()->buff;
1099
1100 // If we have no auth protocol, try to get it
1101 if (!p->AuthProt()) {
1102 XrdSecProtocol *ap = 0;
1103#ifdef ROOT_XrdFour
1104 XrdNetAddr netaddr(p->Link()->NetAddr());
1105#else
1106 struct sockaddr netaddr;
1107 p->Link()->Name(&netaddr);
1108#endif
1109 if (!(ap = fCIA->getProtocol(p->Link()->Host(), netaddr, &cred, &eMsg))) {
1110 eText = eMsg.getErrText(rc);
1111 TRACEP(p, XERR, "user authentication failed; "<<eText);
1112 response->Send(kXR_NotAuthorized, eText);
1113 return -EACCES;
1114 }
1115 p->SetAuthProt(ap);
1116 p->AuthProt()->Entity.tident = p->Link()->ID;
1117 }
1118 // Set the wanted login name
1119 size_t len = strlen("XrdSecLOGINUSER=")+strlen(p->UserIn())+2;
1120 char *u = new char[len];
1121 snprintf(u, len, "XrdSecLOGINUSER=%s", p->UserIn());
1122 putenv(u);
1123
1124 // Now try to authenticate the client using the current protocol
1125 XrdOucString namsg;
1126 if (!(rc = p->AuthProt()->Authenticate(&cred, &parm, &eMsg))) {
1127
1128 // Make sure that the user name that we want is allowed
1129 if (p->AuthProt()->Entity.name && strlen(p->AuthProt()->Entity.name) > 0) {
1130 if (p->UserIn() && strlen(p->UserIn()) > 0) {
1131 XrdOucString usrs(p->AuthProt()->Entity.name);
1132 SafeFree(p->AuthProt()->Entity.name);
1133 XrdOucString usr;
1134 int from = 0, rcmtc = -1;
1135 while ((from = usrs.tokenize(usr, from, ',')) != STR_NPOS) {
1136 // The first one by default, if no match is found
1137 if (!(p->AuthProt()->Entity.name))
1138 p->AuthProt()->Entity.name = strdup(usr.c_str());
1139 if ((usr == p->UserIn())) {
1140 free(p->AuthProt()->Entity.name);
1141 p->AuthProt()->Entity.name = strdup(usr.c_str());
1142 rcmtc = 0;
1143 break;
1144 }
1145 }
1146 if (rcmtc != 0) {
1147 namsg = "logging as '";
1148 namsg += p->AuthProt()->Entity.name;
1149 namsg += "' instead of '";
1150 namsg += p->UserIn();
1151 namsg += "' following admin settings";
1152 TRACEP(p, LOGIN, namsg.c_str());
1153 namsg.insert("Warning: ", 0);
1154 response->Send(kXR_attn, kXPD_srvmsg, 2, (char *) namsg.c_str(), namsg.length());
1155 }
1156 } else {
1157 TRACEP(p, XERR, "user name is empty: protocol error?");
1158 }
1159 } else {
1160 TRACEP(p, XERR, "name of the authenticated entity is empty: protocol error?");
1161 rc = -1;
1162 }
1163
1164 if (rc == 0) {
1165 const char *msg = (p->Status() & XPD_ADMINUSER) ? " admin login as " : " login as ";
1166 rc = response->Send();
1167 char status = p->Status();
1168 status &= ~XPD_NEED_AUTH;
1169 p->SetStatus(status);
1170 p->SetAuthEntity(&(p->AuthProt()->Entity));
1171 if (p->AuthProt()->Entity.name) {
1172 TRACEP(p, LOGIN, p->Link()->ID << msg << p->AuthProt()->Entity.name);
1173 } else {
1174 TRACEP(p, LOGIN, p->Link()->ID << msg << " nobody");
1175 }
1176 return rc;
1177 }
1178 }
1179
1180 // If we need to continue authentication, tell the client as much
1181 if (rc > 0) {
1182 TRACEP(p, DBG, "more auth requested; sz: " <<(parm ? parm->size : 0));
1183 if (parm) {
1184 rc = response->Send(kXR_authmore, parm->buffer, parm->size);
1185 delete parm;
1186 return rc;
1187 }
1188 if (p->AuthProt()) {
1189 p->AuthProt()->Delete();
1190 p->SetAuthProt(0);
1191 }
1192 TRACEP(p, XERR, "security requested additional auth w/o parms!");
1193 response->Send(kXP_ServerError, "invalid authentication exchange");
1194 return -EACCES;
1195 }
1196
1197 // We got an error, bail out
1198 if (p->AuthProt()) {
1199 p->AuthProt()->Delete();
1200 p->SetAuthProt(0);
1201 }
1202 eText = (namsg.length() > 0) ? namsg.c_str() : eMsg.getErrText(rc);
1203 TRACEP(p, XERR, "user authentication failed; "<<eText);
1204 response->Send(kXR_NotAuthorized, eText);
1205 return -EACCES;
1206}
1207
1208////////////////////////////////////////////////////////////////////////////////
1209/// Load security framework and plugins, if not already done
1210
1212{
1213 XPDLOC(CMGR, "ClientMgr::LoadSecurity")
1214
1215 TRACE(REQ, "LoadSecurity");
1216
1217 const char *cfn = CfgFile();
1218 const char *seclib = fSecLib.c_str();
1219
1220 // Make sure the input config file is defined
1221 if (!cfn) {
1222 TRACE(XERR, "config file not specified");
1223 return 0;
1224 }
1225
1226 // Create the plug-in instance
1227 if (!(fSecPlugin = new XrdSysPlugin((fEDest ? fEDest : (XrdSysError *)0), seclib))) {
1228 TRACE(XERR, "could not create plugin instance for "<<seclib);
1229 return (XrdSecService *)0;
1230 }
1231
1232 // Get the function
1233 XrdSecServLoader_t ep = (XrdSecServLoader_t) fSecPlugin->getPlugin("XrdSecgetService");
1234 if (!ep) {
1235 TRACE(XERR, "could not find 'XrdSecgetService()' in "<<seclib);
1236 return (XrdSecService *)0;
1237 }
1238
1239 // Extract in a temporary file the directives prefixed "xpd.sec..." (filtering
1240 // out the prefix), "sec.protocol" and "sec.protparm"
1241 int nd = 0;
1242 char *rcfn = FilterSecConfig(nd);
1243 if (!rcfn) {
1245 if (nd == 0) {
1246 // No directives to be processed
1247 TRACE(XERR, "no security directives: strong authentication disabled");
1248 return 0;
1249 }
1250 // Failure
1251 TRACE(XERR, "creating temporary config file");
1252 return 0;
1253 }
1254
1255 // Get the server object
1256 XrdSecService *cia = 0;
1257 if (!(cia = (*ep)((fEDest ? fEDest->logger() : (XrdSysLogger *)0), rcfn))) {
1258 TRACE(XERR, "Unable to create security service object via " << seclib);
1260 unlink(rcfn);
1261 delete[] rcfn;
1262 return 0;
1263 }
1264 // Notify
1265 TRACE(ALL, "strong authentication enabled");
1266
1267 // Unlink the temporary file and cleanup its path
1268 unlink(rcfn);
1269 delete[] rcfn;
1270
1271 // All done
1272 return cia;
1273}
1274
1275////////////////////////////////////////////////////////////////////////////////
1276/// Grep directives of the form "xpd.sec...", "sec.protparm" and
1277/// "sec.protocol" from file 'cfn' and save them in a temporary file,
1278/// stripping off the prefix "xpd." when needed.
1279/// If any such directory is found, the full path of the temporary file
1280/// is returned, with the number of directives found in 'nd'.
1281/// Otherwise 0 is returned and '-errno' specified in nd.
1282/// The caller has the responsability to unlink the temporary file and
1283/// to release the memory allocated for the path.
1284
1286{
1287 XPDLOC(CMGR, "ClientMgr::FilterSecConfig")
1288
1289 static const char *pfx[] = { "xpd.sec.", "sec.protparm", "sec.protocol", "set" };
1290 char *rcfn = 0;
1291
1292 TRACE(REQ, "enter");
1293
1294 const char *cfn = CfgFile();
1295
1296 // Make sure that we got an input file path and that we can open the
1297 // associated path.
1298 FILE *fin = 0;
1299 if (!cfn || !(fin = fopen(cfn,"r"))) {
1300 nd = (errno > 0) ? -errno : -1;
1301 return rcfn;
1302 }
1303
1304 // Read the directives: if an interesting one is found, we create
1305 // the output temporary file
1306 int fd = -1;
1307 char lin[2048];
1308 while (fgets(lin,sizeof(lin),fin)) {
1309 if (!strncmp(lin, pfx[0], strlen(pfx[0])) ||
1310 !strncmp(lin, pfx[1], strlen(pfx[1])) ||
1311 !strncmp(lin, pfx[2], strlen(pfx[2])) ||
1312 !strncmp(lin, pfx[3], strlen(pfx[3]))) {
1313 // Target directive found
1314 nd++;
1315 // Create the output file, if not yet done
1316 if (!rcfn) {
1317 size_t len = strlen(fMgr->TMPdir()) + strlen("/xpdcfn_XXXXXX") + 2;
1318 rcfn = new char[len];
1319 snprintf(rcfn, len, "%s/xpdcfn_XXXXXX", fMgr->TMPdir());
1320 mode_t oldum = umask(022);
1321 if ((fd = mkstemp(rcfn)) < 0) {
1322 delete[] rcfn;
1323 nd = (errno > 0) ? -errno : -1;
1324 fclose(fin);
1325 rcfn = 0;
1326 oldum = umask(oldum);
1327 return rcfn;
1328 }
1329 oldum = umask(oldum);
1330 }
1331 XrdOucString slin = lin;
1332 // Strip the prefix "xpd."
1333 if (slin.beginswith("xpd.")) slin.replace("xpd.","");
1334 // Make keyword substitution
1335 fMgr->ResolveKeywords(slin, 0);
1336 // Write the line to the output file
1337 XrdProofdAux::Write(fd, slin.c_str(), slin.length());
1338 }
1339 }
1340
1341 // Close files
1342 fclose(fin);
1343 if (fd >= 0) close(fd);
1344
1345 return rcfn;
1346}
1347
1348////////////////////////////////////////////////////////////////////////////////
1349/// Handle request for localizing a client instance for {usr, grp} from the list.
1350/// Create a new instance, if required; for new instances, use the path at 'sock'
1351/// for the unix socket, or generate a new one, if sock = 0.
1352
1353XrdProofdClient *XrdProofdClientMgr::GetClient(const char *usr, const char *grp,
1354 bool create)
1355{
1356 XPDLOC(CMGR, "ClientMgr::GetClient")
1357
1358 TRACE(DBG, "usr: "<< (usr ? usr : "undef")<<", grp:"<<(grp ? grp : "undef"));
1359
1360 XrdOucString dmsg, emsg;
1361 XrdProofdClient *c = 0;
1362 bool newclient = 0;
1363 std::list<XrdProofdClient *>::iterator i;
1364
1366 for (i = fProofdClients.begin(); i != fProofdClients.end(); ++i) {
1367 if ((c = *i) && c->Match(usr,grp)) break;
1368 c = 0;
1369 }
1370 }
1371
1372 if (!c && create) {
1373 // Is this a potential user?
1374 XrdProofUI ui;
1375 bool su;
1376 if (fMgr->CheckUser(usr, grp, ui, emsg, su) == 0) {
1377 // Yes: create an (invalid) instance of XrdProofdClient:
1378 // It would be validated on the first valid login
1379 ui.fUser = usr;
1380 ui.fGroup = grp;
1381 bool full = (fMgr->SrvType() != kXPD_Worker) ? 1 : 0;
1382 c = new XrdProofdClient(ui, full, fMgr->ChangeOwn(), fEDest, fClntAdminPath.c_str(), fReconnectTimeOut);
1383 newclient = 1;
1384 bool freeclient = 1;
1385 if (c && c->IsValid()) {
1386 // Locate and set the group, if any
1387 if (fMgr->GroupsMgr() && fMgr->GroupsMgr()->Num() > 0) {
1388 XrdProofGroup *g = fMgr->GroupsMgr()->GetUserGroup(usr, grp);
1389 if (g) {
1390 c->SetGroup(g->Name());
1391 } else if (TRACING(XERR)) {
1392 emsg = "group = "; emsg += grp; emsg += " nor found";
1393 }
1394 }
1396 XrdProofdClient *nc = 0;
1397 for (i = fProofdClients.begin(); i != fProofdClients.end(); ++i) {
1398 if ((nc = *i) && nc->Match(usr,grp)) break;
1399 nc = 0;
1400 newclient = 0;
1401 }
1402 if (!nc) {
1403 // Add to the list
1404 fProofdClients.push_back(c);
1405 freeclient = 0;
1406 }
1407 }
1408 if (freeclient) {
1409 SafeDelete(c);
1410 } else if (TRACING(DBG)) {
1411 XPDFORM(dmsg, "instance for {client, group} = {%s, %s} created"
1412 " and added to the list (%p)", usr, grp, c);
1413 }
1414 } else {
1415 if (TRACING(XERR)) {
1416 XPDFORM(dmsg, "instance for {client, group} = {%s, %s} is invalid", usr, grp);
1417 }
1418 SafeDelete(c);
1419 }
1420 } else {
1421 if (TRACING(XERR)) {
1422 XPDFORM(dmsg, "client '%s' unknown or unauthorized: %s", usr, emsg.c_str());
1423 }
1424 }
1425 }
1426
1427 // Trim the sandbox, if needed
1428 if (c && !newclient) {
1429 if (c->TrimSessionDirs() != 0) {
1430 if (TRACING(XERR)) {
1431 XPDFORM(dmsg, "problems trimming client '%s' sandbox", usr);
1432 }
1433 }
1434 }
1435
1436 if (dmsg.length() > 0) {
1437 if (TRACING(DBG)) {
1438 TRACE(DBG, dmsg);
1439 } else {
1440 if (emsg.length() > 0) TRACE(XERR, emsg);
1441 TRACE(XERR, dmsg);
1442 }
1443 }
1444
1445 // Over
1446 return c;
1447}
1448
1449////////////////////////////////////////////////////////////////////////////////
1450/// Broadcast message 'msg' to the connected instances of client 'clnt' or to all
1451/// connected instances if clnt == 0.
1452
1454{
1455 // The clients to notified
1456 std::list<XrdProofdClient *> *clnts;
1457 if (!clnt) {
1458 // The full list
1459 clnts = &fProofdClients;
1460 } else {
1461 clnts = new std::list<XrdProofdClient *>;
1462 clnts->push_back(clnt);
1463 }
1464
1465 // Loop over them
1466 XrdProofdClient *c = 0;
1467 std::list<XrdProofdClient *>::iterator i;
1469 for (i = clnts->begin(); i != clnts->end(); ++i) {
1470 if ((c = *i))
1471 c->Broadcast(msg);
1472 }
1473
1474 // Cleanup, if needed
1475 if (clnt) delete clnts;
1476}
1477
1478////////////////////////////////////////////////////////////////////////////////
1479/// Terminate sessions of client 'clnt' or to of all clients if clnt == 0.
1480/// The list of process IDs having been signalled is returned.
1481
1483 int srvtype)
1484{
1485 XPDLOC(CMGR, "ClientMgr::TerminateSessions")
1486
1487 // The clients to notified
1488 bool all = 0;
1489 std::list<XrdProofdClient *> *clnts;
1490 if (!clnt) {
1491 // The full list
1492 clnts = &fProofdClients;
1493 all = 1;
1494 } else {
1495 clnts = new std::list<XrdProofdClient *>;
1496 clnts->push_back(clnt);
1497 }
1498
1499 // If cleaning all, we send a unique meassge to scan the dirs in one go;
1500 // We first broadcast the message to connected clients.
1501 XrdProofdClient *c = 0;
1502 std::list<XrdProofdClient *>::iterator i;
1504 for (i = clnts->begin(); i != clnts->end(); ++i) {
1505 if ((c = *i)) {
1506 // Notify the attached clients that we are going to cleanup
1507 c->Broadcast(msg);
1508 }
1509 }
1510
1511 TRACE(DBG, "cleaning "<<all);
1512
1513 if (fMgr && fMgr->SessionMgr()) {
1514 int rc = 0;
1515 XrdOucString buf;
1516 XPDFORM(buf, "%s %d", (all ? "all" : clnt->User()), srvtype);
1517 TRACE(DBG, "posting: "<<buf);
1519 buf.c_str())) != 0) {
1520 TRACE(XERR, "problem posting the pipe; errno: "<<-rc);
1521 }
1522 }
1523
1524 // Reset the client instances
1525 for (i = clnts->begin(); i != clnts->end(); ++i) {
1526 if ((c = *i))
1527 c->ResetSessions();
1528 }
1529
1530 // Cleanup, if needed
1531 if (clnt) delete clnts;
1532}
#define SafeDelete(p)
Definition RConfig.hxx:542
#define d(i)
Definition RSha256.hxx:102
#define c(i)
Definition RSha256.hxx:101
#define g(i)
Definition RSha256.hxx:105
#define e(i)
Definition RSha256.hxx:103
virtual RooAbsTestStatistic * create(const char *name, const char *title, RooAbsReal &real, RooAbsData &data, const RooArgSet &projDeps, Configuration const &cfg)=0
#define TRACE(Flag, Args)
Definition TGHtml.h:121
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
#define kXPD_Master
#define kXPD_ClientMaster
#define kXPD_TopMaster
#define kXPD_Admin
#define kXPD_AnyServer
@ kXP_nosession
@ kXP_ServerError
#define kXPD_MasterMaster
#define kXPD_Worker
#define kXPD_MasterWorker
#define kXPD_Internal
@ kXPD_srvmsg
#define XrdSysError
Definition XpdSysError.h:8
#define XrdSysLogger
Definition XpdSysLogger.h:8
#define XrdSysPlugin
Definition XpdSysPlugin.h:8
int DoDirectiveString(XrdProofdDirective *, char *val, XrdOucStream *cfg, bool rcf)
Process directive for a string.
#define XPDFORM
#define SafeFree(x)
int DoDirectiveClass(XrdProofdDirective *, char *val, XrdOucStream *cfg, bool rcf)
Generic class directive processor.
int DoDirectiveInt(XrdProofdDirective *, char *val, XrdOucStream *cfg, bool rcf)
Process directive for an integer.
XrdSecService *(* XrdSecServLoader_t)(XrdSysLogger *, const char *cfn)
void * XrdProofdClientCron(void *p)
This is an endless loop to check the system periodically or when triggered via a message in a dedicat...
static XpdManagerCron_t fManagerCron
#define XPD_NEED_MAP
#define XPD_NEED_AUTH
#define XPD_LOGGEDIN
#define XPD_ADMINUSER
#define XPD_LONGOK(x)
#define XPROOFD_VERSBIN
#define XPD_SETRESP(p, x)
#define TRACEI(id, act, x)
#define XPDLOC(d, x)
#define TRACEP(p, act, x)
#define TRACING(x)
#define XPDERR(x)
#define XrdSysMutexHelper
Definition XrdSysToOuc.h:17
#define XrdSysRecMutex
Definition XrdSysToOuc.h:18
#define free
Definition civetweb.c:1539
#define snprintf
Definition civetweb.c:1540
virtual void Delete(Option_t *option="")
Delete this object.
Definition TObject.cxx:248
int Type() const
XrdProofGroup * GetGroup(const char *grp)
Returns the instance of for group 'grp.
XrdProofGroup * GetUserGroup(const char *usr, const char *grp=0)
Returns the instance of the first group to which this user belongs; if grp != 0, return the instance ...
const char * Name() const
XrdOucString fUser
XrdOucString fGroup
static int GetUserInfo(const char *usr, XrdProofUI &ui)
Get information about user 'usr' in a thread safe way.
static int ParseUsrGrp(const char *path, XrdOucString &usr, XrdOucString &grp)
Parse a path in the form of "<usr>[.<grp>][.<pid>]", filling 'usr' and 'grp'.
static int AssertDir(const char *path, XrdProofUI ui, bool changeown)
Make sure that 'path' exists and is owned by the entity described by 'ui'.
static int GetIDFromPath(const char *path, XrdOucString &emsg)
Extract an integer from a file.
static int Write(int fd, const void *buf, size_t nb)
Write nb bytes at buf to descriptor 'fd' ignoring interrupts Return the number of bytes written or -1...
static int RmDir(const char *path)
Remove directory at path and its content.
static int CheckIf(XrdOucStream *s, const char *h)
Check existence and match condition of an 'if' directive If none (valid) is found,...
int Auth(XrdProofdProtocol *xp)
Analyse client authentication info.
XrdOucString fClntAdminPath
int CreateAdminPath(XrdProofdProtocol *p, XrdOucString &path, XrdOucString &e)
Create the client directory in the admin path.
int CheckAdminPath(XrdProofdProtocol *p, XrdOucString &cidpath, XrdOucString &emsg)
Check the old-clients admin for an existing entry for this client and read the client ID;.
int CheckClients()
Regular checks of the client admin path; run by the cron job.
char * FilterSecConfig(int &nd)
Grep directives of the form "xpd.sec...", "sec.protparm" and "sec.protocol" from file 'cfn' and save ...
int CheckClient(XrdProofdProtocol *p, const char *user, XrdOucString &emsg)
Perform checks on the client username.
XrdProofdClientMgr(XrdProofdManager *mgr, XrdProtocol_Config *pi, XrdSysError *e)
Constructor.
std::list< XrdProofdClient * > fProofdClients
XrdProofdClient * GetClient(const char *usr, const char *grp=0, bool create=1)
Handle request for localizing a client instance for {usr, grp} from the list.
XrdProofdManager * fMgr
XrdSysPlugin * fSecPlugin
void Broadcast(XrdProofdClient *c, const char *msg)
Broadcast message 'msg' to the connected instances of client 'clnt' or to all connected instances if ...
void TerminateSessions(XrdProofdClient *c, const char *msg, int srvtype)
Terminate sessions of client 'clnt' or to of all clients if clnt == 0.
int ParsePreviousClients(XrdOucString &emsg)
Client entries for the clients still connected when the daemon terminated.
int Config(bool rcf=0)
Run configuration and parse the entered config directives.
XrdSysRecMutex * fMutex
int MapClient(XrdProofdProtocol *xp, bool all=1)
Process a login request.
XrdProofdPipe * Pipe()
int DoDirectiveClientMgr(char *, XrdOucStream *, bool)
Process 'clientmgr' directive eg: xpd.clientmgr checkfq:120 activityto:600.
void RegisterDirectives()
Register directives for configuration.
int Login(XrdProofdProtocol *xp)
Process a login request.
XrdSecService * LoadSecurity()
Load security framework and plugins, if not already done.
int DoDirective(XrdProofdDirective *d, char *val, XrdOucStream *cfg, bool rcf)
Update the priorities of the active sessions.
XrdSysRecMutex * Mutex() const
bool IsValid() const
int GetClientID(XrdProofdProtocol *p)
Get next free client ID.
const char * User() const
XrdProofdProofServ * GetServer(int psid)
Get from the vector server instance with ID psid.
int SetClientID(int cid, XrdProofdProtocol *p)
Set slot cid to instance 'p'.
bool Match(const char *usr, const char *grp=0)
return TRUE if this instance matches 'id' (and 'grp', if defined)
virtual int Config(bool rcf=0)
void Register(const char *dname, XrdProofdDirective *d)
XrdSysError * fEDest
const char * CfgFile() const
bool ChangeOwn() const
XrdROOTMgr * ROOTMgr() const
XrdProofGroupMgr * GroupsMgr() const
const char * Host() const
bool RemotePLite() const
bool CheckMaster(const char *m)
Check if master 'm' is allowed to connect to this host.
const char * TMPdir() const
const char * EffectiveUser() 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.
XrdProofdProofServMgr * SessionMgr() const
const char * AdminPath() const
int ResolveKeywords(XrdOucString &s, XrdProofdClient *pcl)
Resolve special keywords in 's' for client 'pcl'.
bool IsValid() const
int Recv(XpdMsg &msg)
Recv message from the pipe.
int Poll(int to=-1)
Poll over the read pipe for to secs; return whatever poll returns.
int Post(int type, const char *msg)
Post message on the pipe.
void SetValid(bool valid=1)
void SetConnection(XrdProofdResponse *r)
const char * Ordinal() const
void SetTag(const char *tag)
const char * TraceID() const
void SetTraceID()
Auxilliary set method.
XrdROOT * DefaultVersion() const
Definition XrdROOT.h:121
XrdProofdProofServMgr * fSessionMgr
XrdProofdClientMgr * fClientMgr