00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 #ifdef OLDXRDOUC
00023 #  include "XrdSysToOuc.h"
00024 #  include "XrdOuc/XrdOucError.hh"
00025 #  include "XrdOuc/XrdOucPlugin.hh"
00026 #  include "XrdOuc/XrdOucPthread.hh"
00027 #else
00028 #  include "XrdSys/XrdSysError.hh"
00029 #  include "XrdSys/XrdSysPlugin.hh"
00030 #  include "XrdSys/XrdSysPthread.hh"
00031 #endif
00032 
00033 #include "XrdProofConn.h"
00034 #include "XProofProtocol.h"
00035 
00036 #include "XrdClient/XrdClientConnMgr.hh"
00037 #include "XrdClient/XrdClientConst.hh"
00038 #include "XrdClient/XrdClientDebug.hh"
00039 #include "XrdClient/XrdClientEnv.hh"
00040 #include "XrdClient/XrdClientLogConnection.hh"
00041 #include "XrdClient/XrdClientPhyConnection.hh"
00042 #include "XrdClient/XrdClientMessage.hh"
00043 #include "XrdClient/XrdClientUrlInfo.hh"
00044 #include "XrdNet/XrdNetDNS.hh"
00045 #include "XrdOuc/XrdOucErrInfo.hh"
00046 #include "XrdOuc/XrdOucString.hh"
00047 #include "XrdSec/XrdSecInterface.hh"
00048 
00049 
00050 
00051 #if (defined(SUNCC) || defined(SUN))
00052 #include <sys/isa_defs.h>
00053 #if defined(_ILP32) && (_FILE_OFFSET_BITS != 32)
00054 #undef  _FILE_OFFSET_BITS
00055 #define _FILE_OFFSET_BITS 32
00056 #undef  _LARGEFILE_SOURCE
00057 #endif
00058 #endif
00059 
00060 #ifndef WIN32
00061 #include <dlfcn.h>
00062 #if !defined(__APPLE__)
00063 #include <link.h>
00064 #endif
00065 #endif
00066 
00067 
00068 #include "XrdProofdTrace.h"
00069 
00070 #ifndef WIN32
00071 #include <sys/socket.h>
00072 #include <sys/types.h>
00073 #include <pwd.h>
00074 #else
00075 #include <process.h>
00076 #include <Winsock2.h>
00077 #endif
00078 
00079 
00080 typedef XrdSecProtocol *(*XrdSecGetProt_t)(const char *, const struct sockaddr &,
00081                                            const XrdSecParameters &, XrdOucErrInfo *);
00082 
00083 XrdClientConnectionMgr *XrdProofConn::fgConnMgr = 0;
00084 
00085 
00086 int XrdProofConn::fgMaxTry = 5;
00087 int XrdProofConn::fgTimeWait = 2;  
00088 
00089 XrdSysPlugin *XrdProofConn::fgSecPlugin = 0;       
00090 void         *XrdProofConn::fgSecGetProtocol = 0;  
00091 
00092 #ifndef SafeDelete
00093 #define SafeDelete(x) { if (x) { delete x; x = 0; } }
00094 #endif
00095 #define URLTAG "["<<fUrl.Host<<":"<<fUrl.Port<<"]"
00096 
00097 
00098 XrdProofConn::XrdProofConn(const char *url, char m, int psid, char capver,
00099                            XrdClientAbsUnsolMsgHandler *uh, const char *logbuf)
00100    : fMode(m), fConnected(0), fLogConnID(-1), fStreamid(0), fRemoteProtocol(-1),
00101      fServerProto(-1), fServerType(kSTNone), fSessionID(psid),
00102      fLastErr(kXR_Unsupported), fCapVer(capver), fLoginBuffer(logbuf), fMutex(0),
00103      fConnectInterruptMtx(0), fConnectInterrupt(0),
00104      fPhyConn(0), fUnsolMsgHandler(uh), fSender(0), fSenderArg(0)
00105 {
00106    
00107    
00108    
00109    
00110    
00111    
00112    
00113    
00114    
00115    
00116    
00117    XPDLOC(ALL, "XrdProofConn")
00118 
00119    
00120    fMutex = new XrdSysRecMutex();
00121    fConnectInterruptMtx = new XrdSysRecMutex();
00122 
00123    
00124    if (url && !Init(url)) {
00125       if (GetServType() != kSTProofd)
00126          TRACE(XERR, "XrdProofConn: severe error occurred while opening a"
00127                      " connection" << " to server "<<URLTAG);
00128    }
00129 
00130    return;
00131 }
00132 
00133 
00134 void XrdProofConn::GetRetryParam(int &maxtry, int &timewait)
00135 {
00136    
00137    
00138 
00139    maxtry = fgMaxTry;
00140    timewait = fgTimeWait;
00141 }
00142 
00143 
00144 void XrdProofConn::SetRetryParam(int maxtry, int timewait)
00145 {
00146    
00147    
00148 
00149    fgMaxTry = maxtry;
00150    fgTimeWait = timewait;
00151 }
00152 
00153 
00154 bool XrdProofConn::Init(const char *url)
00155 {
00156    
00157    XPDLOC(ALL, "Conn::Init")
00158 
00159    
00160    if (!fgConnMgr) {
00161       if (!(fgConnMgr = new XrdClientConnectionMgr())) {
00162          TRACE(XERR,"error initializing connection manager");
00163          return 0;
00164       }
00165    }
00166 
00167    
00168    fUrl.TakeUrl(XrdOucString(url));
00169    fUser = fUrl.User.c_str();
00170    
00171    if (fUser.length() <= 0) {
00172       
00173 #ifndef WIN32
00174       struct passwd *pw = getpwuid(getuid());
00175       fUser = pw ? pw->pw_name : "";
00176 #else
00177       char  name[256];
00178       DWORD length = sizeof (name);
00179       ::GetUserName(name, &length);
00180       if (strlen(name) > 1)
00181          fUser = name;
00182 #endif
00183    }
00184    fHost = fUrl.Host.c_str();
00185    fPort = fUrl.Port;
00186 
00187    
00188    Connect();
00189 
00190    
00191    return fConnected;
00192 }
00193 
00194 
00195 void XrdProofConn::Connect()
00196 {
00197    
00198    XPDLOC(ALL, "Conn::Connect")
00199 
00200    
00201    int maxTry = (fgMaxTry > -1) ? fgMaxTry : EnvGetLong(NAME_FIRSTCONNECTMAXCNT);
00202    int timeWait = (fgTimeWait > -1) ? fgTimeWait : EnvGetLong(NAME_CONNECTTIMEOUT);
00203 
00204    fConnected = 0;
00205    int logid = -1;
00206    int i = 0;
00207    for (; (i < maxTry) && (!fConnected); i++) {
00208 
00209       
00210       logid = TryConnect();
00211 
00212       
00213       if (ConnectInterrupt()) {
00214          TRACE(ALL, "got an interrupt while connecting - aborting attempts");
00215          break;
00216       }
00217 
00218       
00219       if (fConnected) {
00220 
00221          
00222          fPort = fUrl.Port;
00223 
00224          if (fPhyConn->IsLogged() == kNo) {
00225             
00226             
00227             TRACE(DBG, "new logical connection ID: "<<logid);
00228 
00229             
00230             if (!GetAccessToSrv()) {
00231                if (GetServType() == kSTProofd) {
00232                   fConnected = 0;
00233                   return;
00234                }
00235                if (fLastErr == kXR_NotAuthorized || fLastErr == kXR_InvalidRequest) {
00236                   
00237                   Close("P");
00238                   XrdOucString msg = fLastErrMsg;
00239                   msg.erase(msg.rfind(":"));
00240                   TRACE(XERR, "failure: " << msg);
00241                   return;
00242                } else {
00243                   TRACE(XERR, "access to server failed (" << fLastErrMsg << ")");
00244                }
00245                fConnected = 0;
00246                continue;
00247             }
00248          }
00249 
00250          
00251          TRACE(DBG, "connection successfully created");
00252          break;
00253 
00254       }
00255 
00256       
00257       TRACE(REQ, "disconnecting");
00258       Close();
00259 
00260       
00261       if (i < maxTry - 1) {
00262          TRACE(DBG, "connection attempt failed: sleep " << timeWait << " secs");
00263          sleep(timeWait);
00264       }
00265 
00266    } 
00267 
00268    
00269    if (!fConnected) {
00270       TRACE(XERR, "failed to connect to " << fUrl.GetUrl());
00271    }
00272 }
00273 
00274 
00275 XrdProofConn::~XrdProofConn()
00276 {
00277    
00278 
00279    
00280    
00281    
00282    if (fRemoteProtocol > 1004) {
00283       
00284       SetConnectInterrupt();
00285       
00286       XrdClientPhyConnLocker pcl(fPhyConn);
00287       
00288       Close();
00289    } else {
00290       Close();
00291    }
00292 
00293    
00294    SafeDelete(fMutex);
00295    SafeDelete(fConnectInterruptMtx);
00296 }
00297 
00298 
00299 void XrdProofConn::ReConnect()
00300 {
00301    
00302    XPDLOC(ALL, "Conn::ReConnect")
00303 
00304    if (!IsValid()) {
00305       if (fRemoteProtocol > 1004) {
00306 
00307          
00308          XrdClientPhyConnLocker pcl(fPhyConn);
00309 
00310          Close();
00311          int maxtry, timewait;
00312          XrdProofConn::GetRetryParam(maxtry, timewait);
00313          XrdProofConn::SetRetryParam(300, 1);
00314          Connect();
00315          XrdProofConn::SetRetryParam();
00316 
00317       } else {
00318          TRACE(DBG, "server does not support reconnections (protocol: %d" <<
00319                     fRemoteProtocol << " < 1005)");
00320       }
00321    }
00322 }
00323 
00324 
00325 int XrdProofConn::TryConnect()
00326 {
00327    
00328    XPDLOC(ALL, "Conn::TryConnect")
00329 
00330    int logid;
00331    logid = -1;
00332 
00333    
00334    char *haddr[10] = {0}, *hname[10] = {0};
00335    int naddr = XrdNetDNS::getAddrName(fUrl.Host.c_str(), 10, haddr, hname);
00336 
00337    int i = 0;
00338    for (; i < naddr; i++ ) {
00339       
00340       fUrl.HostAddr = (const char *) haddr[i];
00341       
00342       fUrl.Host = (const char *) hname[i];
00343       
00344       TRACE(HDBG, "found host "<<fUrl.Host<<" with addr " << fUrl.HostAddr);
00345    }
00346 
00347    
00348    static int servdef = -1;
00349    if (servdef < 0) {
00350       struct servent *ent = getservbyname("proofd", "tcp");
00351       servdef = (ent) ? (int)ntohs(ent->s_port) : 1093;
00352    }
00353    fUrl.Port = (fUrl.Port <= 0) ? servdef : fUrl.Port;
00354 
00355    
00356    if ((logid = fgConnMgr->Connect(fUrl)) < 0) {
00357       TRACE(DBG, "failure creating logical connection to " <<URLTAG);
00358       fLogConnID = logid;
00359       fConnected = 0;
00360       return -1;
00361    }
00362 
00363    
00364    fLogConnID = logid;
00365    fStreamid = fgConnMgr->GetConnection(fLogConnID)->Streamid();
00366    fPhyConn = fgConnMgr->GetConnection(fLogConnID)->GetPhyConnection();
00367    fConnected = 1;
00368 
00369    TRACE(DBG, "connect to "<<URLTAG<<" returned {"<<fLogConnID<<", "<< fStreamid<<"}");
00370 
00371    
00372    
00373    if (fRemoteProtocol < 0)
00374       fRemoteProtocol = fPhyConn->fServerProto;
00375 
00376    
00377    SetAsync(fUnsolMsgHandler);
00378 
00379    
00380    return logid;
00381 }
00382 
00383 
00384 void XrdProofConn::Close(const char *opt)
00385 {
00386    
00387    XPDLOC(ALL, "Conn::Close")
00388 
00389    
00390    if (!fConnected)
00391       return;
00392 
00393    
00394    bool closephys = (opt[0] == 'P') ? 1 : 0;
00395    TRACE(DBG, URLTAG <<": closing also physical connection ? "<< closephys);
00396 
00397    
00398    if (fgConnMgr)
00399       fgConnMgr->Disconnect(GetLogConnID(), closephys);
00400 
00401    
00402    fConnected = 0;
00403 
00404    
00405    return;
00406 }
00407 
00408 
00409 UnsolRespProcResult XrdProofConn::ProcessUnsolicitedMsg(XrdClientUnsolMsgSender *,
00410                                                         XrdClientMessage *m)
00411 {
00412    
00413    
00414    
00415    
00416    
00417    XPDLOC(ALL, "Conn::ProcessUnsolicitedMsg")
00418 
00419    TRACE(DBG,"processing unsolicited response");
00420 
00421    if (!m || m->IsError()) {
00422       TRACE(XERR, "Got empty or error unsolicited message");
00423    } else {
00424       
00425       int len = 0;
00426       if ((len = m->DataLen()) < (int)sizeof(kXR_int32)) {
00427          TRACE(XERR, "empty or bad-formed message - ignoring");
00428          return kUNSOL_KEEP;
00429       }
00430       
00431       kXR_int32 acod = 0;
00432       memcpy(&acod, m->GetData(), sizeof(kXR_int32));
00433       
00434       
00435       void *pdata = (void *)((char *)(m->GetData()) + sizeof(kXR_int32));
00436       
00437       
00438       if (acod == kXPD_srvmsg) {
00439          
00440          kXR_int32 opt = 0;
00441          memcpy(&opt, pdata, sizeof(kXR_int32));
00442          opt = ntohl(opt);
00443          if (opt == 0 || opt == 1 || opt == 2) {
00444             
00445             pdata = (void *)((char *)pdata + sizeof(kXR_int32));
00446             len -= sizeof(kXR_int32);
00447          } else {
00448             opt = 1;
00449          }
00450          
00451          if (fSender) {
00452             (*fSender)((const char *)pdata, len, fSenderArg);
00453          }
00454       }
00455    }
00456 
00457    return kUNSOL_KEEP;
00458 }
00459 
00460 
00461 void XrdProofConn::SetAsync(XrdClientAbsUnsolMsgHandler *uh,
00462                             XrdProofConnSender_t sender, void *arg)
00463 {
00464    
00465 
00466    if (fgConnMgr && (fLogConnID > -1)  && fgConnMgr->GetConnection(fLogConnID))
00467       fgConnMgr->GetConnection(fLogConnID)->UnsolicitedMsgHandler = uh;
00468 
00469    
00470    fSender = sender;
00471    fSenderArg = arg;
00472 }
00473 
00474 
00475 XrdClientMessage *XrdProofConn::ReadMsg()
00476 {
00477    
00478 
00479    return (fgConnMgr ? fgConnMgr->ReadMsg(fLogConnID) : (XrdClientMessage *)0);
00480 }
00481 
00482 
00483 XrdClientMessage *XrdProofConn::SendRecv(XPClientRequest *req, const void *reqData,
00484                                          char **answData)
00485 {
00486    
00487    
00488    
00489    
00490    
00491    
00492    XPDLOC(ALL, "Conn::SendRecv")
00493 
00494    XrdClientMessage *xmsg = 0;
00495 
00496    
00497    
00498    
00499    
00500    SetSID(req->header.streamid);
00501 
00502    
00503    if (TRACING(HDBG))
00504       XPD::smartPrintClientHeader(req);
00505 
00506    
00507    int reqDataLen = req->header.dlen;
00508    if (XPD::clientMarshall(req) != 0) {
00509       TRACE(XERR, "problems marshalling "<<URLTAG);
00510       return xmsg;
00511    }
00512    if (LowWrite(req, reqData, reqDataLen) != kOK) {
00513       TRACE(XERR, "problems sending request to server "<<URLTAG);
00514       return xmsg;
00515    }
00516 
00517    
00518    bool needalloc = (answData && !(*answData));
00519 
00520    
00521    
00522    
00523    size_t dataRecvSize = 0;
00524    do {
00525       
00526       
00527       
00528       kXR_int16 xst = kXR_error;
00529       if (!(xmsg = ReadMsg()) || xmsg->IsError()) {
00530          TRACE(XERR, "reading msg from connmgr (server "<<URLTAG<<")");
00531       } else {
00532          
00533          if (TRACING(HDBG))
00534             XPD::smartPrintServerHeader(&(xmsg->fHdr));
00535          
00536          xst = xmsg->HeaderStatus();
00537       }
00538 
00539       
00540       
00541       if ((xst == kXR_ok) || (xst == kXR_oksofar) || (xst == kXR_authmore)) {
00542          if (answData && xmsg->DataLen() > 0) {
00543             if (needalloc) {
00544                *answData = (char *) realloc(*answData, dataRecvSize + xmsg->DataLen());
00545                if (!(*answData)) {
00546                   
00547                   TRACE(XERR, "reallocating "<<dataRecvSize<<" bytes");
00548                   free((void *) *answData);
00549                   *answData = 0;
00550                   SafeDelete(xmsg);
00551                   return xmsg;
00552                }
00553             }
00554             
00555             
00556             memcpy((*answData)+dataRecvSize,
00557                    xmsg->GetData(), xmsg->DataLen());
00558             
00559             
00560             if (TRACING(HDBG)) {
00561                TRACE(DBG, "dumping read data ...");
00562                for (int jj = 0; jj < xmsg->DataLen(); jj++) {
00563                   printf("0x%.2x ", *(((kXR_char *)xmsg->GetData())+jj));
00564                   if (!(jj%10)) printf("\n");
00565                }
00566             }
00567          }
00568          
00569          dataRecvSize += xmsg->DataLen();
00570 
00571       } else if (xst != kXR_error) {
00572          
00573          
00574          TRACE(XERR, "status in reply is unknown ["<<
00575                XPD::convertRespStatusToChar(xmsg->fHdr.status)<<
00576                "] (server "<<URLTAG<<") - Abort");
00577          
00578          SafeDelete(xmsg);
00579          return xmsg;
00580       }
00581       
00582       if (xmsg && (xst == kXR_oksofar) && (xmsg->DataLen() == 0))
00583          return xmsg;
00584 
00585    } while (xmsg && (xmsg->HeaderStatus() == kXR_oksofar));
00586 
00587    
00588    if (xmsg)
00589       xmsg->fHdr.dlen = dataRecvSize;
00590 
00591    return xmsg;
00592 }
00593 
00594 
00595 XrdClientMessage *XrdProofConn::SendReq(XPClientRequest *req, const void *reqData,
00596                                         char **answData, const char *CmdName,
00597                                         bool notifyerr)
00598 {
00599    
00600    XPDLOC(ALL, "Conn::SendReq")
00601 
00602    XrdClientMessage *answMex = 0;
00603 
00604    TRACE(DBG,"len: "<<req->sendrcv.dlen);
00605 
00606    int retry = 0;
00607    bool resp = 0, abortcmd = 0;
00608    int maxTry = (fgMaxTry > -1) ? fgMaxTry : kXR_maxReqRetry;
00609 
00610    
00611    XPClientRequest reqsave;
00612    memcpy(&reqsave, req, sizeof(XPClientRequest));
00613 
00614    while (!abortcmd && !resp) {
00615 
00616       TRACE(HDBG, this << " locking phyconn: "<<fPhyConn);
00617 
00618       
00619       abortcmd = 0;
00620 
00621       
00622       memcpy(req, &reqsave, sizeof(XPClientRequest));
00623 
00624       
00625       
00626       TRACE(DBG,"calling SendRecv");
00627       answMex = SendRecv(req, reqData, answData);
00628 
00629       
00630       
00631       retry++;
00632       if (!answMex || answMex->IsError()) {
00633 
00634          TRACE(DBG, "communication error detected with "<<URLTAG);
00635          if (retry > maxTry) {
00636             TRACE(XERR,"max number of retries reached - Abort");
00637             abortcmd = 1;
00638          } else {
00639             if (!IsValid()) {
00640                
00641                ReConnect();
00642                if (!IsValid()) {
00643                   TRACE(XERR,"not connected: nothing to do");
00644                   break;
00645                }
00646             }
00647             abortcmd = 0;
00648             
00649             memcpy(req, &reqsave, sizeof(XPClientRequest));
00650          }
00651       } else {
00652 
00653          
00654          
00655          resp = CheckResp(&(answMex->fHdr), CmdName, notifyerr);
00656 
00657          
00658          
00659          if (!resp)
00660             abortcmd = CheckErrorStatus(answMex, retry, CmdName, notifyerr);
00661 
00662          if (retry > maxTry) {
00663             TRACE(XERR,"max number of retries reached - Abort");
00664             abortcmd = 1;
00665          }
00666       }
00667       if (abortcmd) {
00668          
00669          SafeDelete(answMex);
00670       } else if (!resp) {
00671          
00672          int sleeptime = 1;
00673          TRACE(DBG,"sleep "<<sleeptime<<" secs ...");
00674          sleep(sleeptime);
00675       }
00676    }
00677 
00678    
00679    return answMex;
00680 }
00681 
00682 
00683 bool XrdProofConn::CheckResp(struct ServerResponseHeader *resp,
00684                              const char *method, bool notifyerr)
00685 {
00686    
00687    
00688    
00689    XPDLOC(ALL, "Conn::CheckResp")
00690 
00691    if (MatchStreamID(resp)) {
00692 
00693       if (resp->status != kXR_ok && resp->status != kXR_authmore &&
00694           resp->status != kXR_wait) {
00695          if (notifyerr) {
00696             TRACE(XERR,"server "<<URLTAG<<
00697                        " did not return OK replying to last request");
00698          }
00699          return 0;
00700       }
00701       return 1;
00702 
00703    } else {
00704       if (notifyerr) {
00705          TRACE(XERR, method << " return message not belonging to this client"
00706                                " - protocol error");
00707       }
00708       return 0;
00709    }
00710 }
00711 
00712 
00713 bool XrdProofConn::MatchStreamID(struct ServerResponseHeader *ServerResponse)
00714 {
00715    
00716 
00717    char sid[2];
00718 
00719    memcpy(sid, &fStreamid, sizeof(sid));
00720 
00721    
00722    return (memcmp(ServerResponse->streamid, sid, sizeof(sid)) == 0 );
00723 }
00724 
00725 
00726 void XrdProofConn::SetSID(kXR_char *sid) {
00727    
00728 
00729    memcpy((void *)sid, (const void*)&fStreamid, 2);
00730 }
00731 
00732 
00733 XReqErrorType XrdProofConn::LowWrite(XPClientRequest *req, const void* reqData,
00734                                      int reqDataLen)
00735 {
00736    
00737    
00738    XPDLOC(ALL, "Conn::LowWrite")
00739 
00740    
00741    XrdClientPhyConnLocker pcl(fPhyConn);
00742    int wc = 0;
00743 
00744    
00745    
00746    int len = sizeof(req->header);
00747    if ((wc = WriteRaw(req, len)) != len) {
00748       TRACE(XERR, "sending header to server "<<URLTAG<<" (rc="<<wc<<")");
00749       return kWRITE;
00750    }
00751 
00752    
00753    
00754    if (reqDataLen > 0) {
00755       
00756       if ((wc = WriteRaw(reqData, reqDataLen)) != reqDataLen) {
00757          TRACE(XERR, "sending data ("<<reqDataLen<<" bytes) to server "<<URLTAG<<
00758                     " (rc="<<wc<<")");
00759          return kWRITE;
00760       }
00761    }
00762 
00763    return kOK;
00764 }
00765 
00766 
00767 bool XrdProofConn::CheckErrorStatus(XrdClientMessage *mex, int &Retry,
00768                                     const char *CmdName, bool notifyerr)
00769 {
00770    
00771    XPDLOC(ALL, "Conn::CheckErrorStatus")
00772 
00773    TRACE(DBG, "parsing reply from server "<<URLTAG);
00774 
00775    if (mex->HeaderStatus() == kXR_error) {
00776       
00777       
00778       
00779 
00780       struct ServerResponseBody_Error *body_err;
00781 
00782       body_err = (struct ServerResponseBody_Error *)mex->GetData();
00783 
00784       if (body_err) {
00785          fLastErr = (XErrorCode)ntohl(body_err->errnum);
00786          fLastErrMsg = body_err->errmsg;
00787          if (notifyerr) {
00788             
00789             if (fLastErr == (XErrorCode)kXP_reconnecting) {
00790                TRACE(XERR, fLastErrMsg);
00791             } else {
00792                TRACE(XERR,"error "<<fLastErr<<": '"<<fLastErrMsg<<"'");
00793             }
00794          }
00795       }
00796       if (fLastErr == (XErrorCode)kXP_reconnecting)
00797          return 0;
00798       return 1;
00799    }
00800 
00801    if (mex->HeaderStatus() == kXR_wait) {
00802       
00803       
00804       
00805 
00806       struct ServerResponseBody_Wait *body_wait;
00807 
00808       body_wait = (struct ServerResponseBody_Wait *)mex->GetData();
00809 
00810       if (body_wait) {
00811          int sleeptime = ntohl(body_wait->seconds);
00812          if (mex->DataLen() > 4) {
00813             TRACE(DBG,"wait request ("<<sleeptime<<
00814                   " secs); message: "<<(const char*)body_wait->infomsg);
00815          } else {
00816             TRACE(DBG,"wait request ("<<sleeptime<<" secs)");
00817          }
00818          sleep(sleeptime);
00819       }
00820 
00821       
00822       Retry--;
00823       return 0;
00824    }
00825 
00826    
00827    TRACE(XERR,"after: "<<CmdName<<": server reply not recognized - protocol error");
00828 
00829    return 1;
00830 }
00831 
00832 
00833 bool XrdProofConn::GetAccessToSrv()
00834 {
00835    
00836    
00837    XPDLOC(ALL, "Conn::GetAccessToSrv")
00838 
00839    
00840    {  XrdClientPhyConnLocker pcl(fPhyConn);
00841       fServerType = DoHandShake();
00842    }
00843 
00844    switch (fServerType) {
00845 
00846    case kSTXProofd:
00847 
00848       TRACE(DBG,"found server at "<<URLTAG);
00849 
00850       
00851       fPhyConn->StartReader();
00852       fPhyConn->fServerType = kSTBaseXrootd;
00853       break;
00854 
00855    case kSTProofd:
00856       TRACE(DBG,"server at "<<URLTAG<<" is a proofd");
00857       
00858       kXR_int32 dum[2];
00859       dum[0] = (kXR_int32)htonl(0);
00860       dum[1] = (kXR_int32)htonl(2034);
00861       WriteRaw(&dum[0], sizeof(dum));
00862       Close("P");
00863       return 0;
00864 
00865    case kSTError:
00866       TRACE(XERR,"handShake failed with server "<<URLTAG);
00867       Close("P");
00868       return 0;
00869 
00870    case kSTNone:
00871       TRACE(XERR,"server at "<<URLTAG<<" is unknown");
00872       Close("P");
00873       return 0;
00874    }
00875 
00876    bool ok = (fPhyConn->IsLogged() == kNo) ? Login() : 1;
00877    if (!ok) {
00878       TRACE(XERR,"client could not login at "<<URLTAG);
00879       return ok;
00880    }
00881 
00882    
00883    return ok;
00884 }
00885 
00886 
00887 int XrdProofConn::WriteRaw(const void *buf, int len)
00888 {
00889    
00890 
00891    if (fgConnMgr)
00892       return fgConnMgr->WriteRaw(fLogConnID, buf, len, 0);
00893 
00894    
00895    return -1;
00896 }
00897 
00898 
00899 int XrdProofConn::ReadRaw(void *buf, int len)
00900 {
00901    
00902 
00903    if (fgConnMgr)
00904       return fgConnMgr->ReadRaw(fLogConnID, buf, len);
00905 
00906    
00907    return -1;
00908 }
00909 
00910 
00911 XrdProofConn::ESrvType XrdProofConn::DoHandShake()
00912 {
00913    
00914    
00915    XPDLOC(ALL, "Conn::DoHandShake")
00916 
00917    
00918    if (fPhyConn->fServerType == kSTBaseXrootd) {
00919 
00920       TRACE(DBG,"already connected to a PROOF server "<<URLTAG);
00921       return kSTXProofd;
00922    }
00923 
00924    
00925    struct ClientInitHandShake initHS;
00926    memset(&initHS, 0, sizeof(initHS));
00927    initHS.third  = (kXR_int32)htonl((int)1);
00928 
00929    
00930    
00931    int len = sizeof(initHS);
00932    TRACE(HDBG, "step 1: sending "<<len<<" bytes to server "<<URLTAG);
00933 
00934    int writeCount = WriteRaw(&initHS, len);
00935    if (writeCount != len) {
00936       TRACE(XERR, "sending "<<len<<" bytes to server "<<URLTAG);
00937       return kSTError;
00938    }
00939 
00940    
00941    kXR_int32 dum[2];
00942    dum[0] = (kXR_int32)htonl(4);
00943    dum[1] = (kXR_int32)htonl(2012);
00944    writeCount = WriteRaw(&dum[0], sizeof(dum));
00945    if (writeCount != sizeof(dum)) {
00946       TRACE(XERR, "sending "<<sizeof(dum)<<" bytes to server "<<URLTAG);
00947       return kSTError;
00948    }
00949 
00950    
00951    ServerResponseType type;
00952    len = sizeof(type);
00953    TRACE(HDBG, "step 2: reading "<<len<<" bytes from server "<<URLTAG);
00954 
00955    
00956    
00957    int readCount = ReadRaw(&type, len); 
00958    if (readCount != len) {
00959       if (readCount == (int)TXSOCK_ERR_TIMEOUT) {
00960          TRACE(ALL,"-----------------------");
00961          TRACE(ALL,"TimeOut condition reached reading from remote server.");
00962          TRACE(ALL,"This may indicate that the server is a 'proofd', version <= 12");
00963          TRACE(ALL,"Retry commenting the 'Plugin.TSlave' line in system.rootrc or adding");
00964          TRACE(ALL,"Plugin.TSlave: ^xpd  TSlave Proof \"TSlave(const char *,const char"
00965                " *,int,const char *, TProof *,ESlaveType,const char *,const char *)\"");
00966          TRACE(ALL,"to your $HOME/.rootrc .");
00967          TRACE(ALL,"-----------------------");
00968       } else {
00969          TRACE(XERR, "reading "<<len<<" bytes from server "<<URLTAG);
00970       }
00971       return kSTError;
00972    }
00973 
00974    
00975    type = ntohl(type);
00976 
00977    
00978    if (type == 0) {
00979 
00980       struct ServerInitHandShake xbody;
00981 
00982       
00983       len = sizeof(xbody);
00984       TRACE(HDBG, "step 3: reading "<<len<<" bytes from server "<<URLTAG);
00985 
00986       readCount = ReadRaw(&xbody, len); 
00987       if (readCount != len) {
00988          TRACE(XERR, "reading "<<len<<" bytes from server "<<URLTAG);
00989          return kSTError;
00990       }
00991 
00992       XPD::ServerInitHandShake2HostFmt(&xbody);
00993 
00994       fRemoteProtocol = xbody.protover;
00995       if (fPhyConn->fServerProto <= 0)
00996          fPhyConn->fServerProto = fRemoteProtocol;
00997 
00998       return kSTXProofd;
00999 
01000    } else if (type == 8) {
01001       
01002       return kSTProofd;
01003    } else {
01004       
01005       TRACE(XERR, "unknown server type ("<<type<<")");
01006       return kSTNone;
01007    }
01008 }
01009 
01010 
01011 int XrdProofConn::GetLowSocket()
01012 {
01013    
01014 
01015    return (fPhyConn ? fPhyConn->GetSocket() : -1);
01016 }
01017 
01018 
01019 bool XrdProofConn::Login()
01020 {
01021    
01022    
01023    XPDLOC(ALL, "Conn::Login")
01024 
01025    XPClientRequest reqhdr, reqsave;
01026 
01027    
01028    memset( &reqhdr, 0, sizeof(reqhdr));
01029 
01030    reqhdr.login.pid = getpid();
01031 
01032    
01033    XrdOucString ug = fUser;
01034    if (fUrl.Passwd.length() > 0) {
01035       ug += ":";
01036       ug += fUrl.Passwd;
01037    }
01038 
01039    
01040    if (ug.length() > 8) {
01041       
01042       
01043       strcpy( (char *)reqhdr.login.username, "?>buf" );
01044       
01045       
01046       if (fLoginBuffer.find("|usr:") == STR_NPOS) {
01047          fLoginBuffer += "|usr:";
01048          fLoginBuffer += ug;
01049       }
01050    } else if (ug.length() >= 0) {
01051       memcpy((void *)reqhdr.login.username, (void *)(ug.c_str()), ug.length());
01052       if (ug.length() < 8) reqhdr.login.username[ug.length()] = '\0';
01053    } else {
01054       strcpy((char *)reqhdr.login.username, "????" );
01055    }
01056 
01057    
01058    
01059    const void *buf = (const void *)(fLoginBuffer.c_str());
01060    reqhdr.header.dlen = fLoginBuffer.length();
01061 
01062    
01063    reqhdr.login.role[0] = fMode;
01064 
01065    
01066    
01067    
01068    short int sessID = fSessionID;
01069    
01070    memcpy(&reqhdr.login.reserved[0], &sessID, 2);
01071 
01072    
01073    reqhdr.login.capver[0] = fCapVer;
01074 
01075    
01076    if (TRACING(DBG)) {
01077       XrdOucString usr((const char *)&reqhdr.login.username[0], 8);
01078       TRACE(DBG, "logging into server "<<URLTAG<<"; pid="<<reqhdr.login.pid<<
01079                  "; uid=" << usr);
01080    }
01081 
01082    
01083    SetSID(reqhdr.header.streamid);
01084    reqhdr.header.requestid = kXP_login;
01085    
01086    memcpy(&reqsave, &reqhdr, sizeof(XPClientRequest));
01087 
01088    
01089    fPhyConn->SetLogged(kNo);
01090 
01091    bool notdone = 1;
01092    bool resp = 1;
01093 
01094 
01095    
01096    XrdSecProtocol *secp = 0;
01097    while (notdone) {
01098 
01099       
01100       char *pltmp = 0;
01101 
01102       
01103       memcpy(&reqhdr, &reqsave, sizeof(XPClientRequest));
01104 
01105       XrdClientMessage *xrsp = SendReq(&reqhdr, buf,
01106                                        &pltmp, "XrdProofConn::Login");
01107       
01108       secp = 0;
01109       char *plref = pltmp;
01110       if (xrsp) {
01111          
01112          
01113          int len = xrsp->DataLen();
01114          if (len >= (int)sizeof(kXR_int32)) {
01115             
01116             kXR_int32 vers = 0;
01117             memcpy(&vers, pltmp, sizeof(kXR_int32));
01118             fRemoteProtocol = ntohl(vers);
01119             pltmp = (char *)((char *)pltmp + sizeof(kXR_int32));
01120             len -= sizeof(kXR_int32);
01121          }
01122          
01123          if (pltmp && (len > 0)) {
01124             
01125             
01126             resp = 0;
01127             
01128             
01129             char *s = 0;
01130             if (EnvGetLong(NAME_DEBUG) > 0) {
01131                s = new char [strlen("XrdSecDEBUG")+20];
01132                sprintf(s, "XrdSecDEBUG=%ld", EnvGetLong(NAME_DEBUG));
01133                putenv(s);
01134             }
01135             
01136             s = new char [strlen("XrdSecUSER")+fUser.length()+2];
01137             sprintf(s, "XrdSecUSER=%s", fUser.c_str());
01138             putenv(s);
01139             
01140             s = new char [strlen("XrdSecHOST")+fHost.length()+2];
01141             sprintf(s, "XrdSecHOST=%s", fHost.c_str());
01142             putenv(s);
01143             
01144             XrdOucString netrc;
01145 #ifndef WIN32
01146             struct passwd *pw = getpwuid(getuid());
01147             if (pw) {
01148                netrc = pw->pw_dir;
01149                netrc += "/.rootnetrc";
01150             }
01151 #endif
01152             if (netrc.length() > 0) {
01153                s = new char [strlen("XrdSecNETRC")+netrc.length()+2];
01154                sprintf(s, "XrdSecNETRC=%s", netrc.c_str());
01155                putenv(s);
01156             }
01157             
01158             
01159             char *plist = new char[len+1];
01160             memcpy(plist, pltmp, len);
01161             plist[len] = 0;
01162             TRACE(DBG, "server requires authentication");
01163 
01164             secp = Authenticate(plist, (int)(len+1));
01165             resp = (secp != 0) ? 1 : 0;
01166 
01167             if (!resp)
01168                
01169                notdone = 0;
01170 
01171             if (plist)
01172                delete[] plist;
01173          } else {
01174             
01175             resp = 1;
01176             notdone = 0;
01177          }
01178          
01179          SafeDelete(xrsp);
01180       } else {
01181          
01182          resp = 0;
01183          notdone = 0;
01184          
01185          if (GetLastErr())
01186             XPDPRT(fHost << ": "<< GetLastErr());
01187       }
01188 
01189       
01190       if (plref)
01191          free(plref);
01192 
01193    }
01194 
01195    
01196    if (resp) {
01197       fPhyConn->SetLogged(kYes);
01198       fPhyConn->SetSecProtocol(secp);
01199    }
01200 
01201    
01202    return resp;
01203 }
01204 
01205 
01206 XrdSecProtocol *XrdProofConn::Authenticate(char *plist, int plsiz)
01207 {
01208    
01209    
01210    
01211    XPDLOC(ALL, "Conn::Authenticate")
01212 
01213    XrdSecProtocol *protocol = (XrdSecProtocol *)0;
01214 
01215    if (!plist || plsiz <= 0)
01216       return protocol;
01217 
01218    TRACE(DBG, "host "<<URLTAG<< " sent a list of "<<plsiz<<" bytes");
01219    
01220    
01221    
01222    struct sockaddr_in netaddr;
01223    char **hosterrmsg = 0;
01224    if (XrdNetDNS::getHostAddr((char *)fUrl.HostAddr.c_str(),
01225                                 (struct sockaddr &)netaddr, hosterrmsg) <= 0) {
01226       TRACE(XERR, "getHostAddr: "<< *hosterrmsg);
01227       return protocol;
01228    }
01229    netaddr.sin_port   = fUrl.Port;
01230    
01231    
01232    XrdSecParameters  *secToken = 0;
01233    XrdSecCredentials *credentials = 0;
01234 
01235    
01236    
01237    char *bpar = (char *)malloc(plsiz + 1);
01238    if (bpar)
01239       memcpy(bpar, plist, plsiz);
01240    bpar[plsiz] = 0;
01241    XrdSecParameters Parms(bpar, plsiz + 1);
01242 
01243    
01244    if (!fgSecGetProtocol) {
01245       static XrdSysError err(0, "XrdProofConn_");
01246       
01247       if (!fgSecPlugin)
01248          fgSecPlugin = new XrdSysPlugin(&err, "libXrdSec.so");
01249 
01250       
01251       if (!(fgSecGetProtocol = fgSecPlugin->getPlugin("XrdSecGetProtocol"))) {
01252          TRACE(XERR, "unable to load XrdSecGetProtocol()");
01253          return protocol;
01254       }
01255    }
01256    
01257    
01258    while ((protocol = (*((XrdSecGetProt_t)fgSecGetProtocol))((char *)fUrl.Host.c_str(),
01259                                           (const struct sockaddr &)netaddr, Parms, 0))) {
01260       
01261       
01262       XrdOucString protname = protocol->Entity.prot;
01263       
01264       
01265       XrdOucErrInfo ei;
01266       credentials = protocol->getCredentials(0, &ei);
01267       if (!credentials) {
01268          TRACE(XERR, "cannot obtain credentials (protocol: "<<protname<<")");
01269          
01270          fLastErr = kXR_NotAuthorized;
01271          if (fLastErrMsg.length() > 0) fLastErrMsg += ":";
01272          fLastErrMsg += "cannot obtain credentials for protocol: ";
01273          fLastErrMsg += ei.getErrText();
01274          protocol->Delete();
01275          protocol = 0;
01276          continue;
01277       } else {
01278          TRACE(HDBG, "credentials size: " << credentials->size);
01279       }
01280       
01281       
01282       XPClientRequest reqhdr;
01283       memset(reqhdr.auth.reserved, 0, 12);
01284       memset(reqhdr.auth.credtype, 0, 4);
01285       memcpy(reqhdr.auth.credtype, protname.c_str(), protname.length());
01286 
01287       bool failed = 0;
01288       int status = kXR_authmore;
01289       int dlen = 0;
01290       char *srvans = 0;
01291       XrdClientMessage *xrsp = 0;
01292       while (status == kXR_authmore) {
01293          
01294          
01295          SetSID(reqhdr.header.streamid);
01296          reqhdr.header.requestid = kXP_auth;
01297          reqhdr.header.dlen = (credentials) ? credentials->size : 0;
01298          char *credbuf = (credentials) ? credentials->buffer : 0;
01299          xrsp = SendReq(&reqhdr, credbuf, &srvans, "XrdProofConn::Authenticate");
01300          SafeDelete(credentials);
01301          status = (xrsp) ? xrsp->HeaderStatus() : kXR_error;
01302          dlen = (xrsp) ? xrsp->DataLen() : 0;
01303          TRACE(HDBG, "server reply: status: "<<status<<" dlen: "<<dlen);
01304 
01305          if (xrsp && (status == kXR_authmore)) {
01306             
01307             
01308             
01309             
01310             secToken = new XrdSecParameters(srvans, dlen);
01311             
01312             
01313             credentials = protocol->getCredentials(secToken, &ei);
01314             SafeDelete(secToken); 
01315             srvans = 0;
01316             if (!credentials) {
01317                TRACE(XERR, "cannot obtain credentials");
01318                
01319                fLastErr = kXR_NotAuthorized;
01320                if (fLastErrMsg.length() > 0) fLastErrMsg += ":";
01321                fLastErrMsg += "cannot obtain credentials: ";
01322                fLastErrMsg += ei.getErrText();
01323                protocol->Delete();
01324                protocol = 0;
01325                
01326                
01327                
01328                SafeDelete(xrsp);
01329                failed = 1;
01330                break;
01331             } else {
01332                TRACE(HDBG, "credentials size " << credentials->size);
01333             }
01334          } else if (status != kXR_ok) {
01335             
01336             if (GetLastErr())
01337                TRACE(XERR, fHost << ": "<< GetLastErr());
01338             if (protocol) {
01339                protocol->Delete();
01340                protocol = 0;
01341             }
01342          }
01343          
01344          SafeDelete(xrsp);
01345       }
01346 
01347       
01348       if (protocol) {
01349          fLastErr = kXR_Unsupported;
01350          fLastErrMsg = "";
01351          break;
01352       }
01353       
01354       
01355       if (failed) break;
01356    }
01357    if (!protocol) {
01358       TRACE(XERR, "unable to get protocol object.");
01359       
01360       fLastErr = kXR_NotAuthorized;
01361       if (fLastErrMsg.length() > 0) fLastErrMsg += ":";
01362       fLastErrMsg += "unable to get protocol object.";
01363    }
01364 
01365    
01366    
01367    return protocol;
01368 }
01369 
01370 
01371 void XrdProofConn::SetInterrupt()
01372 {
01373    
01374 
01375    if (fPhyConn)
01376       fPhyConn->SetInterrupt();
01377 }
01378 
01379 
01380 void XrdProofConn::SetConnectInterrupt()
01381 {
01382    
01383 
01384    XrdSysMutexHelper mhp(fConnectInterruptMtx);
01385    fConnectInterrupt = 1;
01386 }
01387 
01388 
01389 bool XrdProofConn::ConnectInterrupt()
01390 {
01391    
01392 
01393    bool rc = 0;
01394    {  XrdSysMutexHelper mhp(fConnectInterruptMtx);
01395       rc = fConnectInterrupt;
01396       
01397       fConnectInterrupt = 0;
01398    }
01399    
01400    return rc;
01401 }
01402 
01403 
01404 bool XrdProofConn::IsValid() const
01405 {
01406    
01407 
01408    if (fConnected)
01409       if (fPhyConn && fPhyConn->IsValid())
01410          return 1;
01411    
01412    return 0;
01413 }
01414