XrdProofdClientMgr.cxx

Go to the documentation of this file.
00001 // @(#)root/proofd:$Id: XrdProofdClientMgr.cxx 31441 2009-11-27 07:29:29Z ganis $
00002 // Author: G. Ganis Jan 2008
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // XrdProofdClientMgr                                                   //
00015 //                                                                      //
00016 // Author: G. Ganis, CERN, 2008                                         //
00017 //                                                                      //
00018 // Class managing clients.                                              //
00019 //                                                                      //
00020 //////////////////////////////////////////////////////////////////////////
00021 #include "XrdProofdPlatform.h"
00022 
00023 #ifdef OLDXRDOUC
00024 #  include "XrdOuc/XrdOucError.hh"
00025 #  define XPD_LOG_01 OUC_LOG_01
00026 #else
00027 #  include "XrdSys/XrdSysError.hh"
00028 #  define XPD_LOG_01 SYS_LOG_01
00029 #endif
00030 
00031 #include "Xrd/XrdBuffer.hh"
00032 #include "XrdOuc/XrdOucErrInfo.hh"
00033 #include "XrdOuc/XrdOucStream.hh"
00034 #include "XrdSec/XrdSecInterface.hh"
00035 
00036 #include "XrdProofdClient.h"
00037 #include "XrdProofdClientMgr.h"
00038 #include "XrdProofdManager.h"
00039 #include "XrdProofdProtocol.h"
00040 #include "XrdProofGroup.h"
00041 #include "XrdProofdProofServ.h"
00042 #include "XrdProofdProofServMgr.h"
00043 #include "XrdROOT.h"
00044 
00045 // Tracing utilities
00046 #include "XrdProofdTrace.h"
00047 
00048 static XpdManagerCron_t fManagerCron;
00049 
00050 // Security handle
00051 typedef XrdSecService *(*XrdSecServLoader_t)(XrdSysLogger *, const char *cfn);
00052 
00053 //--------------------------------------------------------------------------
00054 //
00055 // XrdProofdClientCron
00056 //
00057 // Client manager thread
00058 //
00059 //--------------------------------------------------------------------------
00060 void *XrdProofdClientCron(void *p)
00061 {
00062    // This is an endless loop to check the system periodically or when
00063    // triggered via a message in a dedicated pipe
00064    XPDLOC(CMGR, "ClientCron")
00065 
00066    XpdManagerCron_t *mc = (XpdManagerCron_t *)p;
00067    XrdProofdClientMgr *mgr = mc->fClientMgr;
00068    if (!(mgr)) {
00069       TRACE(REQ, "undefined client manager: cannot start");
00070       return (void *)0;
00071    }
00072    XrdProofdProofServMgr *smgr = mc->fSessionMgr;
00073    if (!(mgr)) {
00074       TRACE(REQ, "undefined session manager: cannot start");
00075       return (void *)0;
00076    }
00077 
00078    // Time of last session check
00079    int lastcheck = time(0), ckfreq = mgr->CheckFrequency(), deltat = 0;
00080    while(1) {
00081       // We wait for processes to communicate a session status change
00082       if ((deltat = ckfreq - (time(0) - lastcheck)) <= 0)
00083          deltat = ckfreq;
00084       int pollRet = mgr->Pipe()->Poll(deltat);
00085 
00086       if (pollRet > 0) {
00087          // Read message
00088          XpdMsg msg;
00089          int rc = 0;
00090          if ((rc = mgr->Pipe()->Recv(msg)) != 0) {
00091             XPDERR("problems receiving message; errno: "<<-rc);
00092             continue;
00093          }
00094          // Parse type
00095          XrdOucString buf;
00096          if (msg.Type() == XrdProofdClientMgr::kClientDisconnect) {
00097             // Read admin path and pointer to the client instance
00098             XrdOucString adminpath;
00099             rc = msg.Get(adminpath);
00100             void *cp = 0;
00101             rc = (rc == 0) ? msg.Get(&cp) : rc;
00102             XrdProofdClient *c = (XrdProofdClient *)cp;
00103             int cid = -1;
00104             rc = (rc == 0) ? msg.Get(cid) : rc;
00105             int pid = -1;
00106             rc = (rc == 0) ? msg.Get(pid) : rc;
00107             if (rc != 0) {
00108                TRACE(XERR, "kClientDisconnect: problems parsing message: '"<<
00109                            msg.Buf()<<"'; errno: "<<-rc);
00110                continue;
00111             }
00112             TRACE(DBG, "kClientDisconnect: got: '"<<adminpath<<"', "<<c<<", "<<cid);
00113             if (c) {
00114                // Reset the corresponding client slot in the list of this client
00115                c->ResetClientSlot(cid);
00116             } else {
00117                TRACE(XERR, "kClientDisconnect: problems getting pointer to client instance: "<<c);
00118             }
00119 
00120             // Remove the client admin path
00121             if (adminpath != "????") {
00122                adminpath.erase(adminpath.rfind("/cid"));
00123                if ((rc = XrdProofdAux::RmDir(adminpath.c_str())) != 0) {
00124                   TRACE(XERR, "kClientDisconnect: problems removing admin path; errno: "<<-rc);
00125                   continue;
00126                }
00127             }
00128 
00129             // Tell the session manager that a client has gone
00130             XPDFORM(buf, "%d", pid);
00131             smgr->Pipe()->Post(XrdProofdProofServMgr::kClientDisconnect, buf.c_str());
00132             TRACE(DBG,"sending to ProofServMgr: "<<buf);
00133 
00134          } else {
00135             TRACE(XERR, "unknown type: "<<msg.Type());
00136             continue;
00137          }
00138       } else {
00139          // Run regular checks
00140          mgr->CheckClients();
00141          // Remember when ...
00142          lastcheck = time(0);
00143       }
00144    }
00145 
00146    // Should never come here
00147    return (void *)0;
00148 }
00149 
00150 //______________________________________________________________________________
00151 XrdProofdClientMgr::XrdProofdClientMgr(XrdProofdManager *mgr,
00152                                        XrdProtocol_Config *pi, XrdSysError *e)
00153                   : XrdProofdConfig(pi->ConfigFN, e)
00154 {
00155    // Constructor
00156    XPDLOC(CMGR, "XrdProofdClientMgr")
00157 
00158    fMutex = new XrdSysRecMutex;
00159    fMgr = mgr;
00160    fCIA = 0;
00161    fNDisconnected = 0;
00162    fReconnectTimeOut = 300;
00163    // Defaults can be changed via 'clientmgr'
00164    fActivityTimeOut = 1200;
00165    fCheckFrequency = 60;
00166 
00167    // Init pipe for manager thread
00168    if (!fPipe.IsValid()) {
00169       TRACE(XERR, "unable to generate the pipe");
00170       return;
00171    }
00172 
00173    // Configuration directives
00174    RegisterDirectives();
00175 }
00176 
00177 //__________________________________________________________________________
00178 void XrdProofdClientMgr::RegisterDirectives()
00179 {
00180    // Register directives for configuration
00181 
00182    Register("clientmgr", new XrdProofdDirective("clientmgr", this, &DoDirectiveClass));
00183    Register("seclib", new XrdProofdDirective("seclib",
00184                                    (void *)&fSecLib, &DoDirectiveString, 0));
00185    Register("reconnto", new XrdProofdDirective("reconnto",
00186                                (void *)&fReconnectTimeOut, &DoDirectiveInt));
00187 }
00188 
00189 //______________________________________________________________________________
00190 int XrdProofdClientMgr::DoDirective(XrdProofdDirective *d,
00191                                     char *val, XrdOucStream *cfg, bool rcf)
00192 {
00193    // Update the priorities of the active sessions.
00194    XPDLOC(SMGR, "ClientMgr::DoDirective")
00195 
00196    if (!d)
00197       // undefined inputs
00198       return -1;
00199 
00200    if (d->fName == "clientmgr") {
00201       return DoDirectiveClientMgr(val, cfg, rcf);
00202    }
00203    TRACE(XERR,"unknown directive: "<<d->fName);
00204    return -1;
00205 }
00206 
00207 //______________________________________________________________________________
00208 int XrdProofdClientMgr::DoDirectiveClientMgr(char *val, XrdOucStream *cfg, bool)
00209 {
00210    // Process 'clientmgr' directive
00211    // eg: xpd.clientmgr checkfq:120 activityto:600
00212    XPDLOC(SMGR, "ClientMgr::DoDirectiveClientMgr")
00213 
00214    if (!val || !cfg)
00215       // undefined inputs
00216       return -1;
00217 
00218    int checkfq = -1;
00219    int activityto = -1;
00220 
00221    while (val) {
00222       XrdOucString tok(val);
00223       if (tok.beginswith("checkfq:")) {
00224          tok.replace("checkfq:", "");
00225          checkfq = strtol(tok.c_str(), 0, 10);
00226       } else if (tok.beginswith("activityto:")) {
00227          tok.replace("activityto:", "");
00228          activityto = strtol(tok.c_str(), 0, 10);
00229       }
00230       // Get next
00231       val = cfg->GetWord();
00232    }
00233 
00234    // Check deprecated 'if' directive
00235    if (fMgr->Host() && cfg)
00236       if (XrdProofdAux::CheckIf(cfg, fMgr->Host()) == 0)
00237          return 0;
00238 
00239    // Set the values
00240    fCheckFrequency = (XPD_LONGOK(checkfq) && checkfq > 0) ? checkfq : fCheckFrequency;
00241    fActivityTimeOut = (XPD_LONGOK(activityto) && activityto > 0) ? activityto : fActivityTimeOut;
00242 
00243    XrdOucString msg;
00244    XPDFORM(msg, "checkfq: %d s, activityto: %d s", fCheckFrequency, fActivityTimeOut);
00245    TRACE(ALL, msg);
00246 
00247    return 0;
00248 }
00249 
00250 //__________________________________________________________________________
00251 int XrdProofdClientMgr::Config(bool rcf)
00252 {
00253    // Run configuration and parse the entered config directives.
00254    // Return 0 on success, -1 on error
00255    XPDLOC(CMGR, "ClientMgr::Config")
00256 
00257    // Run first the configurator
00258    if (XrdProofdConfig::Config(rcf) != 0) {
00259       XPDERR("problems parsing file ");
00260       return -1;
00261    }
00262 
00263    XrdOucString msg;
00264    msg = (rcf) ? "re-configuring" : "configuring";
00265    TRACE(ALL, msg.c_str());
00266 
00267    // Admin paths
00268    fClntAdminPath = fMgr->AdminPath();
00269    fClntAdminPath += "/clients";
00270 
00271    // Make sure they exist
00272    XrdProofUI ui;
00273    XrdProofdAux::GetUserInfo(fMgr->EffectiveUser(), ui);
00274    if (XrdProofdAux::AssertDir(fClntAdminPath.c_str(), ui, 1) != 0) {
00275       XPDERR("unable to assert the clients admin path: "<<fClntAdminPath);
00276       fClntAdminPath = "";
00277       return -1;
00278    }
00279    TRACE(ALL, "clients admin path set to: "<<fClntAdminPath);
00280 
00281    // Init place holders for previous active clients, if any
00282    if (ParsePreviousClients(msg) != 0) {
00283       XPDERR("problems parsing previous active clients: "<<msg);
00284    }
00285 
00286    // Initialize the security system if this is wanted
00287    if (!rcf) {
00288       if (fSecLib.length() <= 0) {
00289          TRACE(ALL, "XRD seclib not specified; strong authentication disabled");
00290       } else {
00291          if (!(fCIA = LoadSecurity())) {
00292             XPDERR("unable to load security system.");
00293             return -1;
00294          }
00295          TRACE(ALL, "security library loaded");
00296       }
00297    }
00298 
00299    if (rcf) {
00300       // Re-assign groups
00301       if (fMgr->GroupsMgr() && fMgr->GroupsMgr()->Num() > 0) {
00302          std::list<XrdProofdClient *>::iterator pci;
00303          for (pci = fProofdClients.begin(); pci != fProofdClients.end(); ++pci)
00304             (*pci)->SetGroup(fMgr->GroupsMgr()->GetUserGroup((*pci)->User())->Name());
00305       }
00306    }
00307 
00308    if (!rcf) {
00309       // Start cron thread
00310       pthread_t tid;
00311       // Fill manager pointers structure
00312       fManagerCron.fClientMgr = this;
00313       fManagerCron.fSessionMgr = fMgr->SessionMgr();
00314       if (XrdSysThread::Run(&tid, XrdProofdClientCron,
00315                            (void *)&fManagerCron, 0, "ClientMgr cron thread") != 0) {
00316          XPDERR("could not start cron thread");
00317          return 0;
00318       }
00319       TRACE(ALL, "cron thread started");
00320    }
00321 
00322    // Done
00323    return 0;
00324 }
00325 
00326 //______________________________________________________________________________
00327 int XrdProofdClientMgr::Login(XrdProofdProtocol *p)
00328 {
00329    // Process a login request
00330    XPDLOC(CMGR, "ClientMgr::Login")
00331 
00332    int rc = 0;
00333    XPD_SETRESP(p, "Login");
00334 
00335    TRACEP(p, HDBG, "enter");
00336 
00337    // If this server is explicitely required to be a worker node or a
00338    // submaster, check whether the requesting host is allowed to connect
00339    if (p->Request()->login.role[0] != 'i' &&
00340       (fMgr->SrvType() == kXPD_MasterWorker || fMgr->SrvType() == kXPD_Master)) {
00341       if (!fMgr->CheckMaster(p->Link()->Host())) {
00342          TRACEP(p, XERR,"master not allowed to connect - "
00343                         "ignoring request ("<<p->Link()->Host()<<")");
00344          response->Send(kXR_InvalidRequest,
00345                             "master not allowed to connect - request ignored");
00346          return 0;
00347       }
00348    }
00349 
00350    // If this is the second call (after authentication) we just need mapping
00351    if (p->Status() == XPD_NEED_MAP) {
00352       // Acknowledge the client
00353       response->Send();
00354       p->SetStatus(XPD_LOGGEDIN);
00355       return MapClient(p, 0);
00356    }
00357 
00358    // Make sure the user is not already logged in
00359    if ((p->Status() & XPD_LOGGEDIN)) {
00360       response->Send(kXR_InvalidRequest, "duplicate login; already logged in");
00361       return 0;
00362    }
00363 
00364    // Find out the connection type: 'i', internal, means this is a proofsrv calling back.
00365    bool needauth = 0;
00366    bool ismaster = (fMgr->SrvType() == kXPD_TopMaster || fMgr->SrvType() == kXPD_Master) ? 1 : 0;
00367    switch (p->Request()->login.role[0]) {
00368    case 'A':
00369       p->SetConnType(kXPD_Admin);
00370       response->SetTag("adm");
00371       break;
00372    case 'i':
00373       p->SetConnType(kXPD_Internal);
00374       response->SetTag("int");
00375       break;
00376    case 'M':
00377       if (fMgr->SrvType() == kXPD_AnyServer || ismaster) {
00378          p->SetConnType(kXPD_ClientMaster);
00379          needauth = 1;
00380          response->SetTag("m2c");
00381       } else {
00382          TRACEP(p, XERR,"top master mode not allowed - ignoring request");
00383          response->Send(kXR_InvalidRequest,
00384                             "Server not allowed to be top master - ignoring request");
00385          return 0;
00386       }
00387       break;
00388    case 'm':
00389       if (fMgr->SrvType() == kXPD_AnyServer || ismaster) {
00390          p->SetConnType(kXPD_MasterMaster);
00391          needauth = 1;
00392          response->SetTag("m2m");
00393       } else {
00394          TRACEP(p, XERR,"submaster mode not allowed - ignoring request");
00395          response->Send(kXR_InvalidRequest,
00396                              "Server not allowed to be submaster - ignoring request");
00397          return 0;
00398       }
00399       break;
00400    case 's':
00401       if (fMgr->SrvType() == kXPD_AnyServer || fMgr->SrvType() == kXPD_MasterWorker) {
00402          p->SetConnType(kXPD_MasterWorker);
00403          needauth = 1;
00404          response->SetTag("w2m");
00405       } else {
00406          TRACEP(p, XERR,"worker mode not allowed - ignoring request");
00407          response->Send(kXR_InvalidRequest,
00408                         "Server not allowed to be worker - ignoring request");
00409          return 0;
00410       }
00411       break;
00412    default:
00413       TRACEP(p, XERR, "unknown mode: '" << p->Request()->login.role[0] <<"'");
00414       response->Send(kXR_InvalidRequest, "Server type: invalide mode");
00415       return rc;
00416    }
00417    response->SetTraceID();
00418 
00419    // Get user and group names for the entity requiring to login
00420    int i, pid;
00421    XrdOucString uname, gname;
00422 
00423    // Unmarshall the data: process ID
00424    pid = (int)ntohl(p->Request()->login.pid);
00425    p->SetPid(pid);
00426 
00427    // Username
00428    char un[9];
00429    for (i = 0; i < (int)sizeof(un)-1; i++) {
00430       if (p->Request()->login.username[i] == '\0' || p->Request()->login.username[i] == ' ')
00431          break;
00432       un[i] = p->Request()->login.username[i];
00433    }
00434    un[i] = '\0';
00435    uname = un;
00436 
00437    // Longer usernames are in the attached buffer
00438    if (uname == "?>buf") {
00439       // Attach to buffer
00440       char *buf = p->Argp()->buff;
00441       int   len = p->Request()->login.dlen;
00442       // Extract username
00443       uname.assign(buf,0,len-1);
00444       int iusr = uname.find("|usr:");
00445       if (iusr == -1) {
00446          TRACEP(p, XERR,"long user name not found");
00447          response->Send(kXR_InvalidRequest, "long user name not found");
00448          return 0;
00449       }
00450       uname.erase(0,iusr+5);
00451       uname.erase(uname.find("|"));
00452    }
00453 
00454    // Extract group name, if specified (syntax is uname[:gname])
00455    int ig = uname.find(":");
00456    if (ig != -1) {
00457       gname.assign(uname, ig+1);
00458       uname.erase(ig);
00459       TRACEP(p, DBG, "requested group: "<<gname);
00460    }
00461 
00462    // Here we check if the user is allowed to use the system
00463    // If not, we fail.
00464    XrdOucString emsg;
00465    XrdProofUI ui;
00466    bool su;
00467    if (fMgr->CheckUser(uname.c_str(), ui, emsg, su) != 0) {
00468       XPDFORM(emsg, "username not allowed: %s", uname.c_str());
00469       TRACEP(p, XERR, emsg);
00470       response->Send(kXR_InvalidRequest, emsg.c_str());
00471       return 0;
00472    }
00473    if (su) {
00474       // Update superuser flag
00475       p->SetSuperUser(su);
00476       TRACEP(p, DBG, "request from entity: "<<uname<<":"<<gname<<" (privileged)");
00477    } else {
00478       TRACEP(p, DBG, "request from entity: "<<uname<<":"<<gname);
00479    }
00480 
00481    // Check if user belongs to a group
00482    XrdProofGroup *g = 0;
00483    if (fMgr->GroupsMgr() && fMgr->GroupsMgr()->Num() > 0) {
00484       if (gname.length() > 0) {
00485          g = fMgr->GroupsMgr()->GetGroup(gname.c_str());
00486          if (!g) {
00487             XPDFORM(emsg, "group unknown: %s", gname.c_str());
00488             TRACEP(p, XERR, emsg);
00489             response->Send(kXR_InvalidRequest, emsg.c_str());
00490             return 0;
00491          } else if (strncmp(g->Name(),"default",7) &&
00492                    !g->HasMember(uname.c_str())) {
00493             XPDFORM(emsg, "user %s is not member of group %s", uname.c_str(), gname.c_str());
00494             TRACEP(p, XERR, emsg);
00495             response->Send(kXR_InvalidRequest, emsg.c_str());
00496             return 0;
00497          } else {
00498             if (TRACING(DBG)) {
00499                TRACEP(p, DBG,"group: "<<gname<<" found");
00500                g->Print();
00501             }
00502          }
00503       } else {
00504          g = fMgr->GroupsMgr()->GetUserGroup(uname.c_str());
00505          gname = g ? g->Name() : "default";
00506       }
00507    }
00508    ui.fGroup = gname;
00509 
00510    // Attach-to / Create the XrdProofdClient instance for this user: if login
00511    // fails this will be removed at a later stage
00512    XrdProofdClient *c = GetClient(uname.c_str(), gname.c_str());
00513    if (c) {
00514       if (!c->ROOT())
00515          c->SetROOT(fMgr->ROOTMgr()->DefaultVersion());
00516       if (c->IsValid()) {
00517          // Set the group, if any
00518          c->SetGroup(g->Name());
00519       }
00520    } else {
00521       emsg = "unable to instantiate object for client ";
00522       emsg += uname;
00523       TRACEP(p, XERR, emsg.c_str());
00524       response->Send(kXR_InvalidRequest, emsg.c_str());
00525       return 0;
00526    }
00527    // Save into the protocol instance
00528    p->SetClient(c);
00529 
00530    // Establish IDs for this link
00531    p->Link()->setID(uname.c_str(), pid);
00532    p->SetTraceID();
00533    response->SetTraceID();
00534    p->SetClntCapVer(p->Request()->login.capver[0]);
00535 
00536    // Get the security token for this link. We will either get a token, a null
00537    // string indicating host-only authentication, or a null indicating no
00538    // authentication. We can then optimize of each case.
00539    if (needauth && fCIA) {
00540       const char *pp = fCIA->getParms(i, p->Link()->Name());
00541       if (pp && i ) {
00542          response->SendI((kXR_int32)XPROOFD_VERSBIN, (void *)pp, i);
00543          p->SetStatus((XPD_NEED_MAP | XPD_NEED_AUTH));
00544          return 0;
00545       } else {
00546          response->SendI((kXR_int32)XPROOFD_VERSBIN);
00547          p->SetStatus(XPD_LOGGEDIN);
00548          if (pp)
00549             p->SetAuthEntity();
00550       }
00551    } else {
00552       rc = response->SendI((kXR_int32)XPROOFD_VERSBIN);
00553       p->SetStatus(XPD_LOGGEDIN);
00554    }
00555 
00556    // Map the client
00557    return MapClient(p, 1);
00558 }
00559 
00560 //______________________________________________________________________________
00561 int XrdProofdClientMgr::MapClient(XrdProofdProtocol *p, bool all)
00562 {
00563    // Process a login request
00564    XPDLOC(CMGR, "ClientMgr::MapClient")
00565 
00566    int rc = 0;
00567    XPD_SETRESP(p, "MapClient");
00568 
00569    XrdOucString msg;
00570 
00571    TRACEP(p, HDBG, "all: "<< all);
00572 
00573    // Attach to the client
00574    XrdProofdClient *pc = p->Client();
00575 
00576    // Map the existing session, if found
00577    if (!pc || !pc->IsValid()) {
00578       if (pc) {
00579          {  // Remove from the list
00580             XrdSysMutexHelper mh(fMutex);
00581             fProofdClients.remove(pc);
00582          }
00583          SafeDelete(pc);
00584          p->SetClient(0);
00585       }
00586       TRACEP(p, DBG, "cannot find valid instance of XrdProofdClient");
00587       response->Send(kXP_ServerError,
00588                      "MapClient: cannot find valid instance of XrdProofdClient");
00589       return 0;
00590    }
00591 
00592    // Flag for internal connections
00593    bool proofsrv = ((p->ConnType() == kXPD_Internal) && all) ? 1 : 0;
00594 
00595    // If call back from proofsrv, find out the target session
00596    short int psid = -1;
00597    char protver = -1;
00598    short int clientvers = -1;
00599    if (proofsrv) {
00600       memcpy(&psid, (const void *)&(p->Request()->login.reserved[0]), 2);
00601       if (psid < 0) {
00602          TRACEP(p, XERR, "proofsrv callback: sent invalid session id");
00603          response->Send(kXR_InvalidRequest,
00604                         "MapClient: proofsrv callback: sent invalid session id");
00605          return 0;
00606       }
00607       protver = p->Request()->login.capver[0];
00608       TRACEP(p, DBG, "proofsrv callback for session: " <<psid);
00609    } else {
00610       // Get PROOF version run by client
00611       memcpy(&clientvers, (const void *)&(p->Request()->login.reserved[0]), 2);
00612       TRACEP(p, DBG, "PROOF version run by client: " <<clientvers);
00613    }
00614 
00615    // If proofsrv, locate the target session
00616    if (proofsrv) {
00617       XrdProofdProofServ *psrv = pc->GetServer(psid);
00618       if (!psrv) {
00619          TRACEP(p, XERR, "proofsrv callback: wrong target session: "<<psid<<" : protocol error");
00620          response->Send(kXP_nosession, "MapClient: proofsrv callback:"
00621                                        " wrong target session: protocol error");
00622          return -1;
00623       } else {
00624          // Set the protocol version
00625          psrv->SetProtVer(protver);
00626          // Assign this link to it
00627          XrdProofdResponse *resp = p->Response(1);
00628          psrv->SetConnection(resp);
00629          psrv->SetValid(1);
00630          // Set Trace ID
00631          XrdOucString tid;
00632          XPDFORM(tid, "xrd->%s", psrv->Ordinal());
00633          resp->SetTag(tid.c_str());
00634          resp->SetTraceID();
00635          TRACEI(resp->TraceID(), DBG, "proofsrv callback: link assigned to target session "<<psid);
00636       }
00637    } else {
00638 
00639       // Only one instance of this client can map at a time
00640       XrdSysMutexHelper mhc(pc->Mutex());
00641 
00642       // Make sure that the version is filled correctly (if an admin operation
00643       // was run before this may still be -1 on workers)
00644       p->SetProofProtocol(clientvers);
00645 
00646       // Check if we have already an ID for this client from a previous connection
00647       XrdOucString cpath;
00648       int cid = -1;
00649       if ((cid = CheckAdminPath(p, cpath, msg)) >= 0) {
00650          // Assign the slot
00651          pc->SetClientID(cid, p);
00652          // The index of the next free slot will be the unique ID
00653          p->SetCID(cid);
00654          // Remove the file indicating that this client was still disconnected
00655          XrdOucString discpath(cpath, 0, cpath.rfind("/cid"));
00656          discpath += "/disconnected";
00657          if (unlink(discpath.c_str()) != 0) {
00658             XPDFORM(msg, "warning: could not remove %s (errno: %d)", discpath.c_str(), errno);
00659             TRACEP(p, XERR, msg.c_str());
00660          }
00661          // Update counters
00662          fNDisconnected--;
00663 
00664       } else {
00665          // The index of the next free slot will be the unique ID
00666          p->SetCID(pc->GetClientID(p));
00667          // Create the client directory in the admin path
00668          if (CreateAdminPath(p, cpath, msg) != 0) {
00669             TRACEP(p, XERR, msg.c_str());
00670             fProofdClients.remove(pc);
00671             SafeDelete(pc);
00672             p->SetClient(0);
00673             response->Send(kXP_ServerError, msg.c_str());
00674             return 0;
00675          }
00676       }
00677       p->SetAdminPath(cpath.c_str());
00678       XPDFORM(msg, "client ID and admin paths created: %s", cpath.c_str());
00679       TRACEP(p, DBG, msg.c_str());
00680 
00681       TRACEP(p, DBG, "CID: "<<p->CID()<<", size: "<<pc->Size());
00682    }
00683 
00684    // Document this login
00685    if (!(p->Status() & XPD_NEED_AUTH)) {
00686       const char *srvtype[6] = {"ANY", "MasterWorker", "MasterMaster",
00687                                 "ClientMaster", "Internal", "Admin"};
00688       XPDFORM(msg, "user %s logged-in%s; type: %s", pc->User(),
00689                    p->SuperUser() ? " (privileged)" : "", srvtype[p->ConnType()+1]);
00690       TRACEP(p, LOGIN, msg);
00691    }
00692 
00693    // Done
00694    return 0;
00695 }
00696 
00697 //_____________________________________________________________________________
00698 int XrdProofdClientMgr::CreateAdminPath(XrdProofdProtocol *p,
00699                                         XrdOucString &cpath, XrdOucString &emsg)
00700 {
00701    // Create the client directory in the admin path
00702 
00703    if (!p || !p->Link()) {
00704       XPDFORM(emsg, "invalid inputs (p: %p)", p);
00705       return -1;
00706    }
00707 
00708    // Create link ID
00709    XrdOucString lid;
00710    XPDFORM(lid, "%s.%d", p->Link()->Host(), p->Pid());
00711 
00712    // Create the path now
00713    XPDFORM(cpath, "%s/%s", p->Client()->AdminPath(), lid.c_str());
00714    XrdProofUI ui;
00715    XrdProofdAux::GetUserInfo(fMgr->EffectiveUser(), ui);
00716    if (XrdProofdAux::AssertDir(cpath.c_str(), ui, 1) != 0) {
00717       XPDFORM(emsg, "error creating client admin path: %s", cpath.c_str());
00718       return -1;
00719    }
00720    // Save client ID for full recovery
00721    cpath += "/cid";
00722    FILE *fcid = fopen(cpath.c_str(), "w");
00723    if (fcid) {
00724       fprintf(fcid, "%d", p->CID());
00725       fclose(fcid);
00726    } else {
00727       XPDFORM(emsg, "error creating file for client id: %s", cpath.c_str());
00728       return -1;
00729    }
00730    // Done
00731    return 0;
00732 }
00733 
00734 //_____________________________________________________________________________
00735 int XrdProofdClientMgr::CheckAdminPath(XrdProofdProtocol *p,
00736                                        XrdOucString &cidpath, XrdOucString &emsg)
00737 {
00738    // Check the old-clients admin for an existing entry for this client and
00739    // read the client ID;
00740 
00741    emsg = "";
00742    if (!p) {
00743       XPDFORM(emsg, "CheckAdminPath: invalid inputs (p: %p)", p);
00744       return -1;
00745    }
00746 
00747    // Create link ID
00748    XrdOucString lid;
00749    XPDFORM(lid, "%s.%d", p->Link()->Host(), p->Pid());
00750 
00751    // Create the path now
00752    XPDFORM(cidpath, "%s/%s/cid", p->Client()->AdminPath(), lid.c_str());
00753 
00754    // Check last access time
00755    int rc = 0;
00756    bool expired = false;
00757    struct stat st;
00758    if ((rc = stat(cidpath.c_str(), &st)) != 0 ||
00759        (expired = ((int)(time(0) - st.st_atime) > fReconnectTimeOut))) {
00760       if (expired || (rc != 0 && errno != ENOENT)) {
00761          // Remove the file
00762          cidpath.replace("/cid", "");
00763          if (expired)
00764             XPDFORM(emsg, "CheckAdminPath: reconnection timeout expired: remove %s ",
00765                           cidpath.c_str());
00766          else
00767             XPDFORM(emsg, "CheckAdminPath: problems stat'ing %s (errno: %d): remove ",
00768                           cidpath.c_str(), errno);
00769          if (XrdProofdAux::RmDir(cidpath.c_str()) != 0)
00770             emsg += ": failure!";
00771       } else {
00772          XPDFORM(emsg, "CheckAdminPath: no such file %s", cidpath.c_str());
00773       }
00774       return -1;
00775    }
00776 
00777    // Get the client ID for full recovery
00778    return XrdProofdAux::GetIDFromPath(cidpath.c_str(), emsg);
00779 }
00780 
00781 //_____________________________________________________________________________
00782 int XrdProofdClientMgr::ParsePreviousClients(XrdOucString &emsg)
00783 {
00784    // Client entries for the clients still connected when the daemon terminated
00785    XPDLOC(CMGR, "ClientMgr::ParsePreviousClients")
00786 
00787    emsg = "";
00788 
00789    // Open dir
00790    DIR *dir = opendir(fClntAdminPath.c_str());
00791    if (!dir) {
00792       TRACE(XERR, "cannot open dir "<<fClntAdminPath<<" ; error: "<<errno);
00793       return -1;
00794    }
00795    TRACE(DBG, "creating holders for active clients ...");
00796 
00797    // Scan the active sessions admin path
00798    XrdOucString usrpath, cidpath, discpath, usr, grp;
00799    struct dirent *ent = 0;
00800    while ((ent = (struct dirent *)readdir(dir))) {
00801       // Skip the basic entries
00802       if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue;
00803       XPDFORM(usrpath, "%s/%s", fClntAdminPath.c_str(), ent->d_name);
00804       bool rm = 0;
00805       struct stat st;
00806       if (stat(usrpath.c_str(), &st) == 0) {
00807          usr = ent->d_name;
00808          grp = usr;
00809          usr.erase(usr.find('.'));
00810          grp.erase(0, grp.find('.')+1);
00811          TRACE(DBG, "found usr: "<<usr<<", grp: "<<grp);
00812          // Get client instance
00813          XrdProofdClient *c = GetClient(usr.c_str(), grp.c_str());
00814          if (!c) {
00815             XPDFORM(emsg, "ParsePreviousClients: could not get client instance"
00816                           " for {%s, %s}", usr.c_str(), grp.c_str());
00817             rm = 1;
00818          }
00819          // Open user sub-dir
00820          DIR *subdir = 0;
00821          if (!rm && !(subdir = opendir(usrpath.c_str()))) {
00822             TRACE(XERR, "cannot open dir "<<usrpath<<" ; error: "<<errno);
00823             rm = 1;
00824          }
00825          if (!rm) {
00826             bool xrm = 0;
00827             struct dirent *sent = 0;
00828             while ((sent = (struct dirent *)readdir(subdir))) {
00829                // Skip the basic entries
00830                if (!strcmp(sent->d_name, ".") || !strcmp(sent->d_name, "..")) continue;
00831                if (!strcmp(sent->d_name, "xpdsock")) continue;
00832                XPDFORM(cidpath, "%s/%s/cid", usrpath.c_str(), sent->d_name);
00833                // Check last access time
00834                if (stat(cidpath.c_str(), &st) != 0 ||
00835                   (int)(time(0) - st.st_atime) > fReconnectTimeOut) {
00836                   xrm = 1;
00837                }
00838                // Read the client ID and and reserve an entry in the related vector
00839                int cid = (!xrm) ? XrdProofdAux::GetIDFromPath(cidpath.c_str(), emsg) : -1;
00840                if (cid < 0)
00841                   xrm = 1;
00842                // Reserve an entry in the related vector
00843                if (!xrm && c->ReserveClientID(cid) != 0)
00844                   xrm = 1;
00845                // Flag this as disconnected
00846                if (!xrm) {
00847                   XPDFORM(discpath, "%s/%s/disconnected", usrpath.c_str(), sent->d_name);
00848                   FILE *fd = fopen(discpath.c_str(), "w");
00849                   if (!fd) {
00850                      TRACE(XERR, "unable to create path: " <<discpath);
00851                      xrm = 1;
00852                   }
00853                   fclose(fd);
00854                   if (!xrm)
00855                      fNDisconnected++;
00856                }
00857                // If it did not work remove the entry
00858                if (xrm) {
00859                   TRACE(DBG, "removing path: " <<cidpath);
00860                   cidpath.replace("/cid", "");
00861                   XPDFORM(emsg, "ParsePreviousClients: failure: remove %s ", cidpath.c_str());
00862                   if (XrdProofdAux::RmDir(cidpath.c_str()) != 0)
00863                      emsg += ": failure!";
00864                }
00865             }
00866          }
00867          if (subdir)
00868             closedir(subdir);
00869       } else {
00870          rm = 1;
00871       }
00872       // If it did not work remove the entry
00873       if (rm) {
00874          TRACE(DBG, "removing path: " <<usrpath);
00875          XPDFORM(emsg, "ParsePreviousClients: failure: remove %s ", usrpath.c_str());
00876          if (XrdProofdAux::RmDir(usrpath.c_str()) != 0)
00877             emsg += ": failure!";
00878       }
00879    }
00880    // Close the directory
00881    closedir(dir);
00882 
00883    // Notify the number of previously active clients now offline
00884    TRACE(DBG, "found "<<fNDisconnected<<" active clients");
00885 
00886    // Done
00887    return 0;
00888 }
00889 
00890 //_____________________________________________________________________________
00891 int XrdProofdClientMgr::CheckClients()
00892 {
00893    // Regular checks of the client admin path; run by the cron job
00894    XPDLOC(CMGR, "ClientMgr::CheckClients")
00895 
00896    // Open dir
00897    DIR *dir = opendir(fClntAdminPath.c_str());
00898    if (!dir) {
00899       TRACE(XERR, "cannot open dir "<<fClntAdminPath<<" ; error: "<<errno);
00900       return -1;
00901    }
00902    TRACE(REQ, "checking active clients ...");
00903 
00904    // Scan the active sessions admin path
00905    int rc = 0;
00906    XrdOucString usrpath, cidpath, discpath;
00907    struct dirent *ent = 0;
00908    while ((ent = (struct dirent *)readdir(dir))) {
00909       // Skip the basic entries
00910       if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue;
00911       XPDFORM(usrpath, "%s/%s", fClntAdminPath.c_str(), ent->d_name);
00912       bool rm = 0;
00913       XrdProofdClient *c = 0;
00914       struct stat st, xst;
00915       if (stat(usrpath.c_str(), &xst) == 0) {
00916          // Find client instance
00917          XrdOucString usr, grp;
00918          XrdProofdAux::ParseUsrGrp(ent->d_name, usr, grp);
00919          if (!(c = GetClient(usr.c_str(), grp.c_str(), 0))) {
00920             TRACE(XERR, "instance for client "<<ent->d_name<<" not found!");
00921             rm = 1;
00922          }
00923          // Open user sub-dir
00924          DIR *subdir = 0;
00925          if (!rm && !(subdir = opendir(usrpath.c_str()))) {
00926             TRACE(XERR, "cannot open dir "<<usrpath<<" ; error: "<<errno);
00927             rm = 1;
00928          }
00929          if (!rm) {
00930             bool xrm = 0, xclose = 0;
00931             struct dirent *sent = 0;
00932             while ((sent = (struct dirent *)readdir(subdir))) {
00933                // Skip the basic entries
00934                if (!strcmp(sent->d_name, ".") || !strcmp(sent->d_name, "..")) continue;
00935                if (!strcmp(sent->d_name, "xpdsock")) continue;
00936                XPDFORM(discpath, "%s/%s/disconnected", usrpath.c_str(), sent->d_name);
00937                // Client admin path
00938                XPDFORM(cidpath, "%s/%s/cid", usrpath.c_str(), sent->d_name);
00939                // Check last access time
00940                if (stat(cidpath.c_str(), &st) == 0) {
00941                   // If in disconnected state, check if it needs to be cleaned
00942                   if (stat(discpath.c_str(), &xst) == 0) {
00943                      if ((int)(time(0) - st.st_atime) > fReconnectTimeOut) {
00944                         xrm = 1;
00945                      }
00946                   } else {
00947                      // If required, check the recent activity; if inactive since too long
00948                      // we ask the client to proof its vitality; but only once: next time
00949                      // we close the link
00950                      if (fActivityTimeOut > 0 &&
00951                          (int)(time(0) - st.st_atime) > fActivityTimeOut) {
00952                         if (c->Touch() == 1) {
00953                            // The client was already asked to proof its vitality
00954                            // during last cycle and it did not do it, so we close
00955                            // the link
00956                            xclose = 1;
00957                            // This clients looks like disconnected
00958                            FILE *fd = fopen(discpath.c_str(), "w");
00959                            if (!fd) {
00960                               TRACE(XERR, "unable to create path: " <<discpath);
00961                            } else {
00962                               fclose(fd);
00963                            }
00964                         }
00965                      }
00966                   }
00967                } else {
00968                   // No id info, clean
00969                   xrm = 1;
00970                }
00971                // If too old remove the entry
00972                if (xrm) {
00973                   discpath.replace("/disconnected", "");
00974                   TRACE(DBG, "removing path "<<discpath);
00975                   if ((rc = XrdProofdAux::RmDir(discpath.c_str())) != 0) {
00976                      TRACE(XERR, "problems removing "<<discpath<<"; error: "<<-rc);
00977                   }
00978                }
00979                // If inactive since too long, close the associated link
00980                if (xclose) {
00981                   // Get the client id
00982                   XrdOucString emsg;
00983                   int cid = XrdProofdAux::GetIDFromPath(cidpath.c_str(), emsg);
00984                   if (cid >= 0) {
00985                      // Get the XrdProofdProtocol instance
00986                      XrdProofdProtocol *p = c->GetProtocol(cid);
00987                      if (p && p->Link()) {
00988                         // This client will try to reconnect, if alive, so give it
00989                         // some time by skipping the next sessions check
00990                         c->SkipSessionsCheck(0, emsg);
00991                         // Close the associated link; Recycle is called from there
00992                         p->Link()->Close();
00993                      } else {
00994                         TRACE(XERR, "protocol or link associated with ID "<<cid<<" are invalid");
00995                      }
00996                   } else {
00997                      TRACE(XERR, "could not resolve client id from "<<cidpath);
00998                   }
00999 
01000                   discpath.replace("/disconnected", "");
01001                   TRACE(DBG, "removing path "<<discpath);
01002                   if ((rc = XrdProofdAux::RmDir(discpath.c_str())) != 0) {
01003                      TRACE(XERR, "problems removing "<<discpath<<"; error: "<<-rc);
01004                   }
01005                }
01006             }
01007          }
01008          if (subdir)
01009             closedir(subdir);
01010       } else {
01011          rm = 1;
01012       }
01013       // If it did not work remove the entry
01014       if (rm) {
01015          TRACE(DBG, "removing path: " <<usrpath);
01016          if ((rc = XrdProofdAux::RmDir(usrpath.c_str())) != 0) {
01017             TRACE(XERR, "problems removing "<<usrpath<<"; error: "<<-rc);
01018          }
01019       }
01020    }
01021    // Close the directory
01022    closedir(dir);
01023 
01024    // Done
01025    return 0;
01026 }
01027 
01028 //_____________________________________________________________________________
01029 int XrdProofdClientMgr::Auth(XrdProofdProtocol *p)
01030 {
01031    // Analyse client authentication info
01032    XPDLOC(CMGR, "ClientMgr::Auth")
01033 
01034    struct sockaddr netaddr;
01035    XrdSecCredentials cred;
01036    XrdSecParameters *parm = 0;
01037    XrdOucErrInfo     eMsg;
01038    const char *eText;
01039    int rc = 1;
01040    XPD_SETRESP(p, "Auth");
01041 
01042    TRACEP(p, REQ, "enter");
01043 
01044    // Ignore authenticate requests if security turned off
01045    if (!fCIA)
01046       return response->Send();
01047    cred.size   = p->Request()->header.dlen;
01048    cred.buffer = p->Argp()->buff;
01049 
01050    // If we have no auth protocol, try to get it
01051    if (!p->AuthProt()) {
01052       p->Link()->Name(&netaddr);
01053       XrdSecProtocol *ap = 0;
01054       if (!(ap = fCIA->getProtocol(p->Link()->Host(), netaddr, &cred, &eMsg))) {
01055          eText = eMsg.getErrText(rc);
01056          TRACEP(p, XERR, "user authentication failed; "<<eText);
01057          response->Send(kXR_NotAuthorized, eText);
01058          return -EACCES;
01059       }
01060       p->SetAuthProt(ap);
01061       p->AuthProt()->Entity.tident = p->Link()->ID;
01062    }
01063    // Set the wanted login name
01064    char *u = new char[strlen("XrdSecLOGINUSER=")+strlen(p->Client()->User())+2];
01065    sprintf(u, "XrdSecLOGINUSER=%s", p->Client()->User());
01066    putenv(u);
01067 
01068    // Now try to authenticate the client using the current protocol
01069    XrdOucString namsg;
01070    if (!(rc = p->AuthProt()->Authenticate(&cred, &parm, &eMsg))) {
01071 
01072       // Make sure that the user name that we want is allowed
01073       if (p->AuthProt()->Entity.name && strlen(p->AuthProt()->Entity.name) > 0) {
01074          rc  = -1;
01075          if (p->Client() && p->Client()->User() && strlen(p->Client()->User()) > 0) {
01076             XrdOucString usrs(p->AuthProt()->Entity.name);
01077             XrdOucString usr;
01078             int from = 0;
01079             while ((from = usrs.tokenize(usr, from, ',')) != STR_NPOS) {
01080                if ((usr == p->Client()->User())) {
01081                   free(p->AuthProt()->Entity.name);
01082                   p->AuthProt()->Entity.name = strdup(usr.c_str());
01083                   rc = 0;
01084                   break;
01085                }
01086             }
01087             if (rc != 0) {
01088                namsg = "user ";
01089                namsg += p->Client()->User();
01090                namsg += " not authorized to connect";
01091                TRACEP(p, XERR, namsg.c_str());
01092             }
01093          } else {
01094             TRACEP(p, XERR, "user name is empty: protocol error?");
01095          }
01096       } else {
01097          TRACEP(p, XERR, "name of the authenticated entity is empty: protocol error?");
01098          rc = -1;
01099       }
01100 
01101       if (rc == 0) {
01102          const char *msg = (p->Status() & XPD_ADMINUSER) ? " admin login as " : " login as ";
01103          rc = response->Send();
01104          char status = p->Status();
01105          status &= ~XPD_NEED_AUTH;
01106          p->SetStatus(status);
01107          p->SetAuthEntity(&(p->AuthProt()->Entity));
01108          if (p->AuthProt()->Entity.name) {
01109             TRACEP(p, LOGIN, p->Link()->ID << msg << p->AuthProt()->Entity.name);
01110          } else {
01111             TRACEP(p, LOGIN, p->Link()->ID << msg << " nobody");
01112          }
01113          return rc;
01114       }
01115    }
01116 
01117    // If we need to continue authentication, tell the client as much
01118    if (rc > 0) {
01119       TRACEP(p, DBG, "more auth requested; sz: " <<(parm ? parm->size : 0));
01120       if (parm) {
01121          rc = response->Send(kXR_authmore, parm->buffer, parm->size);
01122          delete parm;
01123          return rc;
01124       }
01125       if (p->AuthProt()) {
01126          p->AuthProt()->Delete();
01127          p->SetAuthProt(0);
01128       }
01129       TRACEP(p, XERR, "security requested additional auth w/o parms!");
01130       response->Send(kXP_ServerError, "invalid authentication exchange");
01131       return -EACCES;
01132    }
01133 
01134    // We got an error, bail out
01135    if (p->AuthProt()) {
01136       p->AuthProt()->Delete();
01137       p->SetAuthProt(0);
01138    }
01139    eText = (namsg.length() > 0) ? namsg.c_str() : eMsg.getErrText(rc);
01140    TRACEP(p, XERR, "user authentication failed; "<<eText);
01141    response->Send(kXR_NotAuthorized, eText);
01142    return -EACCES;
01143 }
01144 
01145 //_____________________________________________________________________________
01146 XrdSecService *XrdProofdClientMgr::LoadSecurity()
01147 {
01148    // Load security framework and plugins, if not already done
01149    XPDLOC(CMGR, "ClientMgr::LoadSecurity")
01150 
01151    TRACE(REQ, "LoadSecurity");
01152 
01153    const char *cfn = CfgFile();
01154    const char *seclib = fSecLib.c_str();
01155 
01156    // Make sure the input config file is defined
01157    if (!cfn) {
01158       TRACE(XERR, "config file not specified");
01159       return 0;
01160    }
01161 
01162    // Open the security library
01163    void *lh = 0;
01164    if (!(lh = dlopen(seclib, RTLD_NOW))) {
01165       TRACE(XERR, dlerror()<<" opening shared library "<< seclib);
01166       return 0;
01167    }
01168 
01169    // Get the server object creator
01170    XrdSecServLoader_t ep = 0;
01171    if (!(ep = (XrdSecServLoader_t)dlsym(lh, "XrdSecgetService"))) {
01172       TRACE(XERR, dlerror() <<" finding XrdSecgetService() in "<<seclib);
01173       return 0;
01174    }
01175 
01176    // Extract in a temporary file the directives prefixed "xpd.sec..." (filtering
01177    // out the prefix), "sec.protocol" and "sec.protparm"
01178    int nd = 0;
01179    char *rcfn = FilterSecConfig(nd);
01180    if (!rcfn) {
01181       if (nd == 0) {
01182          // No directives to be processed
01183          TRACE(XERR, "no security directives: strong authentication disabled");
01184          return 0;
01185       }
01186       // Failure
01187       TRACE(XERR, "creating temporary config file");
01188       return 0;
01189    }
01190 
01191    // Get the server object
01192    XrdSecService *cia = 0;
01193    if (!(cia = (*ep)((fEDest ? fEDest->logger() : (XrdSysLogger *)0), rcfn))) {
01194       TRACE(XERR, "Unable to create security service object via " << seclib);
01195       return 0;
01196    }
01197    // Notify
01198    TRACE(ALL, "strong authentication enabled");
01199 
01200    // Unlink the temporary file and cleanup its path
01201    unlink(rcfn);
01202    delete[] rcfn;
01203 
01204    // All done
01205    return cia;
01206 }
01207 
01208 //__________________________________________________________________________
01209 char *XrdProofdClientMgr::FilterSecConfig(int &nd)
01210 {
01211    // Grep directives of the form "xpd.sec...", "sec.protparm" and
01212    // "sec.protocol" from file 'cfn' and save them in a temporary file,
01213    // stripping off the prefix "xpd." when needed.
01214    // If any such directory is found, the full path of the temporary file
01215    // is returned, with the number of directives found in 'nd'.
01216    // Otherwise 0 is returned and '-errno' specified in nd.
01217    // The caller has the responsability to unlink the temporary file and
01218    // to release the memory allocated for the path.
01219    XPDLOC(CMGR, "ClientMgr::FilterSecConfig")
01220 
01221    static const char *pfx[] = { "xpd.sec.", "sec.protparm", "sec.protocol", "set" };
01222    char *rcfn = 0;
01223 
01224    TRACE(REQ, "enter");
01225 
01226    const char *cfn = CfgFile();
01227 
01228    // Make sure that we got an input file path and that we can open the
01229    // associated path.
01230    FILE *fin = 0;
01231    if (!cfn || !(fin = fopen(cfn,"r"))) {
01232       nd = (errno > 0) ? -errno : -1;
01233       return rcfn;
01234    }
01235 
01236    // Read the directives: if an interesting one is found, we create
01237    // the output temporary file
01238    int fd = -1;
01239    char lin[2048];
01240    while (fgets(lin,sizeof(lin),fin)) {
01241       if (!strncmp(lin, pfx[0], strlen(pfx[0])) ||
01242           !strncmp(lin, pfx[1], strlen(pfx[1])) ||
01243           !strncmp(lin, pfx[2], strlen(pfx[2])) ||
01244           !strncmp(lin, pfx[3], strlen(pfx[3]))) {
01245          // Target directive found
01246          nd++;
01247          // Create the output file, if not yet done
01248          if (!rcfn) {
01249             rcfn = new char[strlen(fMgr->TMPdir()) + strlen("/xpdcfn_XXXXXX") + 2];
01250             sprintf(rcfn, "%s/xpdcfn_XXXXXX", fMgr->TMPdir());
01251             if ((fd = mkstemp(rcfn)) < 0) {
01252                delete[] rcfn;
01253                nd = (errno > 0) ? -errno : -1;
01254                fclose(fin);
01255                rcfn = 0;
01256                return rcfn;
01257             }
01258          }
01259          XrdOucString slin = lin;
01260          // Strip the prefix "xpd."
01261          if (slin.beginswith("xpd.")) slin.replace("xpd.","");
01262          // Make keyword substitution
01263          fMgr->ResolveKeywords(slin, 0);
01264          // Write the line to the output file
01265          XrdProofdAux::Write(fd, slin.c_str(), slin.length());
01266       }
01267    }
01268 
01269    // Close files
01270    fclose(fin);
01271    close(fd);
01272 
01273    return rcfn;
01274 }
01275 
01276 //______________________________________________________________________________
01277 XrdProofdClient *XrdProofdClientMgr::GetClient(const char *usr, const char *grp,
01278                                                bool create)
01279 {
01280    // Handle request for localizing a client instance for {usr, grp} from the list.
01281    // Create a new instance, if required; for new instances, use the path at 'sock'
01282    // for the unix socket, or generate a new one, if sock = 0.
01283    XPDLOC(CMGR, "ClientMgr::GetClient")
01284 
01285    TRACE(DBG, "usr: "<< (usr ? usr : "undef")<<", grp:"<<(grp ? grp : "undef"));
01286 
01287    XrdOucString dmsg, emsg;
01288    XrdProofdClient *c = 0;
01289    bool newclient = 0;
01290    std::list<XrdProofdClient *>::iterator i;
01291 
01292    {  XrdSysMutexHelper mh(fMutex);
01293       for (i = fProofdClients.begin(); i != fProofdClients.end(); ++i) {
01294          if ((c = *i) && c->Match(usr,grp)) break;
01295          c = 0;
01296       }
01297    }
01298 
01299    if (!c && create) {
01300       // Is this a potential user?
01301       XrdProofUI ui;
01302       bool su;
01303       if (fMgr->CheckUser(usr, ui, emsg, su) == 0) {
01304          // Yes: create an (invalid) instance of XrdProofdClient:
01305          // It would be validated on the first valid login
01306          ui.fUser = usr;
01307          ui.fGroup = grp;
01308          bool full = (fMgr->SrvType() != kXPD_Worker)  ? 1 : 0;
01309          c = new XrdProofdClient(ui, full, fMgr->ChangeOwn(), fEDest, fClntAdminPath.c_str());
01310          newclient = 1;
01311          bool freeclient = 1;
01312          if (c && c->IsValid()) {
01313             // Locate and set the group, if any
01314             if (fMgr->GroupsMgr() && fMgr->GroupsMgr()->Num() > 0) {
01315                XrdProofGroup *g = fMgr->GroupsMgr()->GetUserGroup(usr, grp);
01316                if (g) {
01317                   c->SetGroup(g->Name());
01318                } else if (TRACING(XERR)) {
01319                   emsg = "group = "; emsg += grp; emsg += " nor found";
01320                }
01321             }
01322             {  XrdSysMutexHelper mh(fMutex);
01323                XrdProofdClient *nc = 0;
01324                for (i = fProofdClients.begin(); i != fProofdClients.end(); ++i) {
01325                   if ((nc = *i) && nc->Match(usr,grp)) break;
01326                   nc = 0;
01327                   newclient = 0;
01328                }
01329                if (!nc) {
01330                   // Add to the list
01331                   fProofdClients.push_back(c);
01332                   freeclient = 0;
01333                }
01334             }
01335             if (freeclient) {
01336                delete c;
01337             } else if (TRACING(DBG)) {
01338                XPDFORM(dmsg, "instance for {client, group} = {%s, %s} created"
01339                              " and added to the list (%p)", usr, grp, c);
01340             }
01341          } else {
01342             if (TRACING(XERR)) {
01343                XPDFORM(dmsg, "instance for {client, group} = {%s, %s} is invalid", usr, grp);
01344             }
01345             SafeDelete(c);
01346          }
01347       } else {
01348          if (TRACING(XERR)) {
01349             XPDFORM(dmsg, "client '%s' unknown or unauthorized: %s", usr, emsg.c_str());
01350          }
01351       }
01352    }
01353 
01354    // Trim the sandbox, if needed
01355    if (c && !newclient) {
01356       if (c->TrimSessionDirs() != 0) {
01357          if (TRACING(XERR)) {
01358             XPDFORM(dmsg, "problems trimming client '%s' sandbox", usr);
01359          }
01360       }
01361    }
01362 
01363    if (dmsg.length() > 0) {
01364       if (TRACING(DBG)) {
01365          TRACE(DBG, dmsg);
01366       } else {
01367          if (emsg.length() > 0) TRACE(XERR, emsg);
01368          TRACE(XERR, dmsg);
01369       }
01370    }
01371 
01372    // Over
01373    return c;
01374 }
01375 
01376 //______________________________________________________________________________
01377 void XrdProofdClientMgr::Broadcast(XrdProofdClient *clnt, const char *msg)
01378 {
01379    // Broadcast message 'msg' to the connected instances of client 'clnt' or to all
01380    // connected instances if clnt == 0.
01381 
01382    // The clients to notified
01383    std::list<XrdProofdClient *> *clnts;
01384    if (!clnt) {
01385       // The full list
01386       clnts = &fProofdClients;
01387    } else {
01388       clnts = new std::list<XrdProofdClient *>;
01389       clnts->push_back(clnt);
01390    }
01391 
01392    // Loop over them
01393    XrdProofdClient *c = 0;
01394    std::list<XrdProofdClient *>::iterator i;
01395    XrdSysMutexHelper mh(fMutex);
01396    for (i = clnts->begin(); i != clnts->end(); ++i) {
01397       if ((c = *i))
01398          c->Broadcast(msg);
01399    }
01400 
01401    // Cleanup, if needed
01402    if (clnt) delete clnts;
01403 }
01404 
01405 //______________________________________________________________________________
01406 void XrdProofdClientMgr::TerminateSessions(XrdProofdClient *clnt, const char *msg,
01407                                            int srvtype)
01408 {
01409    // Terminate sessions of client 'clnt' or to of all clients if clnt == 0.
01410    // The list of process IDs having been signalled is returned.
01411    XPDLOC(CMGR, "ClientMgr::TerminateSessions")
01412 
01413    // The clients to notified
01414    bool all = 0;
01415    std::list<XrdProofdClient *> *clnts;
01416    if (!clnt) {
01417       // The full list
01418       clnts = &fProofdClients;
01419       all = 1;
01420    } else {
01421       clnts = new std::list<XrdProofdClient *>;
01422       clnts->push_back(clnt);
01423    }
01424 
01425    // If cleaning all, we send a unique meassge to scan the dirs in one go;
01426    // We first broadcast the message to connected clients.
01427    XrdProofdClient *c = 0;
01428    std::list<XrdProofdClient *>::iterator i;
01429    XrdSysMutexHelper mh(fMutex);
01430    for (i = clnts->begin(); i != clnts->end(); ++i) {
01431       if ((c = *i)) {
01432          // Notify the attached clients that we are going to cleanup
01433          c->Broadcast(msg);
01434       }
01435    }
01436 
01437    TRACE(DBG, "cleaning "<<all);
01438 
01439    if (fMgr && fMgr->SessionMgr()) {
01440       int rc = 0;
01441       XrdOucString buf;
01442       XPDFORM(buf, "%s %d", (all ? "all" : clnt->User()), srvtype);
01443       TRACE(DBG, "posting: "<<buf);
01444       if ((rc = fMgr->SessionMgr()->Pipe()->Post(XrdProofdProofServMgr::kCleanSessions,
01445                                                  buf.c_str())) != 0) {
01446          TRACE(XERR, "problem posting the pipe; errno: "<<-rc);
01447       }
01448    }
01449 
01450    // Reset the client instances
01451    for (i = clnts->begin(); i != clnts->end(); ++i) {
01452       if ((c = *i))
01453          c->ResetSessions();
01454    }
01455 
01456    // Cleanup, if needed
01457    if (clnt) delete clnts;
01458 }

Generated on Tue Jul 5 14:51:51 2011 for ROOT_528-00b_version by  doxygen 1.5.1