TAuthenticate.cxx

Go to the documentation of this file.
00001 // @(#)root/auth:$Id: TAuthenticate.cxx 36308 2010-10-12 07:13:29Z brun $
00002 // Author: Fons Rademakers   26/11/2000
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, 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 // TAuthenticate                                                        //
00015 //                                                                      //
00016 // An authentication module for ROOT based network services, like rootd //
00017 // and proofd.                                                          //
00018 //                                                                      //
00019 //////////////////////////////////////////////////////////////////////////
00020 
00021 #include "RConfigure.h"
00022 
00023 #include "TAuthenticate.h"
00024 #include "TApplication.h"
00025 #include "THostAuth.h"
00026 #include "TRootSecContext.h"
00027 #include "TPluginManager.h"
00028 #include "TNetFile.h"
00029 #include "TPSocket.h"
00030 #include "TMessage.h"
00031 #include "TSystem.h"
00032 #include "TError.h"
00033 #include "Getline.h"
00034 #include "TROOT.h"
00035 #include "TEnv.h"
00036 #include "TList.h"
00037 #include "NetErrors.h"
00038 #include "TRegexp.h"
00039 #include "TVirtualMutex.h"
00040 #include "TTimer.h"
00041 #include "TBase64.h"
00042 
00043 #ifndef R__LYNXOS
00044 #include <sys/stat.h>
00045 #endif
00046 #include <errno.h>
00047 #include <sys/types.h>
00048 #include <time.h>
00049 #if !defined(R__WIN32) && !defined(R__MACOSX) && !defined(R__FBSD) && \
00050     !defined(R__OBSD)
00051 #include <crypt.h>
00052 #endif
00053 #ifdef WIN32
00054 #  include <io.h>
00055 #endif /* WIN32 */
00056 #if defined(R__LINUX) || defined(R__FBSD) || defined(R__OBSD)
00057 #  include <unistd.h>
00058 #endif
00059 #include <stdlib.h>
00060 #ifndef WIN32
00061 #  include <sys/time.h>
00062 #endif /* WIN32 */
00063 
00064 #if defined(R__ALPHA) || defined(R__SGI) || defined(R__MACOSX)
00065 extern "C" char *crypt(const char *, const char *);
00066 #endif
00067 
00068 #ifdef R__GLBS
00069 #   include <sys/ipc.h>
00070 #   include <sys/shm.h>
00071 #endif
00072 
00073 #ifdef R__SSL
00074 // SSL specific headers
00075 #   include <openssl/bio.h>
00076 #   include <openssl/err.h>
00077 #   include <openssl/pem.h>
00078 #   include <openssl/rand.h>
00079 #   include <openssl/rsa.h>
00080 #   include <openssl/ssl.h>
00081 #endif
00082 
00083 // Statics initialization
00084 TList          *TAuthenticate::fgAuthInfo = 0;
00085 TString         TAuthenticate::fgAuthMeth[] = { "UsrPwd", "SRP", "Krb5",
00086                                                 "Globus", "SSH", "UidGid" };
00087 Bool_t          TAuthenticate::fgAuthReUse;
00088 TString         TAuthenticate::fgDefaultUser;
00089 TDatime         TAuthenticate::fgExpDate;
00090 GlobusAuth_t    TAuthenticate::fgGlobusAuthHook;
00091 Krb5Auth_t      TAuthenticate::fgKrb5AuthHook;
00092 TString         TAuthenticate::fgKrb5Principal;
00093 TDatime         TAuthenticate::fgLastAuthrc;    // Time of last reading of fgRootAuthrc
00094 TString         TAuthenticate::fgPasswd;
00095 TPluginHandler *TAuthenticate::fgPasswdDialog = (TPluginHandler *)(-1);
00096 Bool_t          TAuthenticate::fgPromptUser;
00097 TList          *TAuthenticate::fgProofAuthInfo = 0;
00098 Bool_t          TAuthenticate::fgPwHash;
00099 Bool_t          TAuthenticate::fgReadHomeAuthrc = kTRUE; // on/off search for $HOME/.rootauthrc
00100 TString         TAuthenticate::fgRootAuthrc;    // Path to last rootauthrc-like file read
00101 Int_t           TAuthenticate::fgRSAKey  = -1;  // Default RSA key type to be used
00102 Int_t           TAuthenticate::fgRSAInit = 0;
00103 rsa_KEY         TAuthenticate::fgRSAPriKey;
00104 rsa_KEY_export  TAuthenticate::fgRSAPubExport[2] = {{0,0},{0,0}};
00105 rsa_KEY         TAuthenticate::fgRSAPubKey;
00106 #ifdef R__SSL
00107 BF_KEY          TAuthenticate::fgBFKey;
00108 #endif
00109 SecureAuth_t    TAuthenticate::fgSecAuthHook;
00110 Bool_t          TAuthenticate::fgSRPPwd;
00111 TString         TAuthenticate::fgUser;
00112 Bool_t          TAuthenticate::fgUsrPwdCrypt;
00113 Int_t           TAuthenticate::fgLastError = -1;
00114 Int_t           TAuthenticate::fgAuthTO = -2;       // Timeout value
00115 
00116 // ID of the main thread as unique identifier
00117 Int_t           TAuthenticate::fgProcessID = -1;
00118 
00119 TVirtualMutex *gAuthenticateMutex = 0;
00120 
00121 // Standard version of Sec Context match checking
00122 Int_t StdCheckSecCtx(const char *, TRootSecContext *);
00123 
00124 
00125 ClassImp(TAuthenticate)
00126 
00127 //______________________________________________________________________________
00128 static int auth_rand()
00129 {
00130    // rand() implementation using /udev/random or /dev/random, if available
00131 
00132 #ifndef WIN32
00133    int frnd = open("/dev/urandom", O_RDONLY);
00134    if (frnd < 0) frnd = open("/dev/random", O_RDONLY);
00135    int r;
00136    if (frnd >= 0) {
00137       ssize_t rs = read(frnd, (void *) &r, sizeof(int));
00138       close(frnd);
00139       if (r < 0) r = -r;
00140       if (rs == sizeof(int)) return r;
00141    }
00142    Printf("+++ERROR+++ : auth_rand: neither /dev/urandom nor /dev/random are available or readable!");
00143    struct timeval tv;
00144    if (gettimeofday(&tv,0) == 0) {
00145       int t1, t2;
00146       memcpy((void *)&t1, (void *)&tv.tv_sec, sizeof(int));
00147       memcpy((void *)&t2, (void *)&tv.tv_usec, sizeof(int));
00148       r = t1 + t2;
00149       if (r < 0) r = -r;
00150       return r;
00151    }
00152    return -1;
00153 #else
00154    // No special random device available: use rand()
00155    return rand();
00156 #endif
00157 }
00158 
00159 //______________________________________________________________________________
00160 TAuthenticate::TAuthenticate(TSocket *sock, const char *remote,
00161                              const char *proto, const char *user)
00162 {
00163    // Create authentication object.
00164 
00165    if (gDebug > 2 && gAuthenticateMutex)
00166       Info("Authenticate", "locking mutex (pid:  %d)",gSystem->GetPid());
00167    R__LOCKGUARD2(gAuthenticateMutex);
00168 
00169    // In PROOF decode the buffer sent by the client, if any
00170    if (gROOT->IsProofServ())
00171       ProofAuthSetup();
00172 
00173    // Use the ID of the starting thread as unique identifier
00174    if (fgProcessID < 0)
00175       fgProcessID = gSystem->GetPid();
00176 
00177    if (fgAuthTO == -2)
00178       fgAuthTO = gEnv->GetValue("Auth.Timeout",-1);
00179 
00180    fSocket   = sock;
00181    fRemote   = remote;
00182    fHostAuth = 0;
00183    fVersion  = 5;                // The latest, by default
00184    fSecContext = 0;
00185 
00186    if (gDebug > 2)
00187       Info("TAuthenticate", "Enter: local host: %s, user is: %s (proto: %s)",
00188            gSystem->HostName(), user, proto);
00189 
00190    // Set protocol string.
00191    // Check if version should be different ...
00192    char *pdd;
00193    Int_t servtype = TSocket::kSOCKD;
00194    if (proto && strlen(proto) > 0) {
00195       char *sproto = StrDup(proto);
00196       if ((pdd = strstr(sproto, ":")) != 0) {
00197          int rproto = atoi(pdd + 1);
00198          *pdd = '\0';
00199          if (strstr(sproto, "root") != 0) {
00200             if (rproto < 12 ) {
00201                fVersion = 4;
00202                if (rproto < 11 ) {
00203                   fVersion = 3;
00204                   if (rproto < 9 ) {
00205                      fVersion = 2;
00206                      if (rproto < 8) {
00207                         fVersion = 1;
00208                         if (rproto < 6)
00209                            fVersion = 0;
00210                      }
00211                   }
00212                }
00213             }
00214             servtype = TSocket::kROOTD;
00215          }
00216          if (strstr(sproto, "proof") != 0) {
00217             if (rproto < 11) {
00218                fVersion = 4;
00219                if (rproto < 10) {
00220                   fVersion = 3;
00221                   if (rproto < 8) {
00222                      fVersion = 2;
00223                      if (rproto < 7)
00224                         fVersion = 1;
00225                   }
00226                }
00227             }
00228             servtype = TSocket::kPROOFD;
00229          }
00230          if (gDebug > 3)
00231             Info("TAuthenticate",
00232                  "service: %s (remote protocol: %d): fVersion: %d", sproto,
00233                  rproto, fVersion);
00234       }
00235       fProtocol = sproto;
00236       delete [] sproto;
00237    }
00238 
00239    // Check or get user name
00240    fUser = "";
00241    TString checkUser;
00242    if (user && strlen(user) > 0) {
00243       fUser = user;
00244       checkUser = user;
00245    } else {
00246       UserGroup_t *u = gSystem->GetUserInfo();
00247       if (u)
00248          checkUser = u->fUser;
00249       delete u;
00250    }
00251    fPasswd = "";
00252    fPwHash = kFALSE;
00253    fSRPPwd = kFALSE;
00254 
00255    // Type of RSA key
00256    if (fgRSAKey < 0) {
00257       fgRSAKey  = 0;                // Default key
00258 #if R__SSL
00259       // Another choice possible: check user preferences
00260       if (gEnv->GetValue("RSA.KeyType",0) == 1)
00261          fgRSAKey = 1;
00262 #endif
00263    }
00264    // This is the key actually used: we propose the default
00265    // to the server, and behave according to its reply
00266    fRSAKey = fgRSAKey;
00267    if (gDebug > 3)
00268       Info("TAuthenticate","RSA key: default type %d", fgRSAKey);
00269 
00270    // RSA key generation (one per session)
00271    if (!fgRSAInit) {
00272       GenRSAKeys();
00273       fgRSAInit = 1;
00274    }
00275 
00276    // Check and save the host FQDN ...
00277    TString fqdn;
00278    TInetAddress addr = gSystem->GetHostByName(fRemote);
00279    if (addr.IsValid())
00280       fqdn = addr.GetHostName();
00281    TString fqdnsrv(Form("%s:%d",fqdn.Data(),servtype));
00282 
00283    // Read directives from files; re-read if files have changed
00284    TAuthenticate::ReadRootAuthrc();
00285 
00286    if (gDebug > 3) {
00287       Info("TAuthenticate",
00288            "number of HostAuth Instantiations in memory: %d",
00289            GetAuthInfo()->GetSize());
00290       TAuthenticate::Show("H");
00291       TAuthenticate::Show("P");
00292    }
00293 
00294    // Check the list of auth info for already loaded info about this host
00295    fHostAuth = GetHostAuth(fqdnsrv, checkUser);
00296 
00297    // If for whatever (and unlikely) reason nothing has been found
00298    // we look for the old envs defaulting to method 0 (UsrPwd)
00299    // if they are missing or meaningless
00300    if (!fHostAuth) {
00301 
00302       TString tmp;
00303       if (fProtocol.Contains("proof")) {
00304          tmp = TString(gEnv->GetValue("Proofd.Authentication", "0"));
00305       } else if (fProtocol.Contains("root")) {
00306          tmp = TString(gEnv->GetValue("Rootd.Authentication", "0"));
00307       }
00308       char am[kMAXSEC][10];
00309       Int_t nw = sscanf(tmp.Data(), "%5s %5s %5s %5s %5s %5s",
00310                         am[0], am[1], am[2], am[3], am[4], am[5]);
00311 
00312       Int_t i = 0, nm = 0, me[kMAXSEC];
00313       for( ; i < nw; i++) {
00314          Int_t met = -1;
00315          if (strlen(am[i]) > 1) {
00316             met = GetAuthMethodIdx(am[i]);
00317          } else {
00318             met = atoi(am[i]);
00319          }
00320          if (met > -1 && met < kMAXSEC) {
00321             me[nm++] = met;
00322          }
00323       }
00324 
00325       // Create THostAuth
00326       if (nm)
00327          fHostAuth = new THostAuth(fRemote,fUser,nm,me,0);
00328       else
00329          fHostAuth = new THostAuth(fRemote,fUser,0,(const char *)0);
00330    }
00331 
00332    //
00333    // If generic THostAuth (i.e. with wild card or user == any)
00334    // make a personalized memory copy of this THostAuth
00335    if (strchr(fHostAuth->GetHost(),'*') || strchr(fHostAuth->GetHost(),'*') ||
00336        fHostAuth->GetServer() == -1 ) {
00337       fHostAuth = new THostAuth(*fHostAuth);
00338       fHostAuth->SetHost(fqdn);
00339       fHostAuth->SetUser(checkUser);
00340       fHostAuth->SetServer(servtype);
00341    }
00342 
00343    // If a specific method has been requested via the protocol
00344    // set it as first
00345    Int_t sec = -1;
00346    TString tmp = fProtocol;
00347    tmp.ReplaceAll("root",4,"",0);
00348    tmp.ReplaceAll("proof",5,"",0);
00349    tmp.ReplaceAll("sock",4,"",0);
00350    if (!strncmp(tmp.Data(),"up",2))
00351       sec = 0;
00352    else if (!strncmp(tmp.Data(),"s",1))
00353       sec = 1;
00354    else if (!strncmp(tmp.Data(),"k",1))
00355       sec = 2;
00356    else if (!strncmp(tmp.Data(),"g",1))
00357       sec = 3;
00358    else if (!strncmp(tmp.Data(),"h",1))
00359       sec = 4;
00360    else if (!strncmp(tmp.Data(),"ug",2))
00361       sec = 5;
00362    if (sec > -1 && sec < kMAXSEC) {
00363       if (fHostAuth->HasMethod(sec)) {
00364          fHostAuth->SetFirst(sec);
00365       } else {
00366          char *dtmp = GetDefaultDetails(sec, 1, checkUser);
00367          TString det(dtmp);
00368          fHostAuth->AddFirst(sec, det);
00369          if (dtmp)
00370             delete [] dtmp;
00371       }
00372    }
00373 
00374    // This is what we have in memory
00375    if (gDebug > 3) {
00376       TIter next(fHostAuth->Established());
00377       TRootSecContext *ctx;
00378       while ((ctx = (TRootSecContext *) next()))
00379          ctx->Print("0");
00380    }
00381 }
00382 
00383 //_____________________________________________________________________________
00384 void TAuthenticate::CatchTimeOut()
00385 {
00386    // Called in connection with a timer timeout
00387 
00388    Info("CatchTimeOut", "%d sec timeout expired (protocol: %s)",
00389         fgAuthTO, fgAuthMeth[fSecurity].Data());
00390 
00391    fTimeOut = 1;
00392    if (fSocket)
00393       fSocket->Close("force");
00394 
00395    return;
00396 }
00397 
00398 //______________________________________________________________________________
00399 Bool_t TAuthenticate::Authenticate()
00400 {
00401    // Authenticate to remote rootd or proofd server. Return kTRUE if
00402    // authentication succeeded.
00403 
00404    if (gDebug > 2 && gAuthenticateMutex)
00405       Info("Authenticate", "locking mutex (pid:  %d)",gSystem->GetPid());
00406    R__LOCKGUARD2(gAuthenticateMutex);
00407 
00408    Bool_t rc = kFALSE;
00409    Int_t st = -1;
00410    Int_t remMeth = 0, rMth[kMAXSEC], tMth[kMAXSEC] = {0};
00411    Int_t meth = 0;
00412    char noSupport[80] = { 0 };
00413    char triedMeth[80] = { 0 };
00414    Int_t ntry = 0;
00415 
00416    TString user, passwd;
00417    Bool_t pwhash;
00418 
00419    if (gDebug > 2)
00420       Info("Authenticate", "enter: fUser: %s", fUser.Data());
00421 
00422    //
00423    // Setup timeout timer, if required
00424    TTimer *alarm = 0;
00425    if (fgAuthTO > 0) {
00426       alarm = new TTimer(0, kFALSE);
00427       alarm->SetInterruptSyscalls();
00428       // The method CatchTimeOut will be called at timeout
00429       alarm->Connect("Timeout()", "TAuthenticate", this, "CatchTimeOut()");
00430    }
00431 
00432 negotia:
00433    st = -1;
00434    tMth[meth] = 1;
00435    ntry++;
00436    if (gDebug > 2)
00437       Info("Authenticate", "try #: %d", ntry);
00438 
00439    user = "";
00440    passwd = "";
00441    pwhash = kFALSE;
00442 
00443    // Security level from the list (if not in cleanup mode ...)
00444    fSecurity = (ESecurity) fHostAuth->GetMethod(meth);
00445    fDetails = fHostAuth->GetDetails((Int_t) fSecurity);
00446    if (gDebug > 2)
00447       Info("Authenticate",
00448            "trying authentication: method:%d, default details:%s",
00449            fSecurity, fDetails.Data());
00450 
00451    // Keep track of tried methods in a list
00452    if (strlen(triedMeth) > 0)
00453       snprintf(triedMeth, 80, "%s %s", triedMeth, fgAuthMeth[fSecurity].Data());
00454    else
00455       snprintf(triedMeth, 80, "%s", fgAuthMeth[fSecurity].Data());
00456 
00457    // Set environments
00458    SetEnvironment();
00459 
00460    st = -1;
00461 
00462    //
00463    // Reset timeout variables and start timer
00464    fTimeOut = 0;
00465    if (fgAuthTO > 0 && alarm) {
00466       alarm->Start(fgAuthTO*1000, kTRUE);
00467    }
00468 
00469    // Auth calls depend of fSec
00470    if (fSecurity == kClear) {
00471 
00472       rc = kFALSE;
00473 
00474       // UsrPwd Authentication
00475       user = fgDefaultUser;
00476       if (user != "")
00477          CheckNetrc(user, passwd, pwhash, kFALSE);
00478       if (passwd == "") {
00479          if (fgPromptUser)
00480             user = PromptUser(fRemote);
00481          rc = GetUserPasswd(user, passwd, pwhash, kFALSE);
00482       }
00483       fUser = user;
00484       fPasswd = passwd;
00485 
00486       if (!rc) {
00487 
00488          if (fUser != "root")
00489             st = ClearAuth(user, passwd, pwhash);
00490       } else {
00491          Error("Authenticate",
00492                "unable to get user name for UsrPwd authentication");
00493       }
00494 
00495    } else if (fSecurity == kSRP) {
00496 
00497       rc = kFALSE;
00498 
00499       // SRP Authentication
00500       user = fgDefaultUser;
00501       if (user != "")
00502          CheckNetrc(user, passwd, pwhash, kTRUE);
00503       if (passwd == "") {
00504          if (fgPromptUser)
00505             user = PromptUser(fRemote);
00506          rc = GetUserPasswd(user, passwd, pwhash, kTRUE);
00507       }
00508       fUser = user;
00509       fPasswd = passwd;
00510 
00511       if (!fgSecAuthHook) {
00512 
00513          char *p;
00514          TString lib = "libSRPAuth";
00515          if ((p = gSystem->DynamicPathName(lib, kTRUE))) {
00516             delete [] p;
00517             gSystem->Load(lib);
00518          }
00519       }
00520       if (!rc && fgSecAuthHook) {
00521 
00522          st = (*fgSecAuthHook) (this, user, passwd, fRemote, fDetails,
00523                                 fVersion);
00524       } else {
00525          if (!fgSecAuthHook)
00526             Error("Authenticate",
00527                   "no support for SRP authentication available");
00528          if (rc)
00529             Error("Authenticate",
00530                   "unable to get user name for SRP authentication");
00531       }
00532       // Fill present user info ...
00533       if (st == 1) {
00534          fPwHash = kFALSE;
00535          fSRPPwd = kTRUE;
00536       }
00537 
00538    } else if (fSecurity == kKrb5) {
00539 
00540       if (fVersion > 0) {
00541 
00542          // Kerberos 5 Authentication
00543          if (!fgKrb5AuthHook) {
00544             char *p;
00545             TString lib = "libKrb5Auth";
00546             if ((p = gSystem->DynamicPathName(lib, kTRUE))) {
00547                delete [] p;
00548                gSystem->Load(lib);
00549             }
00550          }
00551          if (fgKrb5AuthHook) {
00552             fUser = fgDefaultUser;
00553             st = (*fgKrb5AuthHook) (this, fUser, fDetails, fVersion);
00554          } else {
00555             Error("Authenticate",
00556                   "support for kerberos5 auth locally unavailable");
00557          }
00558       } else {
00559          if (gDebug > 0)
00560             Info("Authenticate",
00561                  "remote daemon does not support Kerberos authentication");
00562          if (strlen(noSupport) > 0)
00563             snprintf(noSupport, 80, "%s/Krb5", noSupport);
00564          else
00565             snprintf(noSupport, 80, "Krb5");
00566       }
00567 
00568    } else if (fSecurity == kGlobus) {
00569       if (fVersion > 1) {
00570 
00571          // Globus Authentication
00572          if (!fgGlobusAuthHook) {
00573             char *p;
00574             TString lib = "libGlobusAuth";
00575             if ((p = gSystem->DynamicPathName(lib, kTRUE))) {
00576                delete [] p;
00577                gSystem->Load(lib);
00578             }
00579          }
00580          if (fgGlobusAuthHook) {
00581             st = (*fgGlobusAuthHook) (this, fUser, fDetails);
00582          } else {
00583             Error("Authenticate",
00584                   "no support for Globus authentication available");
00585          }
00586       } else {
00587          if (gDebug > 0)
00588             Info("Authenticate",
00589                  "remote daemon does not support Globus authentication");
00590          if (strlen(noSupport) > 0)
00591             snprintf(noSupport, 80, "%s/Globus", noSupport);
00592          else
00593             snprintf(noSupport, 80, "Globus");
00594       }
00595 
00596 
00597    } else if (fSecurity == kSSH) {
00598 
00599       if (fVersion > 1) {
00600 
00601          // SSH Authentication
00602          st = SshAuth(fUser);
00603 
00604       } else {
00605          if (gDebug > 0)
00606             Info("Authenticate",
00607                  "remote daemon does not support SSH authentication");
00608          if (strlen(noSupport) > 0)
00609             snprintf(noSupport, 80, "%s/SSH", noSupport);
00610          else
00611             snprintf(noSupport, 80, "SSH");
00612       }
00613 
00614    } else if (fSecurity == kRfio) {
00615 
00616       if (fVersion > 1) {
00617 
00618          // UidGid Authentication
00619          st = RfioAuth(fUser);
00620 
00621       } else {
00622          if (gDebug > 0)
00623             Info("Authenticate",
00624                  "remote daemon does not support UidGid authentication");
00625          if (strlen(noSupport) > 0)
00626             snprintf(noSupport, 80, "%s/UidGid", noSupport);
00627          else
00628             snprintf(noSupport, 80, "UidGid");
00629       }
00630    }
00631    //
00632    // Stop timer
00633    if (alarm) alarm->Stop();
00634 
00635    // Flag timeout condition
00636    st = (fTimeOut > 0) ? -3 : st;
00637 
00638    //
00639    // Analyse the result now ...
00640    // Type of action after the analysis:
00641    // 0 = return, 1 = negotiation, 2 = send kROOTD_BYE + 3,
00642    // 3 = print failure and return
00643    Int_t action = 0;
00644    Int_t nmet = fHostAuth->NumMethods();
00645    Int_t remloc = nmet - ntry;
00646    if (gDebug > 0)
00647       Info("Authenticate","remloc: %d, ntry: %d, meth: %d, fSecurity: %d",
00648                            remloc, ntry, meth, fSecurity);
00649    Int_t kind, stat;
00650    switch (st) {
00651 
00652    case 1:
00653       //
00654       // Success
00655       fHostAuth->CountSuccess((Int_t)fSecurity);
00656       if (gDebug > 2)
00657          fSecContext->Print();
00658       if (fSecContext->IsActive())
00659          fSecContext->AddForCleanup(fSocket->GetPort(),
00660                                     fSocket->GetRemoteProtocol(),fSocket->GetServType());
00661       rc = kTRUE;
00662       break;
00663 
00664    case 0:
00665       //
00666       // Failure
00667       fHostAuth->CountFailure((Int_t)fSecurity);
00668       if (fVersion < 2) {
00669          //
00670          // Negotiation not supported by old daemons ...
00671          if (gDebug > 2)
00672             Info("Authenticate",
00673                  "negotiation not supported remotely: try next method, if any");
00674          if (meth < nmet - 1) {
00675             meth++;
00676             action = 1;
00677          } else {
00678             action = 2;
00679          }
00680          rc = kFALSE;
00681          break;
00682       }
00683       //
00684       // Attempt negotiation ...
00685       if (fSocket->Recv(stat, kind) < 0) {
00686          action = 0;
00687          rc = kFALSE;
00688       }
00689       if (gDebug > 2)
00690          Info("Authenticate",
00691               "after failed attempt: kind= %d, stat= %d", kind, stat);
00692       if (kind == kROOTD_ERR) {
00693          action = 2;
00694          rc = kFALSE;
00695       } else if (kind == kROOTD_NEGOTIA) {
00696          if (stat > 0) {
00697             int len = 3 * stat;
00698             char *answer = new char[len];
00699             int nrec = fSocket->Recv(answer, len, kind);  // returns user
00700             if (nrec < 0) {
00701                action = 0;
00702                rc = kFALSE;
00703                break;
00704             }
00705             if (kind != kMESS_STRING)
00706                Warning("Authenticate",
00707                        "strings with accepted methods not received (%d:%d)",
00708                        kind, nrec);
00709             remMeth =
00710                sscanf(answer, "%d %d %d %d %d %d", &rMth[0], &rMth[1],
00711                       &rMth[2], &rMth[3], &rMth[4], &rMth[5]);
00712             if (gDebug > 0 && remloc > 0)
00713                Info("Authenticate",
00714                     "remotely allowed methods not yet tried: %s",
00715                     answer);
00716             delete[] answer;
00717          } else if (stat == 0) {
00718             Info("Authenticate",
00719                  "no more methods accepted remotely to be tried");
00720             action = 3;
00721             rc = kFALSE;
00722             break;
00723          }
00724          // If no more local methods, return
00725          if (remloc < 1) {
00726             action = 2;
00727             rc = kFALSE;
00728             break;
00729          }
00730          // Look if a non-tried method matches
00731          int i, j;
00732          char locav[40] = { 0 };
00733          Bool_t methfound = kFALSE;
00734          for (i = 0; i < remMeth; i++) {
00735             for (j = 0; j < nmet; j++) {
00736                if (fHostAuth->GetMethod(j) == rMth[i] && tMth[j] == 0) {
00737                   meth = j;
00738                   action = 1;
00739                   methfound = kTRUE;
00740                   break;
00741                }
00742                if (i == 0)
00743                   snprintf(locav, 40, "%s %d", locav, fHostAuth->GetMethod(j));
00744             }
00745             if (methfound) break;
00746          }
00747          if (methfound) break;
00748          //
00749          // No method left to be tried: notify and exit
00750          if (gDebug > 0)
00751             Warning("Authenticate",
00752                     "no match with those locally available: %s", locav);
00753          action = 2;
00754          rc = kFALSE;
00755          break;
00756       } else {        // unknown message code at this stage
00757          action = 3;
00758          rc = kFALSE;
00759          break;
00760       }
00761       break;
00762 
00763    case -1:
00764       //
00765       // Method not supported
00766       fHostAuth->CountFailure((Int_t)fSecurity);
00767       if (gDebug > 2)
00768          Info("Authenticate",
00769               "method not even started: insufficient or wrong info: %s",
00770               "try with next method, if any");
00771       fHostAuth->RemoveMethod(fSecurity);
00772       nmet--;
00773       if (nmet > 0) {
00774          action = 1;
00775       } else
00776          action = 2;
00777 
00778       break;
00779 
00780    case -2:
00781       //
00782       // Remote host does not accepts connections from local host
00783       fHostAuth->CountFailure((Int_t)fSecurity);
00784       if (fVersion <= 2)
00785          if (gDebug > 2)
00786             Warning("Authenticate",
00787                     "status code -2 not expected from old daemons");
00788       rc = kFALSE;
00789       break;
00790 
00791    case -3:
00792       //
00793       // Timeout: we set the method as last one, should the caller
00794       // decide to retry, if it will attempt first something else.
00795       // (We can not retry directly, because the server will not be
00796       //  synchronized ...)
00797       fHostAuth->CountFailure((Int_t)fSecurity);
00798       if (gDebug > 2)
00799          Info("Authenticate", "got a timeout");
00800       fHostAuth->SetLast(fSecurity);
00801       if (meth < nmet - 1) {
00802          fTimeOut = 2;
00803       } else
00804          fTimeOut = 1;
00805       rc = kFALSE;
00806       break;
00807 
00808    default:
00809       fHostAuth->CountFailure((Int_t)fSecurity);
00810       if (gDebug > 2)
00811          Info("Authenticate", "unknown status code: %d - assume failure",st);
00812       rc = kFALSE;
00813       action = 0;
00814       break;
00815    }
00816 
00817    switch (action) {
00818    case 1:
00819       goto negotia;
00820       // No break but we go away anyhow
00821    case 2:
00822       fSocket->Send("0", kROOTD_BYE);
00823       // fallthrough
00824    case 3:
00825       if (strlen(noSupport) > 0)
00826          Info("Authenticate", "attempted methods %s are not supported"
00827               " by remote server version", noSupport);
00828       Info("Authenticate",
00829            "failure: list of attempted methods: %s", triedMeth);
00830       AuthError("Authenticate",-1);
00831       rc = kFALSE;
00832       break;
00833    default:
00834       break;
00835    }
00836 
00837    // Cleanup timer
00838    if (alarm)
00839       SafeDelete(alarm);
00840 
00841    return rc;
00842 
00843 }
00844 
00845 //______________________________________________________________________________
00846 void TAuthenticate::SetEnvironment()
00847 {
00848    // Set default authentication environment. The values are inferred
00849    // from fSecurity and fDetails.
00850 
00851    R__LOCKGUARD2(gAuthenticateMutex);
00852 
00853    if (gDebug > 2)
00854       Info("SetEnvironment",
00855            "setting environment: fSecurity:%d, fDetails:%s", fSecurity,
00856            fDetails.Data());
00857 
00858    // Defaults
00859    fgDefaultUser = fgUser;
00860    if (fSecurity == kKrb5 ||
00861        (fSecurity == kGlobus && gROOT->IsProofServ()))
00862       fgAuthReUse = kFALSE;
00863    else
00864       fgAuthReUse = kTRUE;
00865    fgPromptUser = kFALSE;
00866 
00867    // Decode fDetails, is non empty ...
00868    if (fDetails != "") {
00869       char usdef[kMAXPATHLEN] = { 0 };
00870       char pt[5] = { 0 }, ru[5] = { 0 };
00871       Int_t hh = 0, mm = 0;
00872       char us[kMAXPATHLEN] = {0}, cp[kMAXPATHLEN] = {0}, pp[kMAXPATHLEN] = {0};
00873       char cd[kMAXPATHLEN] = {0}, cf[kMAXPATHLEN] = {0}, kf[kMAXPATHLEN] = {0}, ad[kMAXPATHLEN] = {0};
00874       const char *ptr;
00875 
00876       TString usrPromptDef = TString(GetAuthMethod(fSecurity)) + ".LoginPrompt";
00877       if ((ptr = strstr(fDetails, "pt:")) != 0) {
00878          sscanf(ptr + 3, "%4s %8191s", pt, usdef);
00879       } else {
00880          if (!strncasecmp(gEnv->GetValue(usrPromptDef,""),"no",2) ||
00881              !strncmp(gEnv->GetValue(usrPromptDef,""),"0",1))
00882             strncpy(pt,"0",1);
00883          else
00884             strncpy(pt,"1",1);
00885       }
00886       TString usrReUseDef = TString(GetAuthMethod(fSecurity)) + ".ReUse";
00887       if ((ptr = strstr(fDetails, "ru:")) != 0) {
00888          sscanf(ptr + 3, "%4s %8191s", ru, usdef);
00889       } else {
00890          if (!strncasecmp(gEnv->GetValue(usrReUseDef,""),"no",2) ||
00891              !strncmp(gEnv->GetValue(usrReUseDef,""),"0",1))
00892             strncpy(ru,"0",1);
00893          else
00894             strncpy(ru,"1",1);
00895       }
00896       TString usrValidDef = TString(GetAuthMethod(fSecurity)) + ".Valid";
00897       TString hours(gEnv->GetValue(usrValidDef,"24:00"));
00898       Int_t pd = 0;
00899       if ((pd = hours.Index(":")) > -1) {
00900          TString minutes = hours;
00901          hours.Resize(pd);
00902          minutes.Replace(0,pd+1,"");
00903          hh = atoi(hours.Data());
00904          mm = atoi(minutes.Data());
00905       } else {
00906          hh = atoi(hours.Data());
00907          mm = 0;
00908       }
00909 
00910       // Now action depends on method ...
00911       if (fSecurity == kGlobus) {
00912          if ((ptr = strstr(fDetails, "cd:")) != 0)
00913             sscanf(ptr, "%8191s %8191s", cd, usdef);
00914          if ((ptr = strstr(fDetails, "cf:")) != 0)
00915             sscanf(ptr, "%8191s %8191s", cf, usdef);
00916          if ((ptr = strstr(fDetails, "kf:")) != 0)
00917             sscanf(ptr, "%8191s %8191s", kf, usdef);
00918          if ((ptr = strstr(fDetails, "ad:")) != 0)
00919             sscanf(ptr, "%8191s %8191s", ad, usdef);
00920          if (gDebug > 2) {
00921             Info("SetEnvironment",
00922                  "details:%s, pt:%s, ru:%s, cd:%s, cf:%s, kf:%s, ad:%s",
00923                  fDetails.Data(), pt, ru, cd, cf, kf, ad);
00924          }
00925       } else if (fSecurity == kClear) {
00926          if ((ptr = strstr(fDetails, "us:")) != 0)
00927             sscanf(ptr + 3, "%8191s %8191s", us, usdef);
00928          if ((ptr = strstr(fDetails, "cp:")) != 0)
00929             sscanf(ptr + 3, "%8191s %8191s", cp, usdef);
00930          if (gDebug > 2)
00931             Info("SetEnvironment", "details:%s, pt:%s, ru:%s, us:%s cp:%s",
00932                  fDetails.Data(), pt, ru, us, cp);
00933       } else if (fSecurity == kKrb5) {
00934          if ((ptr = strstr(fDetails, "us:")) != 0)
00935             sscanf(ptr + 3, "%8191s %8191s", us, usdef);
00936          if ((ptr = strstr(fDetails, "pp:")) != 0)
00937             sscanf(ptr + 3, "%8191s %8191s", pp, usdef);
00938          if (gDebug > 2)
00939             Info("SetEnvironment", "details:%s, pt:%s, ru:%s, us:%s pp:%s",
00940                  fDetails.Data(), pt, ru, us, pp);
00941       } else {
00942          if ((ptr = strstr(fDetails, "us:")) != 0)
00943             sscanf(ptr + 3, "%8191s %8191s", us, usdef);
00944          if (gDebug > 2)
00945             Info("SetEnvironment", "details:%s, pt:%s, ru:%s, us:%s",
00946                  fDetails.Data(), pt, ru, us);
00947       }
00948 
00949       // Set Prompt flag
00950       if (!strncasecmp(pt, "yes",3) || !strncmp(pt, "1", 1))
00951          fgPromptUser = kTRUE;
00952 
00953       // Set ReUse flag
00954       if (fSecurity == kKrb5) {
00955          fgAuthReUse = kFALSE;
00956          if (!strncasecmp(ru, "yes",3) || !strncmp(ru, "1",1))
00957             fgAuthReUse = kTRUE;
00958       } else {
00959          if (fSecurity != kGlobus || !(gROOT->IsProofServ())) {
00960             fgAuthReUse = kTRUE;
00961             if (!strncasecmp(ru, "no",2) || !strncmp(ru, "0",1))
00962                fgAuthReUse = kFALSE;
00963          }
00964       }
00965 
00966       // Set Expiring date
00967       fgExpDate = TDatime();
00968       fgExpDate.Set(fgExpDate.Convert() + hh*3600 + mm*60);
00969 
00970       // UnSet Crypt flag for UsrPwd, if requested
00971       if (fSecurity == kClear) {
00972          fgUsrPwdCrypt = kTRUE;
00973          if (!strncmp(cp, "no", 2) || !strncmp(cp, "0", 1))
00974             fgUsrPwdCrypt = kFALSE;
00975       }
00976       // Build UserDefaults
00977       usdef[0] = '\0';
00978       if (fSecurity == kGlobus) {
00979          if (strlen(cd) > 0) { snprintf(usdef,8192," %s",cd); }
00980          if (strlen(cf) > 0) { snprintf(usdef,8192,"%s %s",usdef, cf); }
00981          if (strlen(kf) > 0) { snprintf(usdef,8192,"%s %s",usdef, kf); }
00982          if (strlen(ad) > 0) { snprintf(usdef,8192,"%s %s",usdef, ad); }
00983       } else {
00984          if (fSecurity == kKrb5) {
00985             // Collect info about principal, if any
00986             if (strlen(pp) > 0) {
00987                fgKrb5Principal = TString(pp);
00988             } else {
00989                // Allow specification via 'us:' key
00990                if (strlen(us) > 0 && strstr(us,"@"))
00991                   fgKrb5Principal = TString(us);
00992             }
00993             // command line user specification (fUser) gets highest priority
00994             if (fUser.Length()) {
00995                snprintf(usdef, kMAXPATHLEN, "%s", fUser.Data());
00996             } else {
00997                if (strlen(us) > 0 && !strstr(us,"@"))
00998                   snprintf(usdef, kMAXPATHLEN, "%s", us);
00999             }
01000          } else {
01001             // give highest priority to command-line specification
01002             if (fUser == "") {
01003                if (strlen(us) > 0) snprintf(usdef, kMAXPATHLEN, "%s", us);
01004             } else
01005                snprintf(usdef, kMAXPATHLEN, "%s", fUser.Data());
01006          }
01007       }
01008       if (strlen(usdef) > 0) {
01009          fgDefaultUser = usdef;
01010       } else {
01011          if (fgUser != "") {
01012             fgDefaultUser = fgUser;
01013          } else {
01014             UserGroup_t *u = gSystem->GetUserInfo();
01015             if (u)
01016                fgDefaultUser = u->fUser;
01017             delete u;
01018          }
01019       }
01020       if (fgDefaultUser == "anonymous" || fgDefaultUser == "rootd" ||
01021           fgUser != "" || fUser != "") {
01022          // when set by user don't prompt for it anymore
01023          fgPromptUser = kFALSE;
01024       }
01025 
01026       if (gDebug > 2)
01027          Info("SetEnvironment", "usdef:%s", fgDefaultUser.Data());
01028    }
01029 }
01030 
01031 //______________________________________________________________________________
01032 Bool_t TAuthenticate::GetUserPasswd(TString &user, TString &passwd,
01033                                     Bool_t &pwhash, Bool_t srppwd)
01034 {
01035    // Try to get user name and passwd from several sources.
01036 
01037    if (gDebug > 3)
01038       Info("GetUserPasswd", "Enter: User: '%s' Hash:%d SRP:%d",
01039            user.Data(),(Int_t)pwhash,(Int_t)srppwd);
01040 
01041    // Get user and passwd set via static functions SetUser and SetPasswd.
01042    if (user == "") {
01043       if (fgUser != "")
01044          user = fgUser;
01045       if (passwd == "" && fgPasswd != "" && srppwd == fgSRPPwd) {
01046          passwd = fgPasswd;
01047          pwhash = fgPwHash;
01048       }
01049    } else {
01050       if (fgUser != "" && user == fgUser) {
01051          if (passwd == "" && fgPasswd != "" && srppwd == fgSRPPwd) {
01052             passwd = fgPasswd;
01053             pwhash = fgPwHash;
01054          }
01055       }
01056    }
01057    if (gDebug > 3)
01058       Info("GetUserPasswd", "In memory: User: '%s' Hash:%d",
01059            user.Data(),(Int_t)pwhash);
01060 
01061    // Check system info for user if still not defined
01062    if (user == "") {
01063       UserGroup_t *u = gSystem->GetUserInfo();
01064       if (u)
01065          user = u->fUser;
01066       delete u;
01067       if (gDebug > 3)
01068          Info("GetUserPasswd", "In memory: User: '%s' Hash:%d",
01069               user.Data(),(Int_t)pwhash);
01070    }
01071 
01072    // Check ~/.rootnetrc and ~/.netrc files if user was not set via
01073    // the static SetUser() method.
01074    if (user == "" || passwd == "") {
01075       if (gDebug > 3)
01076          Info("GetUserPasswd", "Checking .netrc family ...");
01077       CheckNetrc(user, passwd, pwhash, srppwd);
01078    }
01079    if (gDebug > 3)
01080       Info("GetUserPasswd", "From .netrc family: User: '%s' Hash:%d",
01081            user.Data(),(Int_t)pwhash);
01082 
01083    // If user also not set via  ~/.rootnetrc or ~/.netrc ask user.
01084    if (user == "") {
01085       char *p = PromptUser(fRemote);
01086       user = p;
01087       delete [] p;
01088       if (user == "") {
01089          Error("GetUserPasswd", "user name not set");
01090          return 1;
01091       }
01092    }
01093 
01094    return 0;
01095 }
01096 
01097 //______________________________________________________________________________
01098 Bool_t TAuthenticate::CheckNetrc(TString &user, TString &passwd)
01099 {
01100    // Try to get user name and passwd from the ~/.rootnetrc or
01101    // ~/.netrc files. For more info see the version with 4 arguments.
01102    // This version is maintained for backward compatability reasons.
01103 
01104    Bool_t hash, srppwd;
01105 
01106    // Set srppwd flag
01107    srppwd = (fSecurity == kSRP) ? kTRUE : kFALSE;
01108 
01109    return CheckNetrc(user, passwd, hash, srppwd);
01110 }
01111 
01112 //______________________________________________________________________________
01113 Bool_t TAuthenticate::CheckNetrc(TString &user, TString &passwd,
01114                                  Bool_t &pwhash, Bool_t srppwd)
01115 {
01116    // Try to get user name and passwd from the ~/.rootnetrc or
01117    // ~/.netrc files. First ~/.rootnetrc is tried, after that ~/.netrc.
01118    // These files will only be used when their access masks are 0600.
01119    // Returns kTRUE if user and passwd were found for the machine
01120    // specified in the URL. If kFALSE, user and passwd are "".
01121    // If srppwd == kTRUE then a SRP ('secure') pwd is searched for in
01122    // the files.
01123    // The boolean pwhash is set to kTRUE if the returned passwd is to
01124    // be understood as password hash, i.e. if the 'password-hash' keyword
01125    // is found in the 'machine' lines; not implemented for 'secure'
01126    // and the .netrc file.
01127    // The format of these files are:
01128    //
01129    // # this is a comment line
01130    // machine <machine fqdn> login <user> password <passwd>
01131    // machine <machine fqdn> login <user> password-hash <passwd>
01132    //
01133    // and in addition ~/.rootnetrc also supports:
01134    //
01135    // secure <machine fqdn> login <user> password <passwd>
01136    //
01137    // <machine fqdn> may be a domain name or contain the wild card '*'.
01138    //
01139    // for the secure protocols. All lines must start in the first column.
01140 
01141    Bool_t result = kFALSE;
01142    Bool_t first = kTRUE;
01143    TString remote = fRemote;
01144 
01145    passwd = "";
01146    pwhash = kFALSE;
01147 
01148    char *net =
01149       gSystem->ConcatFileName(gSystem->HomeDirectory(), ".rootnetrc");
01150 
01151    // Determine FQDN of the host ...
01152    TInetAddress addr = gSystem->GetHostByName(fRemote);
01153    if (addr.IsValid())
01154       remote = addr.GetHostName();
01155 
01156 again:
01157    // Only use file when its access rights are 0600
01158    FileStat_t buf;
01159    if (gSystem->GetPathInfo(net, buf) == 0) {
01160 #ifdef WIN32
01161       // Since Win32 does not have proper protections use file always
01162       if (R_ISREG(buf.fMode) && !R_ISDIR(buf.fMode)) {
01163 #else
01164          if (R_ISREG(buf.fMode) && !R_ISDIR(buf.fMode) &&
01165              (buf.fMode & 0777) == (kS_IRUSR | kS_IWUSR)) {
01166 #endif
01167             FILE *fd = fopen(net, "r");
01168             char line[256];
01169             while (fgets(line, sizeof(line), fd) != 0) {
01170                if (line[0] == '#')
01171                   continue;
01172                char word[6][64];
01173                int nword = sscanf(line, "%63s %63s %63s %63s %63s %63s",
01174                                         word[0], word[1], word[2], word[3], word[4], word[5]);
01175                if (nword != 6)
01176                   continue;
01177                if (srppwd && strcmp(word[0], "secure"))
01178                   continue;
01179                if (!srppwd && strcmp(word[0], "machine"))
01180                   continue;
01181                if (strcmp(word[2], "login"))
01182                   continue;
01183                if (srppwd && strcmp(word[4], "password"))
01184                   continue;
01185                if (!srppwd &&
01186                    strcmp(word[4], "password") && strcmp(word[4], "password-hash"))
01187                   continue;
01188 
01189                // Treat the host name found in file as a regular expression
01190                // with '*' as a wild card
01191                TString href(word[1]);
01192                href.ReplaceAll("*",".*");
01193                TRegexp rg(href);
01194                if (remote.Index(rg) != kNPOS) {
01195                   if (user == "") {
01196                      user = word[3];
01197                      passwd = word[5];
01198                      if (!strcmp(word[4], "password-hash"))
01199                         pwhash = kTRUE;
01200                      result = kTRUE;
01201                      break;
01202                   } else {
01203                      if (!strcmp(word[3], user.Data())) {
01204                         passwd = word[5];
01205                         if (!strcmp(word[4], "password-hash"))
01206                            pwhash = kTRUE;
01207                         result = kTRUE;
01208                         break;
01209                      }
01210                   }
01211                }
01212             }
01213             fclose(fd);
01214          } else
01215             Warning("CheckNetrc",
01216                     "file %s exists but has not 0600 permission", net);
01217       }
01218       delete [] net;
01219 
01220       if (first && !srppwd && !result) {
01221          net = gSystem->ConcatFileName(gSystem->HomeDirectory(), ".netrc");
01222          first = kFALSE;
01223          goto again;
01224       }
01225 
01226       return result;
01227    }
01228 
01229 //______________________________________________________________________________
01230 const char *TAuthenticate::GetGlobalUser()
01231 {
01232    // Static method returning the global user.
01233 
01234    return fgUser;
01235 }
01236 
01237 //______________________________________________________________________________
01238 Bool_t TAuthenticate::GetGlobalPwHash()
01239 {
01240    // Static method returning the global password hash flag.
01241 
01242    return fgPwHash;
01243 }
01244 
01245 //______________________________________________________________________________
01246 Bool_t TAuthenticate::GetGlobalSRPPwd()
01247 {
01248    // Static method returning the global SRP password flag.
01249 
01250    return fgSRPPwd;
01251 }
01252 
01253 //______________________________________________________________________________
01254 TDatime TAuthenticate::GetGlobalExpDate()
01255 {
01256    // Static method returning default expiring date for new validity contexts
01257 
01258    return fgExpDate;
01259 }
01260 
01261 //______________________________________________________________________________
01262 const char *TAuthenticate::GetDefaultUser()
01263 {
01264    // Static method returning the default user information.
01265 
01266    return fgDefaultUser;
01267 }
01268 
01269 //______________________________________________________________________________
01270 const char *TAuthenticate::GetKrb5Principal()
01271 {
01272     // Static method returning the principal to be used to init Krb5 tickets.
01273 
01274    return fgKrb5Principal;
01275 }
01276 
01277 //______________________________________________________________________________
01278 Bool_t TAuthenticate::GetAuthReUse()
01279 {
01280    // Static method returning the authentication reuse settings.
01281 
01282    return fgAuthReUse;
01283 }
01284 
01285 //______________________________________________________________________________
01286 Bool_t TAuthenticate::GetPromptUser()
01287 {
01288    // Static method returning the prompt user settings.
01289 
01290    return fgPromptUser;
01291 }
01292 
01293 //______________________________________________________________________________
01294 const char *TAuthenticate::GetAuthMethod(Int_t idx)
01295 {
01296    // Static method returning the method corresponding to idx.
01297 
01298    R__LOCKGUARD2(gAuthenticateMutex);
01299 
01300    if (idx < 0 || idx > kMAXSEC-1) {
01301       ::Error("Authenticate::GetAuthMethod", "idx out of bounds (%d)", idx);
01302       idx = 0;
01303    }
01304    return fgAuthMeth[idx];
01305 }
01306 
01307 //______________________________________________________________________________
01308 Int_t TAuthenticate::GetAuthMethodIdx(const char *meth)
01309 {
01310    // Static method returning the method index (which can be used to find
01311    // the method in GetAuthMethod()). Returns -1 in case meth is not found.
01312 
01313    R__LOCKGUARD2(gAuthenticateMutex);
01314 
01315    if (meth && meth[0]) {
01316       for (Int_t i = 0; i < kMAXSEC; i++) {
01317          if (!fgAuthMeth[i].CompareTo(meth, TString::kIgnoreCase))
01318             return i;
01319       }
01320    }
01321 
01322    return -1;
01323 }
01324 
01325 //______________________________________________________________________________
01326 char *TAuthenticate::PromptUser(const char *remote)
01327 {
01328    // Static method to prompt for the user name to be used for authentication
01329    // to rootd or proofd. User is asked to type user name.
01330    // Returns user name (which must be deleted by caller) or 0.
01331    // If non-interactive run (eg ProofServ) returns default user.
01332 
01333    R__LOCKGUARD2(gAuthenticateMutex);
01334 
01335    const char *user;
01336    if (fgDefaultUser != "")
01337       user = fgDefaultUser;
01338    else
01339       user = gSystem->Getenv("USER");
01340 #ifdef R__WIN32
01341    if (!user)
01342       user = gSystem->Getenv("USERNAME");
01343 #endif
01344    if (isatty(0) == 0 || isatty(1) == 0) {
01345       ::Warning("TAuthenticate::PromptUser",
01346                 "not tty: cannot prompt for user, returning default");
01347       if (strlen(user))
01348          return StrDup(user);
01349       else
01350          return StrDup("None");
01351    }
01352 
01353    char *usr = Getline(Form("Name (%s:%s): ", remote, user));
01354    if (usr[0]) {
01355       usr[strlen(usr) - 1] = 0; // get rid of \n
01356       if (strlen(usr))
01357          return StrDup(usr);
01358       else
01359          return StrDup(user);
01360    }
01361    return 0;
01362 }
01363 
01364 //______________________________________________________________________________
01365 char *TAuthenticate::PromptPasswd(const char *prompt)
01366 {
01367    // Static method to prompt for the user's passwd to be used for
01368    // authentication to rootd or proofd. Uses non-echoing command line
01369    // to get passwd. Returns passwd (which must de deleted by caller) or 0.
01370    // If non-interactive run (eg ProofServ) returns -1
01371 
01372    if (isatty(0) == 0 || isatty(1) == 0) {
01373       ::Warning("TAuthenticate::PromptPasswd",
01374                 "not tty: cannot prompt for passwd, returning -1");
01375       static char noint[4] = {"-1"};
01376       return StrDup(noint);
01377    }
01378 
01379    char buf[128];
01380    char *pw = buf;
01381    // Get the plugin for the passwd dialog box, if needed
01382    if (!gROOT->IsBatch() && (fgPasswdDialog == (TPluginHandler *)(-1)) &&
01383        gEnv->GetValue("Auth.UsePasswdDialogBox", 1) == 1) {
01384       if ((fgPasswdDialog =
01385            gROOT->GetPluginManager()->FindHandler("TGPasswdDialog"))) {
01386          if (fgPasswdDialog->LoadPlugin() == -1) {
01387             fgPasswdDialog = 0;
01388             ::Warning("TAuthenticate",
01389                       "could not load plugin for the password dialog box");
01390          }
01391       }
01392    }
01393    if (fgPasswdDialog && (fgPasswdDialog != (TPluginHandler *)(-1))) {
01394 
01395       // Use graphic dialog
01396       fgPasswdDialog->ExecPlugin(3, prompt, buf, 128);
01397 
01398       // Wait until the user is done
01399       while (gROOT->IsInterrupted())
01400          gSystem->DispatchOneEvent(kFALSE);
01401 
01402    } else {
01403       Gl_config("noecho", 1);
01404       pw = Getline((char *) prompt);
01405       Gl_config("noecho", 0);
01406    }
01407 
01408    // Final checks
01409    if (pw[0]) {
01410       if (pw[strlen(pw)-1] == '\n')
01411          pw[strlen(pw) - 1] = 0;   // get rid of \n
01412       char *rpw = StrDup(pw);
01413       memset(pw, 0, strlen(pw));
01414       return rpw;
01415    }
01416    return 0;
01417 }
01418 
01419 //______________________________________________________________________________
01420 GlobusAuth_t TAuthenticate::GetGlobusAuthHook()
01421 {
01422    // Static method returning the globus authorization hook.
01423 
01424    return fgGlobusAuthHook;
01425 }
01426 
01427 //______________________________________________________________________________
01428 const char *TAuthenticate::GetRSAPubExport(Int_t key)
01429 {
01430    // Static method returning the RSA public keys.
01431 
01432    key = (key >= 0 && key <= 1) ? key : 0;
01433    return fgRSAPubExport[key].keys;
01434 }
01435 
01436 //______________________________________________________________________________
01437 Int_t TAuthenticate::GetRSAInit()
01438 {
01439    // Static method returning the RSA initialization flag.
01440 
01441    return fgRSAInit;
01442 }
01443 
01444 //______________________________________________________________________________
01445 void TAuthenticate::SetDefaultRSAKeyType(Int_t key)
01446 {
01447    // Static method setting the default type of RSA key.
01448 
01449    if (key >= 0 && key <= 1)
01450       fgRSAKey = key;
01451 }
01452 
01453 //______________________________________________________________________________
01454 void TAuthenticate::SetRSAInit(Int_t init)
01455 {
01456    // Static method setting RSA initialization flag.
01457 
01458    fgRSAInit = init;
01459 }
01460 
01461 //______________________________________________________________________________
01462 TList *TAuthenticate::GetAuthInfo()
01463 {
01464    // Static method returning the list with authentication details.
01465 
01466    R__LOCKGUARD2(gAuthenticateMutex);
01467 
01468    if (!fgAuthInfo)
01469       fgAuthInfo = new TList;
01470    return fgAuthInfo;
01471 }
01472 
01473 //______________________________________________________________________________
01474 TList *TAuthenticate::GetProofAuthInfo()
01475 {
01476    // Static method returning the list with authentication directives
01477    // to be sent to proof.
01478 
01479    R__LOCKGUARD2(gAuthenticateMutex);
01480 
01481    if (!fgProofAuthInfo)
01482       fgProofAuthInfo = new TList;
01483    return fgProofAuthInfo;
01484 }
01485 
01486 //______________________________________________________________________________
01487 void TAuthenticate::AuthError(const char *where, Int_t err)
01488 {
01489    // Print error string depending on error code.
01490 
01491    R__LOCKGUARD2(gAuthenticateMutex);
01492 
01493    // Make sure it is in range
01494    err = (err < kErrError) ? ((err > -1) ? err : -1) : kErrError;
01495 
01496    Int_t erc = err;
01497    Bool_t forceprint = kFALSE;
01498    TString lasterr = "";
01499    if (err == -1) {
01500       forceprint = kTRUE;
01501       erc = fgLastError;
01502       lasterr = "(last error only; re-run with gDebug > 0 for more details)";
01503    }
01504 
01505    if (erc > -1)
01506       if (gDebug > 0 || forceprint) {
01507          if (gRootdErrStr[erc])
01508             ::Error(Form("TAuthenticate::%s", where), "%s %s",
01509                     gRootdErrStr[erc], lasterr.Data());
01510          else
01511             ::Error(Form("TAuthenticate::%s", where),
01512                     "unknown error code: server must be running a newer ROOT version %s",
01513                     lasterr.Data());
01514       }
01515 
01516    // Update last error code
01517    fgLastError = err;
01518 }
01519 
01520 //______________________________________________________________________________
01521 void TAuthenticate::SetGlobalUser(const char *user)
01522 {
01523    // Set global user name to be used for authentication to rootd or proofd.
01524 
01525    R__LOCKGUARD2(gAuthenticateMutex);
01526 
01527    if (fgUser != "")
01528       fgUser = "";
01529 
01530    if (user && user[0])
01531       fgUser = user;
01532 }
01533 
01534 //______________________________________________________________________________
01535 void TAuthenticate::SetGlobalPasswd(const char *passwd)
01536 {
01537    // Set global passwd to be used for authentication to rootd or proofd.
01538 
01539    R__LOCKGUARD2(gAuthenticateMutex);
01540 
01541    if (fgPasswd != "")
01542       fgPasswd = "";
01543 
01544    if (passwd && passwd[0])
01545       fgPasswd = passwd;
01546 }
01547 
01548 //______________________________________________________________________________
01549 void TAuthenticate::SetGlobalPwHash(Bool_t pwhash)
01550 {
01551    // Set global passwd hash flag to be used for authentication to rootd or proofd.
01552 
01553    fgPwHash = pwhash;
01554 }
01555 
01556 //______________________________________________________________________________
01557 void TAuthenticate::SetGlobalSRPPwd(Bool_t srppwd)
01558 {
01559    // Set global SRP passwd flag to be used for authentication to rootd or proofd.
01560 
01561    fgSRPPwd = srppwd;
01562 }
01563 
01564 //______________________________________________________________________________
01565 void TAuthenticate::SetReadHomeAuthrc(Bool_t readhomeauthrc)
01566 {
01567    // Set flag controlling the reading of $HOME/.rootauthrc.
01568    // In PROOF the administrator may want to switch off private settings.
01569    // Always true, may only be set false via option to proofd.
01570 
01571    fgReadHomeAuthrc = readhomeauthrc;
01572 }
01573 
01574 //______________________________________________________________________________
01575 void TAuthenticate::SetGlobalExpDate(TDatime expdate)
01576 {
01577    // Set default expiring date for new validity contexts
01578 
01579    fgExpDate = expdate;
01580 }
01581 
01582 //______________________________________________________________________________
01583 void TAuthenticate::SetDefaultUser(const char *defaultuser)
01584 {
01585    // Set default user name.
01586 
01587    if (fgDefaultUser != "")
01588       fgDefaultUser = "";
01589 
01590    if (defaultuser && defaultuser[0])
01591       fgDefaultUser = defaultuser;
01592 }
01593 
01594 //______________________________________________________________________________
01595 void TAuthenticate::SetTimeOut(Int_t to)
01596 {
01597    // Set timeout (active if > 0)
01598 
01599    fgAuthTO = (to <= 0) ? -1 : to;
01600 }
01601 
01602 //______________________________________________________________________________
01603 void TAuthenticate::SetAuthReUse(Bool_t authreuse)
01604 {
01605    // Set global AuthReUse flag
01606 
01607    fgAuthReUse = authreuse;
01608 }
01609 
01610 //______________________________________________________________________________
01611 void TAuthenticate::SetPromptUser(Bool_t promptuser)
01612 {
01613    // Set global PromptUser flag
01614 
01615    fgPromptUser = promptuser;
01616 }
01617 
01618 //______________________________________________________________________________
01619 void TAuthenticate::SetSecureAuthHook(SecureAuth_t func)
01620 {
01621    // Set secure authorization function. Automatically called when libSRPAuth
01622    // is loaded.
01623 
01624    fgSecAuthHook = func;
01625 }
01626 
01627 //______________________________________________________________________________
01628 void TAuthenticate::SetKrb5AuthHook(Krb5Auth_t func)
01629 {
01630    // Set kerberos5 authorization function. Automatically called when
01631    // libKrb5Auth is loaded.
01632 
01633    fgKrb5AuthHook = func;
01634 }
01635 
01636 //______________________________________________________________________________
01637 void TAuthenticate::SetGlobusAuthHook(GlobusAuth_t func)
01638 {
01639    // Set Globus authorization function. Automatically called when
01640    // libGlobusAuth is loaded.
01641 
01642    fgGlobusAuthHook = func;
01643 }
01644 
01645 //______________________________________________________________________________
01646 Int_t TAuthenticate::SshError(const char *errorfile)
01647 {
01648    // SSH error parsing: returns
01649    //     0  :  no error or fatal
01650    //     1  :  should retry (eg 'connection closed by remote host')
01651 
01652    Int_t error = 0;
01653 
01654    if (!gSystem->AccessPathName(errorfile, kReadPermission)) {
01655       FILE *ferr = fopen(errorfile,"r");
01656       if (ferr) {
01657          // Get list of errors for which one should retry
01658          char *serr = StrDup(gEnv->GetValue("SSH.ErrorRetry", ""));
01659          // Prepare for parsing getting rid of '"'s
01660          Int_t lerr = strlen(serr);
01661          char *pc = (char *)memchr(serr,'"',lerr);
01662          while (pc) {
01663             *pc = '\0';
01664             pc = (char *)memchr(pc+1,'"',strlen(pc+1));
01665          }
01666          // Now read the file
01667          char line[kMAXPATHLEN];
01668          while (fgets(line,sizeof(line),ferr)) {
01669             // Get rid of trailing '\n'
01670             if (line[strlen(line)-1] == '\n')
01671                line[strlen(line)-1] = '\0';
01672             if (gDebug > 2)
01673                Info("SshError","read line: %s",line);
01674             pc = serr;
01675             while (pc < serr + lerr) {
01676                if (pc[0] == '\0' || pc[0] == ' ')
01677                   pc++;
01678                else {
01679                   if (gDebug > 2)
01680                      Info("SshError","checking error: '%s'",pc);
01681                   if (strstr(line,pc))
01682                      error = 1;
01683                   pc += strlen(pc);
01684                }
01685             }
01686          }
01687          // Close file
01688          fclose(ferr);
01689          // Free allocated memory
01690          if (serr) delete [] serr;
01691       }
01692    }
01693    return error;
01694 }
01695 
01696 //______________________________________________________________________________
01697 Int_t TAuthenticate::SshAuth(TString &user)
01698 {
01699    // SSH client authentication code.
01700 
01701    // No control on credential forwarding in case of SSH authentication;
01702    // switched it off on PROOF servers, unless the user knows what (s)he
01703    // is doing
01704 
01705    if (gROOT->IsProofServ()) {
01706       if (!(gEnv->GetValue("ProofServ.UseSSH",0))) {
01707          if (gDebug > 0)
01708             Info("SshAuth", "SSH protocol is switched OFF by default"
01709                  " for PROOF servers: use 'ProofServ.UseSSH 1'"
01710                  " to enable it (see system.rootrc)");
01711          return -1;
01712       }
01713    }
01714 
01715    Int_t sshproto = 1;
01716    if (fVersion < 4)
01717       sshproto = 0;
01718 
01719    // Find out which command we should be using
01720    char cmdref[2][5] = {"ssh", "scp"};
01721    char scmd[5] = "";
01722    char *gSshExe = 0;
01723    Bool_t notfound = kTRUE;
01724 
01725    while (notfound && sshproto > -1) {
01726 
01727       strlcpy(scmd,cmdref[sshproto],5);
01728 
01729       // Check First if a 'scmd' executable exists ...
01730       gSshExe = gSystem->Which(gSystem->Getenv("PATH"),
01731                                scmd, kExecutePermission);
01732       if (!gSshExe) {
01733          if (gDebug > 2)
01734             Info("SshAuth", "%s not found in $PATH", scmd);
01735 
01736          // Still allow for client definition of the ssh location ...
01737          if (strcmp(gEnv->GetValue("SSH.ExecDir", "-1"), "-1")) {
01738             if (gDebug > 2)
01739                Info("SshAuth", "searching user defined path ...");
01740             gSshExe = StrDup(Form("%s/%s",
01741                                   (char *)gEnv->GetValue("SSH.ExecDir", ""), scmd));
01742             if (gSystem->AccessPathName(gSshExe, kExecutePermission)) {
01743                if (gDebug > 2)
01744                   Info("SshAuth", "%s not executable", gSshExe);
01745             } else
01746                notfound = kFALSE;
01747          }
01748       } else
01749          notfound = kFALSE;
01750       if (notfound) sshproto--;
01751    }
01752 
01753    // Check if the command was found
01754    if (notfound) {
01755       if (gSshExe) delete [] gSshExe;
01756       return -1;
01757    }
01758    if (gDebug > 2)
01759       Info("SshAuth", "%s is %s (sshproto: %d)", scmd, gSshExe, sshproto);
01760 
01761    // SSH-like authentication code.
01762    // Returns 0 in case authentication failed
01763    //         1 in case of success
01764    //        -1 in case of the remote node does not seem to support
01765    //           SSH-like Authentication
01766    //        -2 in case of the remote node does not seem to allow
01767    //           connections from this node
01768 
01769    char secName[kMAXPATHLEN] = { 0 };
01770 
01771    // Determine user name ...
01772    user = GetSshUser(user);
01773 
01774    // Check ReUse
01775    Int_t reuse = (int)fgAuthReUse;
01776    fDetails = TString(Form("pt:%d ru:%d us:",(int)fgPromptUser,(int)fgAuthReUse))
01777       + user;
01778 
01779    // Create options string
01780    int opt = reuse * kAUTH_REUSE_MSK + fRSAKey * kAUTH_RSATY_MSK;
01781    TString options(Form("%d none %ld %s %d", opt,
01782                         (Long_t)user.Length(),user.Data(),sshproto));
01783 
01784    // Check established authentications
01785    Int_t kind = kROOTD_SSH;
01786    Int_t retval = reuse;
01787    Int_t rc = 0;
01788    if ((rc = AuthExists(user, (Int_t) TAuthenticate::kSSH, options,
01789                         &kind, &retval, &StdCheckSecCtx)) == 1) {
01790       // A valid authentication exists: we are done ...
01791       return 1;
01792    }
01793    if (rc == -2) {
01794       return rc;
01795    }
01796    if (retval == kErrNotAllowed && kind == kROOTD_ERR) {
01797       return 0;
01798    }
01799    // Check return flags
01800    if (kind != kROOTD_SSH)
01801       return 0;                 // something went wrong
01802    if (retval == 0)
01803       return 0;                 // no remote support for SSH
01804    if (retval == -2)
01805       return 0;                 // user unkmown to remote host
01806 
01807    // Wait for the server to communicate remote pid and location
01808    // of command to execute
01809    char cmdinfo[kMAXPATHLEN] = { 0 };
01810    Int_t reclen = (retval+1 > kMAXPATHLEN) ? kMAXPATHLEN : retval+1 ;
01811    if (fSocket->Recv(cmdinfo, reclen, kind) < 0)
01812       return 0;
01813    if (kind != kROOTD_SSH)
01814       return 0;                 // something went wrong
01815    if (gDebug > 3)
01816       Info("SshAuth", "received from server command info: %s", cmdinfo);
01817 
01818    int rport = -1;
01819    TString ci(cmdinfo), tkn;
01820    Ssiz_t from = 0;
01821    while (ci.Tokenize(tkn, from, " ")) {
01822       if (from > 0) cmdinfo[from-1] = '\0';
01823       if (tkn.BeginsWith("p:")) {
01824          tkn.ReplaceAll("p:", "");
01825          if (tkn.IsDigit()) rport = tkn.Atoi();
01826 #ifdef R__SSL
01827       } else if (tkn.BeginsWith("k:")) {
01828          tkn.ReplaceAll("k:", "");
01829          if (tkn.IsDigit() && tkn.Atoi() == 1) fRSAKey = 1;
01830 #endif
01831       }
01832    }
01833 
01834    // If we are a non-interactive session we cannot reply
01835    TString noPrompt = "";
01836    if (isatty(0) == 0 || isatty(1) == 0) {
01837       noPrompt  = TString("-o 'PasswordAuthentication no' ");
01838       noPrompt += TString("-o 'StrictHostKeyChecking no' ");
01839       if (gDebug > 3)
01840          Info("SshAuth", "using noprompt options: %s", noPrompt.Data());
01841    }
01842 
01843    // Remote settings
01844    Int_t srvtyp = fSocket->GetServType();
01845    Int_t rproto = fSocket->GetRemoteProtocol();
01846 
01847    // Send authentication request to remote sshd
01848    // Create command
01849    int ssh_rc = 1;
01850    Int_t ntry = gEnv->GetValue("SSH.MaxRetry",100);
01851    TString fileErr = "";
01852    if (sshproto == 0) {
01853       // Prepare local file first in the home directory
01854       fileErr = "rootsshtmp_";
01855       FILE *floc = gSystem->TempFileName(fileErr,gSystem->HomeDirectory());
01856       if (floc == 0) {
01857          // Try the temp directory
01858          fileErr = "rootsshtmp_";
01859          if ((floc = gSystem->TempFileName(fileErr)))
01860             fclose(floc);
01861       }
01862       fileErr.Append(".error");
01863       TString sshcmd(Form("%s -x -l %s %s",
01864                           gSshExe, user.Data(), noPrompt.Data()));
01865       if (rport != -1)
01866          sshcmd += TString(Form(" -p %d",rport));
01867       sshcmd += TString(Form(" %s %s",fRemote.Data(), cmdinfo));
01868       sshcmd += TString(Form(" 1> /dev/null 2> %s",fileErr.Data()));
01869 
01870       // Execute command
01871       Int_t again = 1;
01872       while (ssh_rc && again && ntry--) {
01873          ssh_rc = gSystem->Exec(sshcmd);
01874          if (ssh_rc) {
01875             again = SshError(fileErr);
01876             if (gDebug > 3)
01877                Info("SshAuth", "%d: sleeping: rc: %d, again:%d, ntry: %d",
01878                     fgProcessID, ssh_rc, again, ntry);
01879             if (again)
01880                gSystem->Sleep(1);
01881          }
01882       }
01883    } else {
01884       // Whether we need to add info about user@host in the command
01885       // Recent rootd/proofd set this correctly so that it works also
01886       // via SSH tunnel
01887       Bool_t addhost = ((srvtyp == TSocket::kROOTD && rproto < 15) ||
01888                         (srvtyp == TSocket::kPROOFD && rproto < 13)||
01889                         (srvtyp == TSocket::kSOCKD && rproto < 1)) ? 1 : 0;
01890 
01891       // Prepare local file first in the home directory
01892       TString fileLoc = "rootsshtmp_";
01893       FILE *floc = gSystem->TempFileName(fileLoc,gSystem->HomeDirectory());
01894       if (floc == 0) {
01895          // Try the temp directory
01896          fileLoc = "rootsshtmp_";
01897          floc = gSystem->TempFileName(fileLoc);
01898       }
01899 
01900       if (floc != 0) {
01901          // Close file and change permissions before filling it
01902          fclose(floc);
01903          if (chmod(fileLoc, 0600) == -1) {
01904             Info("SshAuth", "fchmod error: %d", errno);
01905             ssh_rc = 2;
01906          } else {
01907             floc = fopen(fileLoc, "w");
01908             if (reuse == 1) {
01909                // Send our public key
01910                if (fVersion > 4) {
01911                   fprintf(floc,"k: %d\n",fRSAKey+1);
01912                   fwrite(fgRSAPubExport[fRSAKey].keys,1,
01913                          fgRSAPubExport[fRSAKey].len,floc);
01914                } else {
01915                   fprintf(floc,"k: %s\n",fgRSAPubExport[0].keys);
01916                }
01917             } else
01918                // Just a notification
01919                fprintf(floc,"k: -1\n");
01920             fclose(floc);
01921             ssh_rc = 0;
01922          }
01923          if (!ssh_rc) {
01924             fileErr = TString(fileLoc).Append(".error");
01925             TString sshcmd(Form("%s -p %s", gSshExe, noPrompt.Data()));
01926             if (rport != -1)
01927                sshcmd += TString(Form(" -P %d",rport));
01928             sshcmd += TString(Form(" %s",fileLoc.Data()));
01929             if (addhost) {
01930                sshcmd += TString(Form(" %s@%s:%s 1> /dev/null",
01931                                         user.Data(),fRemote.Data(),cmdinfo));
01932             } else {
01933                sshcmd += TString(Form("%s 1> /dev/null", cmdinfo));
01934             }
01935             sshcmd += TString(Form(" 2> %s",fileErr.Data()));
01936             // Execute command
01937             ssh_rc = 1;
01938             Int_t again = 1;
01939             while (ssh_rc && again && ntry--) {
01940                ssh_rc = gSystem->Exec(sshcmd);
01941                if (ssh_rc) {
01942                   again = SshError(fileErr);
01943                   if (gDebug > 3)
01944                      Info("SshAuth", "%d: sleeping: rc: %d, again:%d, ntry: %d",
01945                           fgProcessID, ssh_rc, again, ntry);
01946                   if (again)
01947                      // Wait 1 sec before retry
01948                      gSystem->Sleep(1000);
01949                }
01950             }
01951          }
01952       } else {
01953          // Problems creating temporary file: return ...
01954          ssh_rc = 1;
01955       }
01956       // Remove the file after use ...
01957       if (!gSystem->AccessPathName(fileLoc,kFileExists)) {
01958          gSystem->Unlink(fileLoc);
01959       }
01960    }
01961    // Remove the file after use ...
01962    if (!gSystem->AccessPathName(fileErr,kFileExists)) {
01963       gSystem->Unlink(fileErr);
01964    }
01965    if (gDebug > 3)
01966       Info("SshAuth", "%d: system return code: %d (%d)",
01967            fgProcessID, ssh_rc, ntry+1);
01968 
01969    if (ssh_rc && sshproto == 0) {
01970 
01971       srvtyp = fSocket->GetServType();
01972       rproto = fSocket->GetRemoteProtocol();
01973       Int_t level = 2;
01974       if ((srvtyp == TSocket::kROOTD && rproto < 10) ||
01975           (srvtyp == TSocket::kPROOFD && rproto < 9))
01976          level = 1;
01977       if ((srvtyp == TSocket::kROOTD && rproto < 8) ||
01978           (srvtyp == TSocket::kPROOFD && rproto < 7))
01979          level = 0;
01980       if (level) {
01981          Int_t port = fSocket->GetPort();
01982          TSocket *newsock = 0;
01983          TString url(Form("sockd://%s",fRemote.Data()));
01984          if (srvtyp == TSocket::kROOTD) {
01985             // Parallel socket requested by 'rootd'
01986             url.ReplaceAll("sockd",5,"rootd",5);
01987             newsock = new TPSocket(url.Data(),port,1,-1);
01988          } else {
01989             if (srvtyp == TSocket::kPROOFD)
01990                url.ReplaceAll("sockd",5,"proofd",6);
01991             newsock = new TSocket(fRemote.Data(),port,-1);
01992             if (srvtyp == TSocket::kPROOFD)
01993                newsock->Send("failure notification");
01994          }
01995          // prepare info to send
01996          char cd1[1024], pipe[1024], dum[1024];
01997          Int_t id3;
01998          sscanf(cmdinfo, "%1023s %d %1023s %1023s", cd1, &id3, pipe, dum);
01999          snprintf(secName, kMAXPATHLEN, "%d -1 0 %s %d %s %d",
02000                   -fgProcessID, pipe,
02001                   (int)strlen(user), user.Data(), TSocket::GetClientProtocol());
02002          newsock->Send(secName, kROOTD_SSH);
02003          if (level > 1) {
02004             // Improved diagnostics
02005             // Receive diagnostics message
02006             if (newsock->Recv(retval, kind) >= 0) {
02007                char *buf = new char[retval+1];
02008                if (newsock->Recv(buf, retval+1, kind) >= 0) {
02009                   if (strncmp(buf,"OK",2)) {
02010                      Info("SshAuth", "from remote host %s:", fRemote.Data());
02011                      Info("SshAuth", ">> nothing listening on port %s %s",buf,
02012                           "(supposed to be associated to sshd)");
02013                      Info("SshAuth", ">> contact the daemon administrator at %s",
02014                           fRemote.Data());
02015                   } else {
02016                      if (gDebug > 0) {
02017                         Info("SshAuth", "from remote host %s:", fRemote.Data());
02018                         Info("SshAuth", ">> something listening on the port"
02019                              " supposed to be associated to sshd.");
02020                         Info("SshAuth", ">> You have probably mistyped your"
02021                              " password. Or you tried to hack the"
02022                              " system.");
02023                         Info("SshAuth", ">> If the problem persists you may"
02024                              " consider contacting the daemon");
02025                         Info("SshAuth", ">> administrator at %s.",fRemote.Data());
02026                      }
02027                   }
02028                }
02029                if (buf)
02030                   delete [] buf;
02031             }
02032          }
02033          SafeDelete(newsock);
02034          // Receive error message
02035          if (fSocket->Recv(retval, kind) >= 0) {  // for consistency
02036             if (kind == kROOTD_ERR)
02037                AuthError("SshAuth", retval);
02038          }
02039       }
02040       return 0;
02041    } else if (ssh_rc && sshproto > 0) {
02042       // Communicate failure
02043       if (fSocket->Send("0", kROOTD_SSH) < 0)
02044          Info("SshAuth", "error communicating failure");
02045       return 0;
02046    }
02047 
02048    // Communicate success
02049    if (sshproto > 0) {
02050       if (fSocket->Send("1", kROOTD_SSH) < 0)
02051          Info("SshAuth", "error communicating success");
02052    }
02053 
02054    Int_t nrec = 0;
02055    // Receive key request info and type of key (if ok, error otherwise)
02056    if ((nrec = fSocket->Recv(retval, kind)) < 0)  // returns user
02057       return 0;
02058    if (gDebug > 3)
02059       Info("SshAuth", "got message %d, flag: %d", kind, retval);
02060 
02061    // Check if an error occured
02062    if (kind == kROOTD_ERR) {
02063       AuthError("SshAuth", retval);
02064       return 0;
02065    }
02066 
02067    if (reuse == 1 && sshproto == 0) {
02068 
02069       // Save type of key
02070       if (kind != kROOTD_RSAKEY  || retval < 1 || retval > 2) {
02071          Error("SshAuth",
02072                "problems recvn RSA key flag: got message %d, flag: %d",
02073                kind, retval);
02074          return 0;
02075       }
02076 
02077       fRSAKey = retval - 1;
02078 
02079       // Send the key securely
02080       if (SendRSAPublicKey(fSocket,fRSAKey) < 0)
02081          return 0;
02082 
02083       // Receive username used for login
02084       if ((nrec = fSocket->Recv(retval, kind)) < 0)  // returns user
02085          return 0;
02086       if (gDebug > 3)
02087          Info("SshAuth", "got message %d, flag: %d", kind, retval);
02088    }
02089 
02090    if (kind != kROOTD_SSH || retval < 1) {
02091       Warning("SshAuth",
02092               "problems recvn (user,offset) length (%d:%d bytes:%d)", kind,
02093               retval, nrec);
02094       return 0;
02095    }
02096 
02097    char answer[256];
02098    reclen = (retval+1 > 256) ? 256 : retval+1;
02099    if ((nrec = fSocket->Recv(answer, reclen, kind)) < 0)  // returns user
02100       return 0;
02101    if (kind != kMESS_STRING)
02102       Warning("SshAuth", "username and offset not received (%d:%d)", kind,
02103               nrec);
02104 
02105    // Parse answer
02106    char lUser[128];
02107    int offset = -1;
02108    sscanf(answer, "%127s %d", lUser, &offset);
02109    if (gDebug > 3)
02110       Info("SshAuth", "received from server: user: %s, offset: %d", lUser,
02111            offset);
02112 
02113    // Receive token
02114    char *token = 0;
02115    if (reuse == 1 && offset > -1) {
02116       if (SecureRecv(fSocket, 1, fRSAKey, &token) == -1) {
02117          Warning("SshAuth", "problems secure-receiving token -"
02118                  " may result in corrupted token");
02119          delete [] token;
02120          return 0;
02121       }
02122       if (gDebug > 3)
02123          Info("SshAuth", "received from server: token: '%s' ", token);
02124    } else {
02125       token = StrDup("");
02126    }
02127 
02128    // Create SecContext object
02129    fSecContext = fHostAuth->CreateSecContext((const char *)lUser, fRemote,
02130                                              (Int_t)kSSH, offset, fDetails,
02131                                              (const char *)token, fgExpDate, 0, fRSAKey);
02132 
02133    // Release allocated memory ...
02134    if (token) delete [] token;
02135 
02136    // Get and Analyse the reply
02137    if (fSocket->Recv(retval, kind) < 0)
02138       return 0;
02139    if (gDebug > 3)
02140       Info("SshAuth", "received from server: kind: %d, retval: %d", kind,
02141            retval);
02142 
02143    if (kind != kROOTD_AUTH) {
02144       return 0;
02145    } else {
02146       return retval;
02147    }
02148 }
02149 
02150 //______________________________________________________________________________
02151 const char *TAuthenticate::GetSshUser(TString user) const
02152 {
02153    // Method returning the user to be used for the ssh login.
02154    // Looks first at SSH.Login and finally at env USER.
02155    // If SSH.LoginPrompt is set to 'yes' it prompts for the 'login name'
02156 
02157    R__LOCKGUARD2(gAuthenticateMutex);
02158 
02159    static TString usr = "";
02160 
02161    if (user == "") {
02162       if (fgPromptUser) {
02163          char *p = PromptUser(fRemote);
02164          usr = p;
02165          delete [] p;
02166       } else {
02167          usr = fgDefaultUser;
02168          if (usr == "") {
02169             char *p = PromptUser(fRemote);
02170             usr = p;
02171             delete [] p;
02172          }
02173       }
02174    } else {
02175       usr = user;
02176    }
02177 
02178    return usr;
02179 }
02180 
02181 //______________________________________________________________________________
02182 Bool_t TAuthenticate::CheckHost(const char *host, const char *href)
02183 {
02184    // Check if 'host' matches 'href':
02185    // this means either equal or "containing" it, even with wild cards *
02186    // in the first field (in the case 'href' is a name, ie not IP address)
02187    // Returns kTRUE if the two matches.
02188 
02189    R__LOCKGUARD2(gAuthenticateMutex);
02190 
02191    Bool_t retval = kTRUE;
02192 
02193    // Both strings should have been defined
02194    if (!host || !href)
02195       return kFALSE;
02196 
02197    // 'href' == '*' indicates any 'host' ...
02198    if (!strcmp(href,"*"))
02199       return kTRUE;
02200 
02201    // If 'href' contains at a letter or an hyphen it is assumed to be
02202    // a host name. Otherwise a name.
02203    // Check also for wild cards
02204    Bool_t name = kFALSE;
02205    TRegexp rename("[+a-zA-Z]");
02206    Int_t len;
02207    if (rename.Index(href,&len) != -1 || strstr(href,"-"))
02208       name = kTRUE;
02209 
02210    // Check also for wild cards
02211    Bool_t wild = kFALSE;
02212    if (strstr(href,"*"))
02213       wild = kTRUE;
02214 
02215    // Now build the regular expression for final checking
02216    TRegexp rehost(href,wild);
02217 
02218    // host to check
02219    TString theHost(host);
02220    if (!name) {
02221       TInetAddress addr = gSystem->GetHostByName(host);
02222       theHost = addr.GetHostAddress();
02223       if (gDebug > 2)
02224          ::Info("TAuthenticate::CheckHost", "checking host IP: %s", theHost.Data());
02225    }
02226 
02227    // Check 'host' against 'rehost'
02228    Ssiz_t pos = rehost.Index(theHost,&len);
02229    if (pos == -1)
02230       retval = kFALSE;
02231 
02232    // If IP and no wilds, it should match either
02233    // the beginning or the end of the string
02234    if (!wild) {
02235       if (pos > 0 && pos != (Ssiz_t)(theHost.Length()-strlen(href)))
02236          retval = kFALSE;
02237    }
02238 
02239    return retval;
02240 }
02241 
02242 //______________________________________________________________________________
02243 Int_t TAuthenticate::RfioAuth(TString &username)
02244 {
02245    // UidGid client authentication code.
02246    // Returns 0 in case authentication failed
02247    //         1 in case of success
02248    //        <0 in case of system error
02249 
02250    if (gDebug > 2)
02251       Info("RfioAuth", "enter ... username %s", username.Data());
02252 
02253    // Get user info ... ...
02254    UserGroup_t *pw = gSystem->GetUserInfo(gSystem->GetEffectiveUid());
02255    if (pw) {
02256 
02257       // These are the details to be saved in case of success ...
02258       username = pw->fUser;
02259       fDetails = TString("pt:0 ru:0 us:") + username;
02260 
02261       // Check that we are not root and that the requested user is ourselves
02262       if (pw->fUid != 0) {
02263 
02264          UserGroup_t *grp = gSystem->GetGroupInfo(gSystem->GetEffectiveGid());
02265 
02266          // Get effective user & group ID associated with the current process...
02267          Int_t uid = pw->fUid;
02268          Int_t gid = grp ? grp->fGid : pw->fGid;
02269 
02270          delete grp;
02271 
02272          // Send request ....
02273          TString sstr = TString(Form("%d %d", uid, gid));
02274          if (gDebug > 3)
02275             Info("RfioAuth", "sending ... %s", sstr.Data());
02276          Int_t ns = 0;
02277          if ((ns = fSocket->Send(sstr.Data(), kROOTD_RFIO)) < 0)
02278             return 0;
02279          if (gDebug > 3)
02280             Info("RfioAuth", "sent ... %d bytes (expected > %d)", ns,
02281                  sstr.Length());
02282 
02283          // Get answer
02284          Int_t stat, kind;
02285          if (fSocket->Recv(stat, kind) < 0)
02286             return 0;
02287          if (gDebug > 3)
02288             Info("RfioAuth", "after kROOTD_RFIO: kind= %d, stat= %d", kind,
02289                  stat);
02290 
02291          // Query result ...
02292          if (kind == kROOTD_AUTH && stat >= 1) {
02293             // Create inactive SecContext object for use in TSocket
02294             fSecContext =
02295                fHostAuth->CreateSecContext((const char *)pw->fUser,
02296                                            fRemote, kRfio, -stat, fDetails, 0);
02297             delete pw;
02298             return 1;
02299          } else {
02300             TString server = "sockd";
02301             if (fProtocol.Contains("root"))
02302                server = "rootd";
02303             if (fProtocol.Contains("proof"))
02304                server = "proofd";
02305 
02306             // Authentication failed
02307             if (stat == kErrConnectionRefused) {
02308                if (gDebug > 0)
02309                   Error("RfioAuth",
02310                         "%s@%s does not accept connections from %s%s",
02311                         server.Data(),fRemote.Data(),
02312                         fUser.Data(),gSystem->HostName());
02313                delete pw;
02314                return -2;
02315             } else if (stat == kErrNotAllowed) {
02316                if (gDebug > 0)
02317                   Error("RfioAuth",
02318                         "%s@%s does not accept %s authentication from %s@%s",
02319                         server.Data(),fRemote.Data(),
02320                         TAuthenticate::fgAuthMeth[5].Data(),
02321                         fUser.Data(),gSystem->HostName());
02322             } else {
02323                AuthError("RfioAuth", stat);
02324             }
02325             delete pw;
02326             return 0;
02327          }
02328       } else {
02329          Warning("RfioAuth", "UidGid login as \"root\" not allowed");
02330          return -1;
02331       }
02332    }
02333    return -1;
02334 }
02335 
02336 //______________________________________________________________________________
02337 Int_t TAuthenticate::ClearAuth(TString &user, TString &passwd, Bool_t &pwdhash)
02338 {
02339    // UsrPwd client authentication code.
02340    // Returns 0 in case authentication failed
02341    //         1 in case of success
02342 
02343    R__LOCKGUARD2(gAuthenticateMutex);
02344 
02345    if (gDebug > 2)
02346       Info("ClearAuth", "enter: user: %s (passwd hashed?: %d)",
02347            user.Data(),(Int_t)pwdhash);
02348 
02349    Int_t reuse    = fgAuthReUse;
02350    Int_t prompt   = fgPromptUser;
02351    Int_t cryptopt = fgUsrPwdCrypt;
02352    Int_t needsalt = 1;
02353    if (pwdhash)
02354       needsalt = 0;
02355    fDetails = TString(Form("pt:%d ru:%d cp:%d us:",
02356                            fgPromptUser, fgAuthReUse, fgUsrPwdCrypt)) + user;
02357    if (gDebug > 2)
02358       Info("ClearAuth", "ru:%d pt:%d cp:%d ns:%d rk:%d",
02359            fgAuthReUse,fgPromptUser,fgUsrPwdCrypt,needsalt,fgRSAKey);
02360 #ifdef R__WIN32
02361    needsalt = 0;
02362 #endif
02363    Int_t stat, kind;
02364 
02365    if (fVersion > 1) {
02366 
02367       //
02368       // New protocol
02369       //
02370       Int_t anon = 0;
02371       TString salt = "";
02372       TString pashash = "";
02373 
02374       // Get effective user (fro remote checks in $HOME/.rhosts)
02375       UserGroup_t *pw = gSystem->GetUserInfo(gSystem->GetEffectiveUid());
02376       TString effUser;
02377       if (pw) {
02378          effUser = TString(pw->fUser);
02379          delete pw;
02380       } else
02381          effUser = user;
02382 
02383       // Create options string
02384       int opt = (reuse * kAUTH_REUSE_MSK) + (cryptopt * kAUTH_CRYPT_MSK) +
02385          (needsalt * kAUTH_SSALT_MSK) + (fRSAKey * kAUTH_RSATY_MSK);
02386       TString options(Form("%d %ld %s %ld %s", opt,
02387                            (Long_t)user.Length(), user.Data(),
02388                            (Long_t)effUser.Length(), effUser.Data()));
02389 
02390       // Check established authentications
02391       kind = kROOTD_USER;
02392       stat = reuse;
02393       Int_t rc = 0;
02394       if ((rc = AuthExists(user, (Int_t) TAuthenticate::kClear, options,
02395                            &kind, &stat, &StdCheckSecCtx)) == 1) {
02396          // A valid authentication exists: we are done ...
02397          return 1;
02398       }
02399       if (rc == -2) {
02400          return rc;
02401       }
02402       if (stat == kErrNotAllowed && kind == kROOTD_ERR) {
02403          return 0;
02404       }
02405 
02406       if (kind == kROOTD_AUTH && stat == -1) {
02407          if (gDebug > 3)
02408             Info("ClearAuth", "anonymous user");
02409          anon  = 1;
02410          cryptopt = 0;
02411          reuse = 0;
02412          needsalt = 0;
02413       }
02414 
02415       // The random tag in hex representation
02416       // Protection against reply attacks
02417       char ctag[11] = {0};
02418       if (anon == 0 && cryptopt == 1) {
02419 
02420          // Check that we got the right thing ..
02421          if (kind != kROOTD_RSAKEY || stat < 1 || stat > 2 ) {
02422             // Check for errors
02423             if (kind != kROOTD_ERR) {
02424                Warning("ClearAuth",
02425                        "problems recvn RSA key flag: got message %d, flag: %d",
02426                        kind, stat);
02427             }
02428             return 0;
02429          }
02430          if (gDebug > 3)
02431             Info("ClearAuth", "get key request ...");
02432 
02433          // Save type of key
02434          fRSAKey = stat - 1;
02435 
02436          // Send the key securely
02437          if (SendRSAPublicKey(fSocket,fRSAKey) < 0)
02438             return 0;
02439 
02440          int slen = 0;
02441          if (needsalt) {
02442             // Receive password salt
02443             char *tmpsalt = 0;
02444             if ((slen = SecureRecv(fSocket, 1, fRSAKey, &tmpsalt)) == -1) {
02445                Warning("ClearAuth", "problems secure-receiving salt -"
02446                        " may result in corrupted salt");
02447                Warning("ClearAuth", "switch off reuse for this session");
02448                needsalt = 0;
02449                return 0;
02450             }
02451             if (slen) {
02452                // Extract random tag, if there
02453                if (slen > 9) {
02454                   int ltmp = slen;
02455                   while (ltmp && tmpsalt[ltmp-1] != '#') ltmp--;
02456                   if (ltmp) {
02457                      if (tmpsalt[ltmp-1] == '#' &&
02458                          tmpsalt[ltmp-10] == '#') {
02459                         strlcpy(ctag,&tmpsalt[ltmp-10],11);
02460                         // We drop the random tag
02461                         ltmp -= 10;
02462                         tmpsalt[ltmp] = 0;
02463                         // Update salt length
02464                         slen -= 10;
02465                      }
02466                   }
02467                   if (!strlen(tmpsalt)) {
02468                      // No salt left
02469                      needsalt = 0;
02470                      slen = 0;
02471                   }
02472                }
02473                if (slen)
02474                   salt = TString(tmpsalt);
02475                delete [] tmpsalt;
02476             }
02477             if (gDebug > 2)
02478                Info("ClearAuth", "got salt: '%s' (len: %d)", salt.Data(), slen);
02479          } else {
02480             if (gDebug > 2)
02481                Info("ClearAuth", "Salt not required");
02482             char *tmptag = 0;
02483             if (SecureRecv(fSocket, 1, fRSAKey, &tmptag) == -1) {
02484                Warning("ClearAuth", "problems secure-receiving rndmtag -"
02485                        " may result in corrupted rndmtag");
02486             }
02487             if (tmptag) {
02488                strlcpy(ctag, tmptag, 11);
02489                delete [] tmptag;
02490             }
02491          }
02492          // We may not have got a salt (if the server may not access it
02493          // or if it needs the full password, like for AFS ...)
02494          if (!slen)
02495             needsalt = 0;
02496       }
02497       // Now get the password either from prompt or from memory, if saved already
02498       if (anon == 1) {
02499 
02500          if (fgPasswd.Contains("@")) {
02501             // Anonymous like login with user chosen passwd ...
02502             passwd = fgPasswd;
02503          } else {
02504             // Anonymous like login with automatic passwd generation ...
02505             TString localuser;
02506             pw = gSystem->GetUserInfo();
02507             if (pw)
02508                localuser = StrDup(pw->fUser);
02509             delete pw;
02510             static TString localFQDN;
02511             if (localFQDN == "") {
02512                TInetAddress addr = gSystem->GetHostByName(gSystem->HostName());
02513                if (addr.IsValid())
02514                   localFQDN = addr.GetHostName();
02515             }
02516             passwd = Form("%s@%s", localuser.Data(), localFQDN.Data());
02517             if (gDebug > 2)
02518                Info("ClearAuth",
02519                     "automatically generated anonymous passwd: %s",
02520                     passwd.Data());
02521          }
02522 
02523       } else {
02524 
02525          if (prompt == 1 || pashash.Length() == 0) {
02526 
02527             if (passwd == "") {
02528                TString xp(Form("%s@%s password: ", user.Data(),fRemote.Data()));
02529                char *pwd = PromptPasswd(xp);
02530                passwd = TString(pwd);
02531                delete [] pwd;
02532                if (passwd == "") {
02533                   Error("ClearAuth", "password not set");
02534                   fSocket->Send("-1", kROOTD_PASS);  // Needs this for consistency
02535                   return 0;
02536                }
02537             }
02538             if (needsalt && !pwdhash) {
02539 #ifndef R__WIN32
02540                pashash = TString(crypt(passwd, salt));
02541                if (!pashash.BeginsWith(salt)) {
02542                   // not the right version of the crypt function:
02543                   // do not send hash
02544                   pashash = passwd;
02545                }
02546 #else
02547                pashash = passwd;
02548 #endif
02549             } else {
02550                pashash = passwd;
02551             }
02552          }
02553 
02554       }
02555 
02556       // Store password for later use
02557       fgUser = fUser;
02558       fgPwHash = kFALSE;
02559       fPwHash = kFALSE;
02560       fgPasswd = passwd;
02561       fPasswd = passwd;
02562       fSRPPwd = kFALSE;
02563       fgSRPPwd = kFALSE;
02564 
02565       // Send it to server
02566       if (anon == 0 && cryptopt == 1) {
02567 
02568          // Needs to send this for consistency
02569          if (fSocket->Send("\0", kROOTD_PASS) < 0)
02570             return 0;
02571 
02572          // Add the random tag received from the server
02573          // (if any); makes packets non re-usable
02574          if (strlen(ctag))
02575             pashash += ctag;
02576 
02577          if (SecureSend(fSocket, 1, fRSAKey, pashash.Data()) == -1) {
02578             Warning("ClearAuth", "problems secure-sending pass hash"
02579                     " - may result in authentication failure");
02580             return 0;
02581          }
02582       } else {
02583 
02584          // Standard technique: invert passwd
02585          if (passwd != "") {
02586             for (int i = 0; i < passwd.Length(); i++) {
02587                char inv = ~passwd(i);
02588                passwd.Replace(i, 1, inv);
02589             }
02590          }
02591          if (fSocket->Send(passwd.Data(), kROOTD_PASS) < 0)
02592             return 0;
02593       }
02594 
02595       Int_t nrec = 0;
02596       // Receive username used for login
02597       if ((nrec = fSocket->Recv(stat, kind)) < 0 )  // returns user
02598          return 0;
02599       if (gDebug > 3)
02600          Info("ClearAuth", "after kROOTD_PASS: kind= %d, stat= %d", kind,
02601               stat);
02602 
02603       // Check for errors
02604       if (kind == kROOTD_ERR) {
02605          AuthError("ClearAuth", stat);
02606          fgPasswd = "";
02607          return 0;
02608       }
02609 
02610       if (kind != kROOTD_PASS || stat < 1)
02611          Warning("ClearAuth",
02612                  "problems recvn (user,offset) length (%d:%d bytes:%d)",
02613                  kind, stat, nrec);
02614 
02615       // Get user and offset
02616       char answer[256];
02617       int reclen = (stat+1 > 256) ? 256 : stat+1;
02618       if ((nrec = fSocket->Recv(answer, reclen, kind)) < 0)
02619          return 0;
02620       if (kind != kMESS_STRING)
02621          Warning("ClearAuth",
02622                  "username and offset not received (%d:%d)", kind,
02623                  nrec);
02624 
02625       // Parse answer
02626       char lUser[128];
02627       Int_t offset = -1;
02628       sscanf(answer, "%127s %d", lUser, &offset);
02629       if (gDebug > 3)
02630          Info("ClearAuth",
02631               "received from server: user: %s, offset: %d (%s)", lUser,
02632               offset, answer);
02633 
02634       // Return username
02635       user = lUser;
02636 
02637       char *token = 0;
02638       if (reuse == 1 && offset > -1) {
02639          // Receive token
02640          if (cryptopt == 1) {
02641             if (SecureRecv(fSocket, 1, fRSAKey, &token) == -1) {
02642                Warning("ClearAuth",
02643                        "problems secure-receiving token -"
02644                        " may result in corrupted token");
02645                return 0;
02646             }
02647          } else {
02648             Int_t tlen = 9;
02649             token = new char[tlen];
02650             if (fSocket->Recv(token, tlen, kind) < 0) {
02651                delete [] token;
02652                return 0;
02653             }
02654             if (kind != kMESS_STRING)
02655                Warning("ClearAuth", "token not received (%d:%d)", kind,
02656                        nrec);
02657             // Invert token
02658             for (int i = 0; i < (int) strlen(token); i++) {
02659                token[i] = ~token[i];
02660             }
02661 
02662          }
02663          if (gDebug > 3)
02664             Info("ClearAuth", "received from server: token: '%s' ",
02665                  token);
02666       }
02667       TPwdCtx *pwdctx = new TPwdCtx(fPasswd,fPwHash);
02668       // Create SecContext object
02669       fSecContext = fHostAuth->CreateSecContext((const char *)lUser, fRemote,
02670                                                 kClear, offset, fDetails, (const char *)token,
02671                                                 fgExpDate, (void *)pwdctx, fRSAKey);
02672 
02673       // Release allocated memory ...
02674       if (token)
02675          delete [] token;
02676 
02677       // This from remote login
02678       if (fSocket->Recv(stat, kind) < 0)
02679          return 0;
02680 
02681 
02682       if (kind == kROOTD_AUTH && stat >= 1) {
02683          if (stat == 5 && fSocket->GetServType() == TSocket::kPROOFD)
02684             // AFS: we cannot reuse the token because remotely the
02685             // daemon token must be re-initialized; for PROOF, we
02686             // just flag the entry as AFS; this allows to skip reusing
02687             // but to keep the session key for password forwarding
02688             fSecContext->SetID("AFS authentication");
02689          return 1;
02690       } else {
02691          fgPasswd = "";
02692          if (kind == kROOTD_ERR)
02693             AuthError("ClearAuth", stat);
02694          return 0;
02695       }
02696 
02697    } else {
02698 
02699       // Old Protocol
02700 
02701       // Send username
02702       if (fSocket->Send(user.Data(), kROOTD_USER) < 0)
02703          return 0;
02704 
02705       // Get replay from server
02706       if (fSocket->Recv(stat, kind) < 0)
02707          return 0;
02708 
02709       // This check should guarantee backward compatibility with a private
02710       // version of rootd used by CDF
02711       if (kind == kROOTD_AUTH && stat == 1) {
02712          fSecContext =
02713             fHostAuth->CreateSecContext(user,fRemote,kClear,-1,fDetails,0);
02714          return 1;
02715       }
02716 
02717       if (kind == kROOTD_ERR) {
02718          TString server = "sockd";
02719          if (fProtocol.Contains("root"))
02720             server = "rootd";
02721          if (fProtocol.Contains("proof"))
02722             server = "proofd";
02723          if (stat == kErrConnectionRefused) {
02724             if (gDebug > 0)
02725                Error("ClearAuth",
02726                      "%s@%s does not accept connections from %s@%s",
02727                      server.Data(),fRemote.Data(),
02728                      fUser.Data(),gSystem->HostName());
02729             return -2;
02730          } else if (stat == kErrNotAllowed) {
02731             if (gDebug > 0)
02732                Error("ClearAuth",
02733                      "%s@%s does not accept %s authentication from %s@%s",
02734                      server.Data(),fRemote.Data(),
02735                      TAuthenticate::fgAuthMeth[0].Data(),
02736                      fUser.Data(),gSystem->HostName());
02737          } else
02738             AuthError("ClearAuth", stat);
02739          return 0;
02740       }
02741       // Prepare passwd to send
02742    badpass1:
02743       if (passwd == "") {
02744          TString xp(Form("%s@%s password: ", user.Data(),fRemote.Data()));
02745          char *p = PromptPasswd(xp);
02746          passwd = p;
02747          delete [] p;
02748          if (passwd == "")
02749             Error("ClearAuth", "password not set");
02750       }
02751       if (fUser == "anonymous" || fUser == "rootd") {
02752          if (!passwd.Contains("@")) {
02753             Warning("ClearAuth",
02754                     "please use passwd of form: user@host.do.main");
02755             passwd = "";
02756             goto badpass1;
02757          }
02758       }
02759 
02760       fgPasswd = passwd;
02761       fPasswd = passwd;
02762 
02763       // Invert passwd
02764       if (passwd != "") {
02765          for (int i = 0; i < passwd.Length(); i++) {
02766             char inv = ~passwd(i);
02767             passwd.Replace(i, 1, inv);
02768          }
02769       }
02770       // Send it over the net
02771       if (fSocket->Send(passwd, kROOTD_PASS) < 0)
02772          return 0;
02773 
02774       // Get result of attempt
02775       if (fSocket->Recv(stat, kind) < 0)  // returns user
02776          return 0;
02777       if (gDebug > 3)
02778          Info("ClearAuth", "after kROOTD_PASS: kind= %d, stat= %d", kind,
02779               stat);
02780 
02781       if (kind == kROOTD_AUTH && stat == 1) {
02782          fSecContext =
02783             fHostAuth->CreateSecContext(user,fRemote,kClear,-1,fDetails,0);
02784          return 1;
02785       } else {
02786          if (kind == kROOTD_ERR)
02787             AuthError("ClearAuth", stat);
02788          return 0;
02789       }
02790    }
02791    return 0;
02792 }
02793 
02794 //______________________________________________________________________________
02795 THostAuth *TAuthenticate::GetHostAuth(const char *host, const char *user,
02796                                       Option_t *opt, Int_t *exact)
02797 {
02798    // Sets fUser=user and search fgAuthInfo for the entry pertaining to
02799    // (host,user), setting fHostAuth accordingly.
02800    // If opt = "P" use fgProofAuthInfo list instead
02801    // If no entry is found fHostAuth is not changed
02802 
02803    if (exact)
02804       *exact = 0;
02805 
02806    if (gDebug > 2)
02807       ::Info("TAuthenticate::GetHostAuth", "enter ... %s ... %s", host, user);
02808 
02809    // Strip off the servertype, if any
02810    Int_t srvtyp = -1;
02811    TString hostname = host;
02812    if (hostname.Contains(":")) {
02813       char *ps = (char *)strstr(host,":");
02814       if (ps)
02815          srvtyp = atoi(ps+1);
02816       hostname.Remove(hostname.Index(":"));
02817    }
02818    TString hostFQDN = hostname;
02819    if (strncmp(host,"default",7) && !hostFQDN.Contains("*")) {
02820       TInetAddress addr = gSystem->GetHostByName(hostFQDN);
02821       if (addr.IsValid())
02822          hostFQDN = addr.GetHostName();
02823    }
02824    TString usr = user;
02825    if (!usr.Length())
02826       usr = "*";
02827    THostAuth *rHA = 0;
02828 
02829    // Check list of auth info for already loaded info about this host
02830    TIter *next = new TIter(GetAuthInfo());
02831    if (!strncasecmp(opt,"P",1)) {
02832       SafeDelete(next);
02833       next = new TIter(GetProofAuthInfo());
02834    }
02835 
02836    THostAuth *ai;
02837    Bool_t notFound = kTRUE;
02838    Bool_t serverOK = kTRUE;
02839    while ((ai = (THostAuth *) (*next)())) {
02840       if (gDebug > 3)
02841          ai->Print("Authenticate::GetHostAuth");
02842 
02843       // server
02844       if (!(serverOK = (ai->GetServer() == -1) ||
02845             (ai->GetServer() == srvtyp)))
02846          continue;
02847 
02848       // Use default entry if existing and nothing more specific is found
02849       if (!strcmp(ai->GetHost(),"default") && serverOK && notFound)
02850          rHA = ai;
02851 
02852       // Check
02853       if (CheckHost(hostFQDN,ai->GetHost()) &&
02854           CheckHost(usr,ai->GetUser())     && serverOK) {
02855          rHA = ai;
02856          notFound = kFALSE;
02857       }
02858 
02859       if (hostFQDN == ai->GetHost() &&
02860           usr == ai->GetUser()     && srvtyp == ai->GetServer() ) {
02861          rHA = ai;
02862          if (exact)
02863             *exact = 1;
02864          break;
02865       }
02866    }
02867    SafeDelete(next);
02868    return rHA;
02869 }
02870 
02871 //______________________________________________________________________________
02872 THostAuth *TAuthenticate::HasHostAuth(const char *host, const char *user,
02873                                       Option_t *opt)
02874 {
02875    // Checks if a THostAuth with exact match for {host,user} exists
02876    // in the fgAuthInfo list
02877    // If opt = "P" use ProofAuthInfo list instead
02878    // Returns pointer to it or 0
02879 
02880    if (gDebug > 2)
02881       ::Info("TAuthenticate::HasHostAuth", "enter ... %s ... %s", host, user);
02882 
02883    // Strip off the servertype, if any
02884    Int_t srvtyp = -1;
02885    TString hostFQDN = host;
02886    if (hostFQDN.Contains(":")) {
02887       char *ps = (char *)strstr(host,":");
02888       if (ps)
02889          srvtyp = atoi(ps+1);
02890       hostFQDN.Remove(hostFQDN.Index(":"));
02891    }
02892    if (strncmp(host,"default",7) && !hostFQDN.Contains("*")) {
02893       TInetAddress addr = gSystem->GetHostByName(hostFQDN);
02894       if (addr.IsValid())
02895          hostFQDN = addr.GetHostName();
02896    }
02897 
02898    TIter *next = new TIter(GetAuthInfo());
02899    if (!strncasecmp(opt,"P",1)) {
02900       SafeDelete(next);
02901       next = new TIter(GetProofAuthInfo());
02902    }
02903    THostAuth *ai;
02904    while ((ai = (THostAuth *) (*next)())) {
02905 
02906       if (hostFQDN == ai->GetHost() &&
02907           !strcmp(user, ai->GetUser()) && srvtyp == ai->GetServer()) {
02908          SafeDelete(next);
02909          return ai;
02910       }
02911    }
02912    SafeDelete(next);
02913    return 0;
02914 }
02915 
02916 //______________________________________________________________________________
02917 void TAuthenticate::FileExpand(const char *fexp, FILE *ftmp)
02918 {
02919    // Expands include directives found in fexp files
02920    // The expanded, temporary file, is pointed to by 'ftmp'
02921    // and should be already open. To be called recursively.
02922 
02923    FILE *fin;
02924    char line[kMAXPATHLEN];
02925    char cinc[20], fileinc[kMAXPATHLEN];
02926 
02927    if (gDebug > 2)
02928       ::Info("TAuthenticate::FileExpand", "enter ... '%s' ... 0x%lx", fexp, (Long_t)ftmp);
02929 
02930    fin = fopen(fexp, "r");
02931    if (fin == 0)
02932       return;
02933 
02934    while (fgets(line, sizeof(line), fin) != 0) {
02935       // Skip comment lines
02936       if (line[0] == '#')
02937          continue;
02938       if (line[strlen(line) - 1] == '\n')
02939          line[strlen(line) - 1] = '\0';
02940       if (gDebug > 2)
02941          ::Info("TAuthenticate::FileExpand", "read line ... '%s'", line);
02942       int nw = sscanf(line, "%19s %8191s", cinc, fileinc);
02943       if (nw < 1)
02944          continue;              // Not enough info in this line
02945       if (strcmp(cinc, "include") != 0) {
02946          // copy line in temporary file
02947          fprintf(ftmp, "%s\n", line);
02948       } else {
02949 
02950          // Drop quotes or double quotes, if any
02951          TString ln(line);
02952          ln.ReplaceAll("\"",1,"",0);
02953          ln.ReplaceAll("'",1,"",0);
02954          sscanf(ln.Data(), "%19s %8191s", cinc, fileinc);
02955 
02956          // support environment directories ...
02957          if (fileinc[0] == '$') {
02958             TString finc(fileinc);
02959             TString edir(fileinc);
02960             if (edir.Contains("/")) {
02961                edir.Remove(edir.Index("/"));
02962                edir.Remove(0,1);
02963                if (gSystem->Getenv(edir.Data())) {
02964                   finc.Remove(0,1);
02965                   finc.ReplaceAll(edir.Data(),gSystem->Getenv(edir.Data()));
02966                   fileinc[0] = '\0';
02967                   strncpy(fileinc,finc.Data(),kMAXPATHLEN);
02968                   fileinc[kMAXPATHLEN-1] = '\0';
02969                }
02970             }
02971          }
02972 
02973          // open (expand) file in temporary file ...
02974          if (fileinc[0] == '~') {
02975             // needs to expand
02976             int flen =
02977                strlen(fileinc) + strlen(gSystem->HomeDirectory()) + 10;
02978             char *ffull = new char[flen];
02979             snprintf(ffull, flen, "%s/%s", gSystem->HomeDirectory(), fileinc + 1);
02980             if (strlen(ffull) < kMAXPATHLEN - 1) strlcpy(fileinc, ffull,kMAXPATHLEN);
02981             delete [] ffull;
02982          }
02983          // Check if file exist and can be read ... ignore if not ...
02984          if (!gSystem->AccessPathName(fileinc, kReadPermission)) {
02985             FileExpand(fileinc, ftmp);
02986          } else {
02987             ::Warning("TAuthenticate::FileExpand",
02988                       "file specified by 'include' cannot be open or read (%s)",
02989                       fileinc);
02990          }
02991       }
02992    }
02993    fclose(fin);
02994 }
02995 
02996 //______________________________________________________________________________
02997 char *TAuthenticate::GetDefaultDetails(int sec, int opt, const char *usr)
02998 {
02999    // Determine default authentication details for method 'sec' and user 'usr'.
03000    // Checks .rootrc family files. Returned string must be deleted by the user.
03001 
03002    char temp[kMAXPATHLEN] = { 0 };
03003    const char copt[2][5] = { "no", "yes" };
03004 
03005    if (gDebug > 2)
03006       ::Info("TAuthenticate::GetDefaultDetails",
03007              "enter ... %d ...pt:%d ... '%s'", sec, opt, usr);
03008 
03009    if (opt < 0 || opt > 1)
03010       opt = 1;
03011 
03012    // UsrPwd
03013    if (sec == TAuthenticate::kClear) {
03014       if (strlen(usr) == 0 || !strncmp(usr,"*",1))
03015          usr = gEnv->GetValue("UsrPwd.Login", "");
03016       snprintf(temp, kMAXPATHLEN, "pt:%s ru:%s cp:%s us:%s",
03017                gEnv->GetValue("UsrPwd.LoginPrompt", copt[opt]),
03018                gEnv->GetValue("UsrPwd.ReUse", "1"),
03019                gEnv->GetValue("UsrPwd.Crypt", "1"), usr);
03020 
03021       // SRP
03022    } else if (sec == TAuthenticate::kSRP) {
03023       if (strlen(usr) == 0 || !strncmp(usr,"*",1))
03024          usr = gEnv->GetValue("SRP.Login", "");
03025       snprintf(temp, kMAXPATHLEN, "pt:%s ru:%s us:%s",
03026                gEnv->GetValue("SRP.LoginPrompt", copt[opt]),
03027                gEnv->GetValue("SRP.ReUse", "0"), usr);
03028 
03029       // Kerberos
03030    } else if (sec == TAuthenticate::kKrb5) {
03031       if (strlen(usr) == 0 || !strncmp(usr,"*",1))
03032          usr = gEnv->GetValue("Krb5.Login", "");
03033       snprintf(temp, kMAXPATHLEN, "pt:%s ru:%s us:%s",
03034                gEnv->GetValue("Krb5.LoginPrompt", copt[opt]),
03035                gEnv->GetValue("Krb5.ReUse", "0"), usr);
03036 
03037       // Globus
03038    } else if (sec == TAuthenticate::kGlobus) {
03039       snprintf(temp, kMAXPATHLEN,"pt:%s ru:%s %s",
03040                gEnv->GetValue("Globus.LoginPrompt", copt[opt]),
03041                gEnv->GetValue("Globus.ReUse", "1"),
03042                gEnv->GetValue("Globus.Login", ""));
03043 
03044       // SSH
03045    } else if (sec == TAuthenticate::kSSH) {
03046       if (strlen(usr) == 0 || !strncmp(usr,"*",1))
03047          usr = gEnv->GetValue("SSH.Login", "");
03048       snprintf(temp, kMAXPATHLEN, "pt:%s ru:%s us:%s",
03049                gEnv->GetValue("SSH.LoginPrompt", copt[opt]),
03050                gEnv->GetValue("SSH.ReUse", "1"), usr);
03051 
03052       // Uid/Gid
03053    } else if (sec == TAuthenticate::kRfio) {
03054       if (strlen(usr) == 0 || !strncmp(usr,"*",1))
03055          usr = gEnv->GetValue("UidGid.Login", "");
03056       snprintf(temp, kMAXPATHLEN, "pt:%s us:%s",
03057                gEnv->GetValue("UidGid.LoginPrompt", copt[opt]), usr);
03058    }
03059    if (gDebug > 2)
03060       ::Info("TAuthenticate::GetDefaultDetails", "returning ... %s", temp);
03061 
03062    return StrDup(temp);
03063 }
03064 
03065 //______________________________________________________________________________
03066 void TAuthenticate::RemoveHostAuth(THostAuth * ha, Option_t *opt)
03067 {
03068    // Remove THostAuth instance from the list
03069 
03070    if (!strncasecmp(opt,"P",1))
03071       GetProofAuthInfo()->Remove(ha);
03072    else
03073       GetAuthInfo()->Remove(ha);
03074    // ... destroy it
03075    delete ha;
03076 }
03077 
03078 //______________________________________________________________________________
03079 void TAuthenticate::Show(Option_t *opt)
03080 {
03081    // Print info about the authentication sector.
03082    // If 'opt' contains 's' or 'S' prints information about established TSecContext,
03083    // else prints information about THostAuth (if 'opt' is 'p' or 'P', prints
03084    // Proof related information)
03085 
03086    TString sopt(opt);
03087 
03088    if (sopt.Contains("s",TString::kIgnoreCase)) {
03089 
03090       // Print established security contexts
03091       TIter next(gROOT->GetListOfSecContexts());
03092       TSecContext *sc = 0;
03093       while ((sc = (TSecContext *)next()))
03094          sc->Print();
03095 
03096    } else {
03097 
03098       ::Info("::Print",
03099              " +--------------------------- BEGIN --------------------------------+");
03100       ::Info("::Print",
03101              " +                                                                  +");
03102       if (sopt.Contains("p",TString::kIgnoreCase)) {
03103          ::Info("::Print",
03104                 " + List fgProofAuthInfo has %4d members                            +",
03105                 GetProofAuthInfo()->GetSize());
03106          ::Info("::Print",
03107                 " +                                                                  +");
03108          ::Info("::Print",
03109                 " +------------------------------------------------------------------+");
03110          TIter next(GetProofAuthInfo());
03111          THostAuth *ai;
03112          while ((ai = (THostAuth *) next())) {
03113             ai->Print();
03114          }
03115       } else {
03116          ::Info("::Print",
03117                 " + List fgAuthInfo has %4d members                                 +",
03118                 GetAuthInfo()->GetSize());
03119          ::Info("::Print",
03120                 " +                                                                  +");
03121          ::Info("::Print",
03122                 " +------------------------------------------------------------------+");
03123          TIter next(GetAuthInfo());
03124          THostAuth *ai;
03125          while ((ai = (THostAuth *) next())) {
03126             ai->Print();
03127             ai->PrintEstablished();
03128          }
03129       }
03130       ::Info("::Print",
03131              " +---------------------------- END ---------------------------------+");
03132    }
03133 }
03134 
03135 //______________________________________________________________________________
03136 Int_t TAuthenticate::AuthExists(TString username, Int_t method, const char *options,
03137                                 Int_t *message, Int_t *rflag,
03138                                 CheckSecCtx_t checksecctx)
03139 {
03140    // Check if we have a valid established sec context in memory
03141    // Retrieves relevant info and negotiates with server.
03142    // options = "Opt,strlen(username),username.Data()"
03143    // message = kROOTD_USER, ...
03144 
03145    // Welcome message, if requested ...
03146    if (gDebug > 2)
03147       Info("AuthExists","%d: enter: msg: %d options: '%s'",
03148            method,*message, options);
03149 
03150    // Look for an existing security context matching this request
03151    Bool_t notHA = kFALSE;
03152 
03153    // First in the local list
03154    TIter next(fHostAuth->Established());
03155    TRootSecContext *secctx;
03156    while ((secctx = (TRootSecContext *)next())) {
03157       if (secctx->GetMethod() == method) {
03158          if (fRemote == secctx->GetHost()) {
03159             if (checksecctx &&
03160                 (*checksecctx)(username,secctx) == 1)
03161                break;
03162          }
03163       }
03164    }
03165 
03166    // If nothing found, try the all list
03167    if (!secctx) {
03168       next = TIter(gROOT->GetListOfSecContexts());
03169       while ((secctx = (TRootSecContext *)next())) {
03170          if (secctx->GetMethod() == method) {
03171             if (fRemote == secctx->GetHost()) {
03172                if (checksecctx &&
03173                    (*checksecctx)(username,secctx) == 1) {
03174                   notHA = kTRUE;
03175                   break;
03176                }
03177             }
03178          }
03179       }
03180    }
03181 
03182    // If we have been given a valid sec context retrieve some info
03183    Int_t offset = -1;
03184    TString token;
03185    if (secctx) {
03186       offset = secctx->GetOffSet();
03187       token = secctx->GetToken();
03188       if (gDebug > 2)
03189          Info("AuthExists",
03190               "found valid TSecContext: offset: %d token: '%s'",
03191               offset, token.Data());
03192    }
03193 
03194    // Prepare string to be sent to the server
03195    TString sstr(Form("%d %d %s", fgProcessID, offset, options));
03196 
03197    // Send message
03198    if (fSocket->Send(sstr, *message) < 0)
03199       return -2;
03200 
03201    Int_t reuse = *rflag;
03202    if (reuse == 1 && offset > -1) {
03203 
03204       // Receive result of checking offset
03205       // But only for recent servers
03206       // NB: not backward compatible with dev version 4.00.02: switch
03207       // off 'reuse' for such servers to avoid hanging at this point.
03208       Int_t rproto = fSocket->GetRemoteProtocol();
03209       Bool_t oldsrv = ((fProtocol.BeginsWith("root") && rproto == 9) ||
03210                        (fProtocol.BeginsWith("proof") && rproto == 8));
03211       Int_t stat = 1, kind;
03212       if (!oldsrv) {
03213          if (fSocket->Recv(stat, kind) < 0)
03214             return -2;
03215          if (kind != kROOTD_AUTH)
03216             Warning("AuthExists","protocol error: expecting %d got %d"
03217                     " (value: %d)",kROOTD_AUTH,kind,stat);
03218       }
03219 
03220       if (stat > 0) {
03221          if (gDebug > 2)
03222             Info("AuthExists","offset OK");
03223 
03224          Int_t rsaKey = secctx->GetRSAKey();
03225          if (gDebug > 2)
03226             Info("AuthExists", "key type: %d", rsaKey);
03227 
03228          if (rsaKey > -1) {
03229 
03230             // Recent servers send a random tag in stat
03231             // It has to be signed too
03232             if (stat > 1) {
03233                // Create hex from tag
03234                char tag[9] = {0};
03235                snprintf(tag, 9, "%08x",stat);
03236                // Add to token
03237                token += tag;
03238             }
03239 
03240             // Send token encrypted
03241             if (SecureSend(fSocket, 1, rsaKey, token) == -1) {
03242                Warning("AuthExists", "problems secure-sending token %s",
03243                        "- may trigger problems in proofing Id ");
03244                return -2;
03245             }
03246          } else {
03247             // Send inverted
03248             for (int i = 0; i < token.Length(); i++) {
03249                char inv = ~token(i);
03250                token.Replace(i, 1, inv);
03251             }
03252             if (fSocket->Send(token, kMESS_STRING) < 0)
03253                return -2;
03254          }
03255       } else {
03256          if (gDebug > 0)
03257             Info("AuthExists","offset not OK - rerun authentication");
03258          // If the sec context was not valid, deactivate it ...
03259          if (secctx)
03260             secctx->DeActivate("");
03261       }
03262    }
03263 
03264    Int_t stat, kind;
03265    if (fSocket->Recv(stat, kind) < 0)
03266       return -2;
03267    if (gDebug > 3)
03268       Info("AuthExists","%d: after msg %d: kind= %d, stat= %d",
03269            method,*message, kind, stat);
03270 
03271    // Return flags
03272    *message = kind;
03273    *rflag = stat;
03274 
03275    if (kind == kROOTD_ERR) {
03276       TString server = "sockd";
03277       if (fSocket->GetServType() == TSocket::kROOTD)
03278          server = "rootd";
03279       if (fSocket->GetServType() == TSocket::kPROOFD)
03280          server = "proofd";
03281       if (stat == kErrConnectionRefused) {
03282          Error("AuthExists","%s@%s does not accept connections from %s@%s",
03283                server.Data(),fRemote.Data(),fUser.Data(),gSystem->HostName());
03284          return -2;
03285       } else if (stat == kErrNotAllowed) {
03286          if (gDebug > 0)
03287             Info("AuthExists",
03288                  "%s@%s does not accept %s authentication from %s@%s",
03289                  server.Data(),fRemote.Data(), fgAuthMeth[method].Data(),
03290                  fUser.Data(),gSystem->HostName());
03291       } else
03292          AuthError("AuthExists", stat);
03293 
03294       // If the sec context was not valid, deactivate it ...
03295       if (secctx)
03296          secctx->DeActivate("");
03297       return 0;
03298    }
03299 
03300    if (kind == kROOTD_AUTH && stat >= 1) {
03301       if (!secctx)
03302          secctx =
03303             fHostAuth->CreateSecContext(fUser,fRemote,method,-stat,fDetails,0);
03304       if (gDebug > 3) {
03305          if (stat == 1)
03306             Info("AuthExists", "valid authentication exists");
03307          if (stat == 2)
03308             Info("AuthExists", "valid authentication exists: offset changed");
03309          if (stat == 3)
03310             Info("AuthExists", "remote access authorized by /etc/hosts.equiv");
03311          if (stat == 4)
03312             Info("AuthExists", "no authentication required remotely");
03313       }
03314 
03315       if (stat == 2) {
03316          int newOffSet;
03317          // Receive new offset ...
03318          if (fSocket->Recv(newOffSet, kind) < 0)
03319             return -2;
03320          // ... and save it
03321          secctx->SetOffSet(newOffSet);
03322       }
03323 
03324       fSecContext = secctx;
03325       // Add it to local list for later use (if not already there)
03326       if (notHA)
03327          fHostAuth->Established()->Add(secctx);
03328       return 1;
03329    }
03330    return 0;
03331 }
03332 
03333 //______________________________________________________________________________
03334 void TAuthenticate::InitRandom()
03335 {
03336    // Initialize random machine using seed from /dev/urandom
03337    // (or current time if /dev/urandom not available).
03338 
03339    static Bool_t notinit = kTRUE;
03340 
03341    if (notinit) {
03342       const char *randdev = "/dev/urandom";
03343       Int_t fd;
03344       UInt_t seed;
03345       if ((fd = open(randdev, O_RDONLY)) != -1) {
03346          if (gDebug > 2)
03347             ::Info("InitRandom", "taking seed from %s", randdev);
03348          if (read(fd, &seed, sizeof(seed)) != sizeof(seed))
03349             ::Warning("InitRandom", "could not read seed from %s", randdev);
03350          close(fd);
03351       } else {
03352          if (gDebug > 2)
03353             ::Info("InitRandom", "%s not available: using time()", randdev);
03354          seed = time(0);   //better use times() + win32 equivalent
03355       }
03356       srand(seed);
03357       notinit = kFALSE;
03358    }
03359 }
03360 
03361 //______________________________________________________________________________
03362 Int_t TAuthenticate::GenRSAKeys()
03363 {
03364    // Generate a valid pair of private/public RSA keys to protect for
03365    // authentication token exchange
03366 
03367    if (gDebug > 2)
03368       Info("GenRSAKeys", "enter");
03369 
03370    if (fgRSAInit == 1) {
03371       if (gDebug > 2)
03372          Info("GenRSAKeys", "Keys prviously generated - return");
03373    }
03374 
03375    // This is for dynamic loads ...
03376    TString lib = "libRsa";
03377 
03378    // This is the local RSA implementation
03379    if (!TRSA_fun::RSA_genprim()) {
03380       char *p;
03381       if ((p = gSystem->DynamicPathName(lib, kTRUE))) {
03382          delete [] p;
03383          gSystem->Load(lib);
03384       }
03385    }
03386 
03387    // Init random machine
03388    TAuthenticate::InitRandom();
03389 
03390 #ifdef R__SSL
03391    if (fgRSAKey == 1) {
03392       // Generate also the SSL key
03393       if (gDebug > 2)
03394          Info("GenRSAKeys","SSL: Generate Blowfish key");
03395 
03396       // Init SSL ...
03397       SSL_library_init();
03398 
03399       //  ... and its error strings
03400       SSL_load_error_strings();
03401 
03402       // Load Ciphers
03403       OpenSSL_add_all_ciphers();
03404 
03405       // Number of bits for key
03406       Int_t nbits = gEnv->GetValue("SSL.BFBits",256);
03407 
03408       // Minimum is 128
03409       nbits = (nbits >= 128) ? nbits : 128;
03410 
03411       // Max to limit size of buffers to 15912 (internal limitation)
03412       nbits = (nbits <= 15912) ? nbits : 15912;
03413 
03414       // Closer Number of chars
03415       Int_t klen = nbits / 8 ;
03416 
03417       // Init random engine
03418       char *rbuf = GetRandString(0,klen);
03419       RAND_seed(rbuf,strlen(rbuf));
03420 
03421       // This is what we export
03422       fgRSAPubExport[1].len = klen;
03423       fgRSAPubExport[1].keys = rbuf;
03424       if (gDebug > 2)
03425          Info("GenRSAKeys","SSL: BF key length: %d", fgRSAPubExport[1].len);
03426 
03427       // Now set the key locally in BF form
03428       BF_set_key(&fgBFKey, klen, (const unsigned char *)rbuf);
03429    }
03430 #endif
03431 
03432    // Sometimes some bunch is not decrypted correctly
03433    // That's why we make retries to make sure that encryption/decryption
03434    // works as expected
03435    Bool_t notOk = 1;
03436    rsa_NUMBER p1, p2, rsa_n, rsa_e, rsa_d;
03437    Int_t l_n = 0, l_e = 0, l_d = 0;
03438    char buf_n[rsa_STRLEN], buf_e[rsa_STRLEN], buf_d[rsa_STRLEN];
03439 #if R__RSADEB
03440    char buf[rsa_STRLEN];
03441 #endif
03442 
03443    Int_t nAttempts = 0;
03444    Int_t thePrimeLen = kPRIMELENGTH;
03445    Int_t thePrimeExp = kPRIMEEXP;   // Prime probability = 1-0.5^thePrimeExp
03446    while (notOk && nAttempts < kMAXRSATRIES) {
03447 
03448       nAttempts++;
03449       if (gDebug > 2 && nAttempts > 1) {
03450          Info("GenRSAKeys", "retry no. %d",nAttempts);
03451          srand(auth_rand());
03452       }
03453 
03454       // Valid pair of primes
03455       p1 = TRSA_fun::RSA_genprim()(thePrimeLen, thePrimeExp);
03456       p2 = TRSA_fun::RSA_genprim()(thePrimeLen+1, thePrimeExp);
03457 
03458       // Retry if equal
03459       Int_t nPrimes = 0;
03460       while (TRSA_fun::RSA_cmp()(&p1, &p2) == 0 && nPrimes < kMAXRSATRIES) {
03461          nPrimes++;
03462          if (gDebug > 2)
03463             Info("GenRSAKeys", "equal primes: regenerate (%d times)",nPrimes);
03464          srand(auth_rand());
03465          p1 = TRSA_fun::RSA_genprim()(thePrimeLen, thePrimeExp);
03466          p2 = TRSA_fun::RSA_genprim()(thePrimeLen+1, thePrimeExp);
03467       }
03468 #if R__RSADEB
03469       if (gDebug > 3) {
03470          TRSA_fun::RSA_num_sput()(&p1, buf, rsa_STRLEN);
03471          Info("GenRSAKeys", "local: p1: '%s' ", buf);
03472          TRSA_fun::RSA_num_sput()(&p2, buf, rsa_STRLEN);
03473          Info("GenRSAKeys", "local: p2: '%s' ", buf);
03474       }
03475 #endif
03476       // Generate keys
03477       if (TRSA_fun::RSA_genrsa()(p1, p2, &rsa_n, &rsa_e, &rsa_d)) {
03478          if (gDebug > 2 && nAttempts > 1)
03479             Info("GenRSAKeys"," genrsa: unable to generate keys (%d)",
03480                  nAttempts);
03481          continue;
03482       }
03483 
03484       // Get equivalent strings and determine their lengths
03485       TRSA_fun::RSA_num_sput()(&rsa_n, buf_n, rsa_STRLEN);
03486       l_n = strlen(buf_n);
03487       TRSA_fun::RSA_num_sput()(&rsa_e, buf_e, rsa_STRLEN);
03488       l_e = strlen(buf_e);
03489       TRSA_fun::RSA_num_sput()(&rsa_d, buf_d, rsa_STRLEN);
03490       l_d = strlen(buf_d);
03491 
03492 #if R__RSADEB
03493       if (gDebug > 3) {
03494          Info("GenRSAKeys", "local: n: '%s' length: %d", buf_n, l_n);
03495          Info("GenRSAKeys", "local: e: '%s' length: %d", buf_e, l_e);
03496          Info("GenRSAKeys", "local: d: '%s' length: %d", buf_d, l_d);
03497       }
03498 #endif
03499       if (TRSA_fun::RSA_cmp()(&rsa_n, &rsa_e) <= 0)
03500          continue;
03501       if (TRSA_fun::RSA_cmp()(&rsa_n, &rsa_d) <= 0)
03502          continue;
03503 
03504       // Now we try the keys
03505       char test[2 * rsa_STRLEN] = "ThisIsTheStringTest01203456-+/";
03506       Int_t lTes = 31;
03507       char *tdum = GetRandString(0, lTes - 1);
03508       strlcpy(test, tdum, lTes+1);
03509       delete [] tdum;
03510       char buf[2 * rsa_STRLEN];
03511       if (gDebug > 3)
03512          Info("GenRSAKeys", "local: test string: '%s' ", test);
03513 
03514       // Private/Public
03515       strlcpy(buf, test, lTes+1);
03516 
03517       // Try encryption with private key
03518       int lout = TRSA_fun::RSA_encode()(buf, lTes, rsa_n, rsa_e);
03519       if (gDebug > 3)
03520          Info("GenRSAKeys",
03521               "local: length of crypted string: %d bytes", lout);
03522 
03523       // Try decryption with public key
03524       TRSA_fun::RSA_decode()(buf, lout, rsa_n, rsa_d);
03525       buf[lTes] = 0;
03526       if (gDebug > 3)
03527          Info("GenRSAKeys", "local: after private/public : '%s' ", buf);
03528 
03529       if (strncmp(test, buf, lTes))
03530          continue;
03531 
03532       // Public/Private
03533       strlcpy(buf, test, lTes+1);
03534 
03535       // Try encryption with public key
03536       lout = TRSA_fun::RSA_encode()(buf, lTes, rsa_n, rsa_d);
03537       if (gDebug > 3)
03538          Info("GenRSAKeys", "local: length of crypted string: %d bytes ",
03539               lout);
03540 
03541       // Try decryption with private key
03542       TRSA_fun::RSA_decode()(buf, lout, rsa_n, rsa_e);
03543       buf[lTes] = 0;
03544       if (gDebug > 3)
03545          Info("GenRSAKeys", "local: after public/private : '%s' ", buf);
03546 
03547       if (strncmp(test, buf, lTes))
03548          continue;
03549 
03550       notOk = 0;
03551    }
03552 
03553    // Save Private key
03554    TRSA_fun::RSA_assign()(&fgRSAPriKey.n, &rsa_n);
03555    TRSA_fun::RSA_assign()(&fgRSAPriKey.e, &rsa_e);
03556 
03557    // Save Public key
03558    TRSA_fun::RSA_assign()(&fgRSAPubKey.n, &rsa_n);
03559    TRSA_fun::RSA_assign()(&fgRSAPubKey.e, &rsa_d);
03560 
03561 #if R__RSADEB
03562    if (gDebug > 2) {
03563       // Determine their lengths
03564       Info("GenRSAKeys", "local: generated keys are:");
03565       Info("GenRSAKeys", "local: n: '%s' length: %d", buf_n, l_n);
03566       Info("GenRSAKeys", "local: e: '%s' length: %d", buf_e, l_e);
03567       Info("GenRSAKeys", "local: d: '%s' length: %d", buf_d, l_d);
03568    }
03569 #endif
03570    // Export form
03571    if (fgRSAPubExport[0].keys) {
03572       delete [] fgRSAPubExport[0].keys;
03573       fgRSAPubExport[0].len = 0;
03574    }
03575    fgRSAPubExport[0].len = l_n + l_d + 4;
03576    fgRSAPubExport[0].keys = new char[fgRSAPubExport[0].len];
03577 
03578    fgRSAPubExport[0].keys[0] = '#';
03579    memcpy(fgRSAPubExport[0].keys + 1, buf_n, l_n);
03580    fgRSAPubExport[0].keys[l_n + 1] = '#';
03581    memcpy(fgRSAPubExport[0].keys + l_n + 2, buf_d, l_d);
03582    fgRSAPubExport[0].keys[l_n + l_d + 2] = '#';
03583    fgRSAPubExport[0].keys[l_n + l_d + 3] = 0;
03584 #if R__RSADEB
03585    if (gDebug > 2)
03586       Info("GenRSAKeys", "local: export pub: '%s'", fgRSAPubExport[0].keys);
03587 #else
03588    if (gDebug > 2)
03589       Info("GenRSAKeys", "local: export pub length: %d bytes", fgRSAPubExport[0].len);
03590 #endif
03591 
03592    // Set availability flag
03593    fgRSAInit = 1;
03594 
03595    return 0;
03596 }
03597 
03598 //______________________________________________________________________________
03599 char *TAuthenticate::GetRandString(Int_t opt, Int_t len)
03600 {
03601    // Allocates and fills a 0 terminated buffer of length len+1 with
03602    // len random characters.
03603    // Returns pointer to the buffer (to be deleted by the caller)
03604    // opt = 0      any non dangerous char
03605    //       1      letters and numbers  (upper and lower case)
03606    //       2      hex characters       (upper and lower case)
03607 
03608    int iimx[4][4] = {
03609       {0x0, 0xffffff08, 0xafffffff, 0x2ffffffe}, // opt = 0
03610       {0x0, 0x3ff0000, 0x7fffffe, 0x7fffffe},    // opt = 1
03611       {0x0, 0x3ff0000, 0x7e, 0x7e},              // opt = 2
03612       {0x0, 0x3ffc000, 0x7fffffe, 0x7fffffe}     // opt = 3
03613    };
03614 
03615    const char *cOpt[4] = { "Any", "LetNum", "Hex", "Crypt" };
03616 
03617    //  Default option 0
03618    if (opt < 0 || opt > 2) {
03619       opt = 0;
03620       if (gDebug > 2)
03621          Info("GetRandString", "unknown option: %d : assume 0", opt);
03622    }
03623    if (gDebug > 2)
03624       Info("GetRandString", "enter ... len: %d %s", len, cOpt[opt]);
03625 
03626    // Allocate buffer
03627    char *buf = new char[len + 1];
03628 
03629    // Init random machine (if needed)
03630    TAuthenticate::InitRandom();
03631 
03632    // randomize
03633    Int_t k = 0;
03634    Int_t i, j, l, m, frnd;
03635    while (k < len) {
03636       frnd = auth_rand();
03637       for (m = 7; m < 32; m += 7) {
03638          i = 0x7F & (frnd >> m);
03639          j = i / 32;
03640          l = i - j * 32;
03641          if ((iimx[opt][j] & (1 << l))) {
03642             buf[k] = i;
03643             k++;
03644          }
03645          if (k == len)
03646             break;
03647       }
03648    }
03649 
03650    // null terminated
03651    buf[len] = 0;
03652    if (gDebug > 3)
03653       Info("GetRandString", "got '%s' ", buf);
03654 
03655    return buf;
03656 }
03657 
03658 //______________________________________________________________________________
03659 Int_t TAuthenticate::SecureSend(TSocket *sock, Int_t enc,
03660                                 Int_t key, const char *str)
03661 {
03662    // Encode null terminated str using the session private key indicated by enc
03663    // and sends it over the network
03664    // Returns number of bytes sent, or -1 in case of error.
03665    // enc = 1 for private encoding, enc = 2 for public encoding
03666 
03667    char buftmp[kMAXSECBUF];
03668    char buflen[20];
03669 
03670    if (gDebug > 2)
03671       ::Info("TAuthenticate::SecureSend", "local: enter ... (enc: %d)", enc);
03672 
03673    Int_t slen = strlen(str) + 1;
03674    Int_t ttmp = 0;
03675    Int_t nsen = -1;
03676 
03677    if (key == 0) {
03678       strlcpy(buftmp, str, slen+1);
03679 
03680       if (enc == 1)
03681          ttmp = TRSA_fun::RSA_encode()(buftmp, slen, fgRSAPriKey.n,
03682                                        fgRSAPriKey.e);
03683       else if (enc == 2)
03684          ttmp = TRSA_fun::RSA_encode()(buftmp, slen, fgRSAPubKey.n,
03685                                        fgRSAPubKey.e);
03686       else
03687          return nsen;
03688    } else if (key == 1) {
03689 
03690 #ifdef R__SSL
03691       ttmp = strlen(str);
03692       if ((ttmp % 8) > 0)           // It should be a multiple of 8!
03693          ttmp = ((ttmp + 8)/8) * 8;
03694       unsigned char iv[8];
03695       memset((void *)&iv[0],0,8);
03696       BF_cbc_encrypt((const unsigned char *)str, (unsigned char *)buftmp,
03697                      strlen(str), &fgBFKey, iv, BF_ENCRYPT);
03698 #else
03699       if (gDebug > 0)
03700          ::Info("TAuthenticate::SecureSend","not compiled with SSL support:"
03701                 " you should not have got here!");
03702 #endif
03703    } else {
03704       if (gDebug > 0)
03705          ::Info("TAuthenticate::SecureSend","unknown key type (%d)",key);
03706       return nsen;
03707    }
03708 
03709    snprintf(buflen,20,"%d",ttmp);
03710    if (sock->Send(buflen, kROOTD_ENCRYPT) < 0)
03711       return -1;
03712    nsen = sock->SendRaw(buftmp, ttmp);
03713    if (gDebug > 3)
03714       ::Info("TAuthenticate::SecureSend",
03715              "local: sent %d bytes (expected: %d)", nsen,ttmp);
03716 
03717    return nsen;
03718 }
03719 
03720 //______________________________________________________________________________
03721 Int_t TAuthenticate::SecureRecv(TSocket *sock, Int_t dec, Int_t key, char **str)
03722 {
03723    // Receive str from sock and decode it using key indicated by key type
03724    // Return number of received bytes or -1 in case of error.
03725    // dec = 1 for private decoding, dec = 2 for public decoding
03726 
03727 
03728    char buftmp[kMAXSECBUF];
03729    char buflen[20];
03730 
03731    Int_t nrec = -1;
03732    // We must get a pointer ...
03733    if (!str)
03734       return nrec;
03735 
03736    Int_t kind;
03737    if (sock->Recv(buflen, 20, kind) < 0)
03738       return -1;
03739    Int_t len = atoi(buflen);
03740    if (gDebug > 3)
03741       ::Info("TAuthenticate::SecureRecv", "got len '%s' %d (msg kind: %d)",
03742              buflen, len, kind);
03743    if (len == 0) {
03744       return len;
03745    }
03746    if (!strncmp(buflen, "-1", 2))
03747       return nrec;
03748 
03749    // Receive buffer
03750    if ((nrec = sock->RecvRaw(buftmp, len)) < 0)
03751       return nrec;
03752    if (key == 0) {
03753       if (dec == 1)
03754          TRSA_fun::RSA_decode()(buftmp, len, fgRSAPriKey.n, fgRSAPriKey.e);
03755       else if (dec == 2)
03756          TRSA_fun::RSA_decode()(buftmp, len, fgRSAPubKey.n, fgRSAPubKey.e);
03757       else
03758          return -1;
03759 
03760       // Prepare output
03761       *str = new char[strlen(buftmp) + 1];
03762       strlcpy(*str, buftmp,strlen(buftmp) + 1);
03763 
03764    } else if (key == 1) {
03765 #ifdef R__SSL
03766       unsigned char iv[8];
03767       memset((void *)&iv[0],0,8);
03768       *str = new char[nrec + 1];
03769       BF_cbc_encrypt((const unsigned char *)buftmp, (unsigned char *)(*str),
03770                      nrec, &fgBFKey, iv, BF_DECRYPT);
03771       (*str)[nrec] = '\0';
03772 #else
03773       if (gDebug > 0)
03774          ::Info("TAuthenticate::SecureRecv","not compiled with SSL support:"
03775                 " you should not have got here!");
03776 #endif
03777    } else {
03778       if (gDebug > 0)
03779          ::Info("TAuthenticate::SecureRecv","unknown key type (%d)",key);
03780       return -1;
03781    }
03782 
03783    nrec= strlen(*str);
03784 
03785    return nrec;
03786 }
03787 
03788 //______________________________________________________________________________
03789 Int_t TAuthenticate::DecodeRSAPublic(const char *rsaPubExport, rsa_NUMBER &rsa_n,
03790                                      rsa_NUMBER &rsa_d, char **rsassl)
03791 {
03792    // Store RSA public keys from export string rsaPubExport.
03793 
03794    if (!rsaPubExport)
03795       return -1;
03796 
03797    if (gDebug > 2)
03798       ::Info("TAuthenticate::DecodeRSAPublic",
03799              "enter: string length: %ld bytes", (Long_t)strlen(rsaPubExport));
03800 
03801    char str[kMAXPATHLEN] = { 0 };
03802    Int_t klen = strlen(rsaPubExport);
03803    if (klen > kMAXPATHLEN - 1) {
03804       ::Info("TAuthenticate::DecodeRSAPublic",
03805              "key too long (%d): truncate to %d",klen,kMAXPATHLEN);
03806       klen = kMAXPATHLEN - 1;
03807    }
03808    memcpy(str, rsaPubExport, klen);
03809    str[klen] ='\0';
03810 
03811    Int_t keytype = -1;
03812 
03813    if (klen > 0) {
03814 
03815       // Skip spaces at beginning, if any
03816       int k = 0;
03817       while (str[k] == 32) k++;
03818 
03819       if (str[k] == '#') {
03820 
03821          keytype = 0;
03822 
03823          // The format is #<hex_n>#<hex_d>#
03824          char *pd1 = strstr(str, "#");
03825          char *pd2 = pd1 ? strstr(pd1 + 1, "#") : (char *)0;
03826          char *pd3 = pd2 ? strstr(pd2 + 1, "#") : (char *)0;
03827          if (pd1 && pd2 && pd3) {
03828             // Get <hex_n> ...
03829             int l1 = (int) (pd2 - pd1 - 1);
03830             char *rsa_n_exp = new char[l1 + 1];
03831             strlcpy(rsa_n_exp, pd1 + 1, l1+1);
03832             if (gDebug > 2)
03833                ::Info("TAuthenticate::DecodeRSAPublic",
03834                       "got %ld bytes for rsa_n_exp", (Long_t)strlen(rsa_n_exp));
03835             // Now <hex_d>
03836             int l2 = (int) (pd3 - pd2 - 1);
03837             char *rsa_d_exp = new char[l2 + 1];
03838             strlcpy(rsa_d_exp, pd2 + 1, 13);
03839             if (gDebug > 2)
03840                ::Info("TAuthenticate::DecodeRSAPublic",
03841                       "got %ld bytes for rsa_d_exp", (Long_t)strlen(rsa_d_exp));
03842 
03843             TRSA_fun::RSA_num_sget()(&rsa_n, rsa_n_exp);
03844             TRSA_fun::RSA_num_sget()(&rsa_d, rsa_d_exp);
03845 
03846             if (rsa_n_exp)
03847                if (rsa_n_exp) delete[] rsa_n_exp;
03848             if (rsa_d_exp)
03849                if (rsa_d_exp) delete[] rsa_d_exp;
03850 
03851          } else
03852             ::Info("TAuthenticate::DecodeRSAPublic","bad format for input string");
03853 #ifdef R__SSL
03854       } else {
03855          // try SSL
03856          keytype = 1;
03857 
03858          RSA *rsatmp;
03859 
03860          // Bio for exporting the pub key
03861          BIO *bpub = BIO_new(BIO_s_mem());
03862 
03863          // Write key from kbuf to BIO
03864          BIO_write(bpub,(void *)str,strlen(str));
03865 
03866          // Read pub key from BIO
03867          if (!(rsatmp = PEM_read_bio_RSAPublicKey(bpub, 0, 0, 0))) {
03868             if (gDebug > 0)
03869                ::Info("TAuthenticate::DecodeRSAPublic",
03870                         "unable to read pub key from bio");
03871          } else
03872             if (rsassl)
03873                *rsassl = (char *)rsatmp;
03874             else
03875                ::Info("TAuthenticate::DecodeRSAPublic",
03876                         "no space allocated for output variable");
03877          BIO_free(bpub);
03878       }
03879 #else
03880       } else {
03881          if (rsassl) { }   // To avoid compiler complains
03882          if (gDebug > 0)
03883             ::Info("TAuthenticate::DecodeRSAPublic","not compiled with SSL support:"
03884                    " you should not have got here!");
03885       }
03886 #endif
03887    }
03888 
03889    return keytype;
03890 }
03891 
03892 //______________________________________________________________________________
03893 Int_t TAuthenticate::SetRSAPublic(const char *rsaPubExport, Int_t klen)
03894 {
03895    // Store RSA public keys from export string rsaPubExport.
03896    // Returns type of stored key, or -1 is not recognized
03897 
03898    if (gDebug > 2)
03899       ::Info("TAuthenticate::SetRSAPublic",
03900              "enter: string length %ld bytes", (Long_t)strlen(rsaPubExport));
03901 
03902    Int_t rsakey = -1;
03903    if (!rsaPubExport)
03904       return rsakey;
03905 
03906    if (klen > 0) {
03907 
03908       // Skip spaces at beginning, if any
03909       int k0 = 0;
03910       while (rsaPubExport[k0] == 32) k0++;
03911       int k2 = klen - 1;
03912 
03913       // Parse rsaPubExport
03914       // Type 0 is in the form
03915       //
03916       //   #< gt 10 exa chars >#< gt 10 exa chars >#
03917       //
03918       rsakey = 1;
03919       if (rsaPubExport[k0] == '#' && rsaPubExport[k2] == '#') {
03920          char *p0 = (char *)&rsaPubExport[k0];
03921          char *p2 = (char *)&rsaPubExport[k2];
03922          char *p1 = strchr(p0+1,'#');
03923          if (p1 > p0 && p1 < p2) {
03924             Int_t l01 = (Int_t)(p1-p0)-1;
03925             Int_t l12 = (Int_t)(p2-p1)-1;
03926             if (l01 >= kPRIMELENGTH*2 && l12 >= kPRIMELENGTH*2) {
03927                // Require exadecimal chars in between
03928                char *c = p0+1;
03929                while (c < p1 && ((*c < 58 && *c > 47) || (*c < 91 && *c > 64)))
03930                   c++;
03931                if (c == p1) {
03932                   c++;
03933                   while (c < p2 && ((*c < 58 && *c > 47) || (*c < 91 && *c > 64)))
03934                      c++;
03935                   if (c == p2)
03936                      rsakey = 0;
03937                }
03938             }
03939          }
03940       }
03941       if (gDebug > 3)
03942          ::Info("TAuthenticate::SetRSAPublic"," Key type: %d",rsakey);
03943       if (rsakey == 0) {
03944 
03945          // Decode input string
03946          rsa_NUMBER rsa_n, rsa_d;
03947          rsakey = TAuthenticate::DecodeRSAPublic(rsaPubExport,rsa_n,rsa_d);
03948 
03949          // Save Public key
03950          TRSA_fun::RSA_assign()(&fgRSAPubKey.n, &rsa_n);
03951          TRSA_fun::RSA_assign()(&fgRSAPubKey.e, &rsa_d);
03952 
03953       } else {
03954          rsakey = 1;
03955 #ifdef R__SSL
03956          // Now set the key locally in BF form
03957          BF_set_key(&fgBFKey, klen, (const unsigned char *)rsaPubExport);
03958 #else
03959          if (gDebug > 0)
03960             ::Info("TAuthenticate::SetRSAPublic",
03961                    "not compiled with SSL support:"
03962                    " you should not have got here!");
03963 #endif
03964       }
03965    }
03966 
03967    return rsakey;
03968 }
03969 
03970 //______________________________________________________________________________
03971 Int_t TAuthenticate::SendRSAPublicKey(TSocket *socket, Int_t key)
03972 {
03973    // Receives server RSA Public key
03974    // Sends local RSA public key encoded
03975 
03976    // Receive server public key
03977    char serverPubKey[kMAXSECBUF];
03978    int kind, nr = 0;
03979    if ((nr = socket->Recv(serverPubKey, kMAXSECBUF, kind)) < 0)
03980       return nr;
03981    if (gDebug > 3)
03982       ::Info("TAuthenticate::SendRSAPublicKey",
03983              "received key from server %ld bytes", (Long_t)strlen(serverPubKey));
03984 
03985    // Decode it
03986    rsa_NUMBER rsa_n, rsa_d;
03987 #ifdef R__SSL
03988    char *tmprsa = 0;
03989    if (TAuthenticate::DecodeRSAPublic(serverPubKey,rsa_n,rsa_d,
03990                                       &tmprsa) != key) {
03991       if (tmprsa)
03992          RSA_free((RSA *)tmprsa);
03993       return -1;
03994    }
03995    RSA *RSASSLServer = (RSA *)tmprsa;
03996 #else
03997    if (TAuthenticate::DecodeRSAPublic(serverPubKey,rsa_n,rsa_d) != key)
03998       return -1;
03999 #endif
04000 
04001    // Send local public key, encodes
04002    char buftmp[kMAXSECBUF] = {0};
04003    char buflen[20] = {0};
04004    Int_t slen = fgRSAPubExport[key].len;
04005    Int_t ttmp = 0;
04006    if (key == 0) {
04007       strlcpy(buftmp,fgRSAPubExport[key].keys,slen+1);
04008       ttmp = TRSA_fun::RSA_encode()(buftmp, slen, rsa_n, rsa_d);
04009       snprintf(buflen, 20, "%d", ttmp);
04010    } else if (key == 1) {
04011 #ifdef R__SSL
04012       Int_t lcmax = RSA_size(RSASSLServer) - 11;
04013       Int_t kk = 0;
04014       Int_t ke = 0;
04015       Int_t ns = slen;
04016       while (ns > 0) {
04017          Int_t lc = (ns > lcmax) ? lcmax : ns ;
04018          if ((ttmp = RSA_public_encrypt(lc,
04019                                         (unsigned char *)&fgRSAPubExport[key].keys[kk],
04020                                         (unsigned char *)&buftmp[ke],
04021                                         RSASSLServer,RSA_PKCS1_PADDING)) < 0) {
04022             char cerr[120];
04023             ERR_error_string(ERR_get_error(), cerr);
04024             ::Info("TAuthenticate::SendRSAPublicKey","SSL: error: '%s' ",cerr);
04025          }
04026          kk += lc;
04027          ke += ttmp;
04028          ns -= lc;
04029       }
04030       ttmp = ke;
04031       snprintf(buflen, 20, "%d", ttmp);
04032 #else
04033       if (gDebug > 0)
04034          ::Info("TAuthenticate::SendRSAPublicKey","not compiled with SSL support:"
04035                 " you should not have got here!");
04036       return -1;
04037 #endif
04038    } else {
04039       if (gDebug > 0)
04040          ::Info("TAuthenticate::SendRSAPublicKey","unknown key type (%d)",key);
04041 #ifdef R__SSL
04042       if (RSASSLServer)
04043          RSA_free(RSASSLServer);
04044 #endif
04045       return -1;
04046    }
04047 
04048    // Send length first
04049    if ((nr = socket->Send(buflen, kROOTD_ENCRYPT)) < 0)
04050       return nr;
04051    // Send Key. second ...
04052    Int_t nsen = socket->SendRaw(buftmp, ttmp);
04053    if (gDebug > 3)
04054       ::Info("TAuthenticate::SendRSAPublicKey",
04055              "local: sent %d bytes (expected: %d)", nsen,ttmp);
04056 #ifdef R__SSL
04057    if (RSASSLServer)
04058       RSA_free(RSASSLServer);
04059 #endif
04060    return nsen;
04061 }
04062 
04063 //______________________________________________________________________________
04064 Int_t TAuthenticate::ReadRootAuthrc()
04065 {
04066    // Read authentication directives from $ROOTAUTHRC, $HOME/.rootauthrc or
04067    // <Root_etc_dir>/system.rootauthrc and create related THostAuth objects.
04068    // Files are read only if they changed since last reading
04069    // If 'proofconf' is defined, check also file proofconf for directives
04070 
04071    // rootauthrc family
04072    char *authrc = 0;
04073    if (gSystem->Getenv("ROOTAUTHRC") != 0) {
04074       authrc = StrDup(gSystem->Getenv("ROOTAUTHRC"));
04075    } else {
04076       if (fgReadHomeAuthrc)
04077          authrc = gSystem->ConcatFileName(gSystem->HomeDirectory(), ".rootauthrc");
04078    }
04079    if (authrc && gDebug > 2)
04080       ::Info("TAuthenticate::ReadRootAuthrc", "Checking file: %s", authrc);
04081    if (!authrc || gSystem->AccessPathName(authrc, kReadPermission)) {
04082       if (authrc && gDebug > 1)
04083          ::Info("TAuthenticate::ReadRootAuthrc",
04084                 "file %s cannot be read (errno: %d)", authrc, errno);
04085       delete [] authrc;
04086 #ifdef ROOTETCDIR
04087       authrc = gSystem->ConcatFileName(ROOTETCDIR,"system.rootauthrc");
04088 #else
04089       char etc[1024];
04090 #ifdef WIN32
04091       snprintf(etc, 1024, "%s\\etc", gRootDir);
04092 #else
04093       snprintf(etc, 1024, "%s/etc", gRootDir);
04094 #endif
04095       authrc = gSystem->ConcatFileName(etc,"system.rootauthrc");
04096 #endif
04097       if (gDebug > 2)
04098          ::Info("TAuthenticate::ReadRootAuthrc", "Checking system file:%s",authrc);
04099       if (gSystem->AccessPathName(authrc, kReadPermission)) {
04100          if (gDebug > 1)
04101             ::Info("TAuthenticate::ReadRootAuthrc",
04102                    "file %s cannot be read (errno: %d)", authrc, errno);
04103          delete [] authrc;
04104          return 0;
04105       }
04106    }
04107 
04108    // Check if file has changed since last read
04109    TString tRootAuthrc = authrc;
04110    if (tRootAuthrc == fgRootAuthrc) {
04111       struct stat si;
04112       stat(tRootAuthrc, &si);
04113       if ((UInt_t)si.st_mtime < fgLastAuthrc.Convert()) {
04114          if (gDebug > 1)
04115             ::Info("TAuthenticate::ReadRootAuthrc",
04116                    "file %s already read", authrc);
04117          delete [] authrc;
04118          return 0;
04119       }
04120    }
04121 
04122    // Save filename in static variable
04123    fgRootAuthrc = tRootAuthrc;
04124    fgLastAuthrc = TDatime();
04125 
04126    // THostAuth lists
04127    TList *authinfo = TAuthenticate::GetAuthInfo();
04128    TList *proofauthinfo = TAuthenticate::GetProofAuthInfo();
04129 
04130    // Expand File into temporary file name and open it
04131    int expand = 1;
04132    TString filetmp = "rootauthrc";
04133    FILE *ftmp = gSystem->TempFileName(filetmp);
04134    if (gDebug > 2)
04135       ::Info("TAuthenticate::ReadRootAuthrc", "got tmp file: %s open at 0x%lx",
04136              filetmp.Data(), (Long_t)ftmp);
04137    if (ftmp == 0)
04138       expand = 0;  // Problems opening temporary file: ignore 'include's ...
04139 
04140    FILE *fd = 0;
04141    // If the temporary file is open, copy everything to the new file ...
04142    if (expand == 1) {
04143       TAuthenticate::FileExpand(authrc, ftmp);
04144       fd = ftmp;
04145       rewind(fd);
04146    } else {
04147       // Open file
04148       fd = fopen(authrc, "r");
04149       if (fd == 0) {
04150          if (gDebug > 2)
04151             ::Info("TAuthenticate::ReadRootAuthrc",
04152                    "file %s cannot be open (errno: %d)", authrc, errno);
04153          delete [] authrc;
04154          return 0;
04155       }
04156    }
04157 
04158    // Now scan file for meaningful directives
04159    TList tmpAuthInfo;
04160    char line[kMAXPATHLEN];
04161    Bool_t cont = kFALSE;
04162    TString proofserv;
04163    while (fgets(line, sizeof(line), fd) != 0) {
04164 
04165       // Skip comment lines
04166       if (line[0] == '#')
04167          continue;
04168 
04169       // Get rid of end of line '\n', if there ...
04170       if (line[strlen(line) - 1] == '\n')
04171          line[strlen(line) - 1] = '\0';
04172 
04173       // Skip empty lines
04174       if (strlen(line) == 0)
04175          continue;
04176 
04177       // Now scan
04178       char *tmp = new char[strlen(line)+1];
04179       if (!tmp) {
04180          ::Error("TAuthenticate::ReadRootAuthrc",
04181                  "could not allocate temporary buffer");
04182          return 0;
04183       }
04184       strlcpy(tmp,line,strlen(line)+1);
04185       char *nxt = strtok(tmp," ");
04186 
04187       if (!strcmp(nxt, "proofserv") || cont) {
04188 
04189          // Building the list of data servers for proof (analyzed at the end)
04190          char *ph = 0;
04191          if (cont)
04192             ph = nxt;
04193          else
04194             ph = strtok(0," ");
04195          while (ph) {
04196             if (*ph != 92) {
04197                proofserv += TString((const char *)ph);
04198                proofserv += TString(" ");
04199                cont = kFALSE;
04200             } else {
04201                cont = kTRUE;
04202             }
04203             ph = strtok(0," ");
04204          }
04205 
04206       } else {
04207 
04208          TString hostsrv = nxt;
04209          TString host   = hostsrv;
04210          TString server = "";
04211          if (hostsrv.Contains(":")) {
04212             server = hostsrv;
04213             host.Remove(host.Index(":"));
04214             server.Remove(0,server.Index(":")+1);
04215          }
04216          Int_t srvtyp = -1;
04217          if (server.Length()) {
04218             if (server == "0" || server.BeginsWith("sock"))
04219                srvtyp = TSocket::kSOCKD;
04220             else if (server == "1" || server.BeginsWith("root"))
04221                srvtyp = TSocket::kROOTD;
04222             else if (server == "2" || server.BeginsWith("proof"))
04223                srvtyp = TSocket::kPROOFD;
04224          }
04225 
04226          // Line with host info directives
04227          TString user = "*";
04228 
04229          nxt = strtok(0," ");
04230          if (!strncmp(nxt,"user",4)) {
04231             nxt = strtok(0," ");
04232             if (strncmp(nxt,"list",4) && strncmp(nxt,"method",6)) {
04233                user = TString(nxt);
04234                nxt = strtok(0," ");
04235             }
04236          }
04237 
04238          // Get related THostAuth, if exists in the tmp list,
04239          TIter next(&tmpAuthInfo);
04240          THostAuth *ha;
04241          while ((ha = (THostAuth *)next())) {
04242             if (host == ha->GetHost() && user == ha->GetUser() &&
04243                 srvtyp == ha->GetServer())
04244                break;
04245          }
04246          if (!ha) {
04247             // Create a new one
04248             ha = new THostAuth(host,srvtyp,user);
04249             tmpAuthInfo.Add(ha);
04250          }
04251 
04252          if (!strncmp(nxt,"list",4)) {
04253             // list of methods for {host,usr}
04254             Int_t nm = 0, me[kMAXSEC] = {0};
04255             char *mth = strtok(0," ");
04256             while (mth) {
04257                Int_t met = -1;
04258                if (strlen(mth) > 1) {
04259                   // Method passed as string: translate it to number
04260                   met = GetAuthMethodIdx(mth);
04261                   if (met == -1 && gDebug > 2)
04262                      ::Info("TAuthenticate::ReadRootAuthrc",
04263                             "unrecognized method (%s): ", mth);
04264                } else {
04265                   met = atoi(mth);
04266                }
04267                if (met > -1 && met < kMAXSEC)
04268                   me[nm++] = met;
04269                mth = strtok(0," ");
04270             }
04271             if (nm)
04272                ha->ReOrder(nm,me);
04273 
04274          } else if (!strncmp(nxt,"method",6)) {
04275 
04276             // details for {host,usr,method}
04277             char *mth = strtok(0," ");
04278             Int_t met = -1;
04279             if (strlen(mth) > 1) {
04280                // Method passed as string: translate it to number
04281                met = GetAuthMethodIdx(mth);
04282                if (met == -1 && gDebug > 2)
04283                   ::Info("TAuthenticate::ReadRootAuthrc",
04284                          "unrecognized method (%s): ", mth);
04285             } else {
04286                met = atoi(mth);
04287             }
04288             if (met > -1 && met < kMAXSEC) {
04289                const char *det = 0;
04290                nxt = strtok(0," ");
04291                if (nxt) {
04292                   det = (const char *)strstr(line,nxt);
04293                }
04294                if (ha->HasMethod(met))
04295                   ha->SetDetails(met,det);
04296                else
04297                   ha->AddMethod(met,det);
04298             }
04299          }
04300       }
04301       if (tmp) delete [] tmp;
04302    }
04303    // Close file and remove it if temporary
04304    fclose(fd);
04305    if (expand == 1)
04306       gSystem->Unlink(filetmp);
04307    // Cleanup allocated memory
04308    delete [] authrc;
04309 
04310    // Update authinfo with new info found
04311    TAuthenticate::MergeHostAuthList(authinfo,&tmpAuthInfo);
04312 
04313    // Print those left, if requested ...
04314    if (gDebug > 2)
04315       TAuthenticate::Show();
04316 
04317    // Now create the list of THostAuth to be sent over to
04318    // the Master/Slaves, if requested ...
04319    TList tmpproofauthinfo;
04320    if (proofserv.Length() > 0) {
04321       char *tmps = new char[proofserv.Length()+1];
04322       strlcpy(tmps,proofserv.Data(),proofserv.Length()+1);
04323       char *nxt = strtok(tmps," ");
04324       while (nxt) {
04325          TString tmp((const char *)nxt);
04326          Int_t pdd = -1;
04327          // host
04328          TString host;
04329          if ((pdd = tmp.Index(":")) == -1) {
04330             host = tmp;
04331          } else {
04332             host = tmp;
04333             host.Resize(pdd);
04334             if (!host.Length())
04335                host = "*";
04336             tmp.Remove(0,pdd+1);
04337          }
04338          // user
04339          TString user;
04340          if ((pdd = tmp.Index(":")) == -1) {
04341             user = tmp;
04342          } else {
04343             user = tmp;
04344             user.Resize(pdd);
04345             if (!user.Length())
04346                user = "*";
04347             tmp.Remove(0,pdd+1);
04348          }
04349          // method(s)
04350          TString meth;
04351          Int_t nm = 0, me[kMAXSEC] = {0}, met = -1;
04352          while (tmp.Length() > 0) {
04353             meth = tmp;
04354             if ((pdd = tmp.Index(":")) > -1)
04355                meth.Resize(pdd);
04356             if (meth.Length() > 1) {
04357                // Method passed as string: translate it to number
04358                met = GetAuthMethodIdx(meth.Data());
04359                if (met == -1 && gDebug > 2)
04360                   ::Info("TAuthenticate::ReadRootAuthrc",
04361                          "unrecognized method (%s): ",meth.Data());
04362             } else if (meth.Length() == 1) {
04363                met = atoi(meth.Data());
04364                if (met > -1 && met < kMAXSEC)
04365                   me[nm++] = met;
04366             }
04367             if (pdd > -1)
04368                tmp.Remove(0,pdd+1);
04369             else
04370                tmp.Resize(0);
04371          }
04372 
04373          // Get related THostAuth, if exists, or create a new one
04374          THostAuth *ha = 0;
04375          THostAuth *hatmp = TAuthenticate::GetHostAuth(host,user);
04376          if (!hatmp) {
04377             ha = new THostAuth(host,user,nm,me,0);
04378          } else {
04379             // Create an empty THostAuth
04380             ha = new THostAuth(host,user);
04381             // Update with hatmp info
04382             ha->Update(hatmp);
04383             // ReOrder following new directives
04384             ha->ReOrder(nm,me);
04385          }
04386          // Add to the tmp list
04387          tmpproofauthinfo.Add(ha);
04388          // Go to next
04389          nxt = strtok(0," ");
04390       }
04391       delete [] tmps;
04392    }
04393 
04394    // Update proofauthinfo with new info found
04395    TAuthenticate::MergeHostAuthList(proofauthinfo,&tmpproofauthinfo,"P");
04396    // Print those, if requested ...
04397    if (gDebug > 2)
04398       TAuthenticate::Show("P");
04399 
04400    return authinfo->GetSize();
04401 }
04402 
04403 //______________________________________________________________________________
04404 Bool_t TAuthenticate::CheckProofAuth(Int_t cSec, TString &out)
04405 {
04406    // Check if the authentication method can be attempted for the client.
04407 
04408    Bool_t rc = kFALSE;
04409    const char sshid[3][20] = { "/.ssh/identity", "/.ssh/id_dsa", "/.ssh/id_rsa" };
04410    const char netrc[2][20] = { "/.netrc", "/.rootnetrc" };
04411    TString user;
04412 
04413    // Get user logon name
04414    UserGroup_t *pw = gSystem->GetUserInfo();
04415    if (pw) {
04416       user = TString(pw->fUser);
04417       delete pw;
04418    } else {
04419       ::Info("CheckProofAuth",
04420              "not properly logged on (getpwuid unable to find relevant info)!");
04421       out = "";
04422       return rc;
04423    }
04424 
04425    // UsrPwd
04426    if (cSec == (Int_t) TAuthenticate::kClear) {
04427       Int_t i = 0;
04428       for (; i < 2; i++) {
04429          TString infofile = TString(gSystem->HomeDirectory())+TString(netrc[i]);
04430          if (!gSystem->AccessPathName(infofile, kReadPermission))
04431             rc = kTRUE;
04432       }
04433       if (rc)
04434          out = Form("pt:0 ru:1 us:%s",user.Data());
04435    }
04436 
04437    // SRP
04438    if (cSec == (Int_t) TAuthenticate::kSRP) {
04439 #ifdef R__SRP
04440       out = Form("pt:0 ru:1 us:%s",user.Data());
04441       rc = kTRUE;
04442 #endif
04443    }
04444 
04445    // Kerberos
04446    if (cSec == (Int_t) TAuthenticate::kKrb5) {
04447 #ifdef R__KRB5
04448       out = Form("pt:0 ru:0 us:%s",user.Data());
04449       rc = kTRUE;
04450 #endif
04451    }
04452 
04453    // Globus
04454    if (cSec == (Int_t) TAuthenticate::kGlobus) {
04455 #ifdef R__GLBS
04456       TApplication *lApp = gROOT->GetApplication();
04457       if (lApp != 0 && lApp->Argc() > 9) {
04458          if (gROOT->IsProofServ()) {
04459             // Delegated Credentials
04460             Int_t ShmId = -1;
04461             if (gSystem->Getenv("ROOTSHMIDCRED"))
04462                ShmId = strtol(gSystem->Getenv("ROOTSHMIDCRED"),
04463                               (char **)0, 10);
04464             if (ShmId != -1) {
04465                struct shmid_ds shm_ds;
04466                if (shmctl(ShmId, IPC_STAT, &shm_ds) == 0)
04467                   rc = kTRUE;
04468             }
04469             if (rc) {
04470                // Build details .. CA dir
04471                TString Adir(gSystem->Getenv("X509_CERT_DIR"));
04472                // Usr Cert
04473                TString Ucer(gSystem->Getenv("X509_USER_CERT"));
04474                // Usr Key
04475                TString Ukey(gSystem->Getenv("X509_USER_KEY"));
04476                // Usr Dir
04477                TString Cdir = Ucer;
04478                Cdir.Resize(Cdir.Last('/')+1);
04479                // Create output
04480                out = Form("pt=0 ru:0 cd:%s cf:%s kf:%s ad:%s",
04481                           Cdir.Data(),Ucer.Data(),Ukey.Data(),Adir.Data());
04482             }
04483          }
04484       }
04485 #endif
04486    }
04487 
04488    // SSH
04489    if (cSec == (Int_t) TAuthenticate::kSSH) {
04490       Int_t i = 0;
04491       for (; i < 3; i++) {
04492          TString infofile = TString(gSystem->HomeDirectory())+TString(sshid[i]);
04493          if (!gSystem->AccessPathName(infofile,kReadPermission))
04494             rc = kTRUE;
04495       }
04496       if (rc)
04497          out = Form("pt:0 ru:1 us:%s",user.Data());
04498    }
04499 
04500    // Rfio
04501    if (cSec == (Int_t) TAuthenticate::kRfio) {
04502       out = Form("pt:0 ru:0 us:%s",user.Data());
04503       rc = kTRUE;
04504    }
04505 
04506    if (gDebug > 3) {
04507       if (strlen(out) > 0)
04508          ::Info("CheckProofAuth",
04509                 "meth: %d ... is available: details: %s", cSec, out.Data());
04510       else
04511          ::Info("CheckProofAuth",
04512                 "meth: %d ... is NOT available", cSec);
04513    }
04514 
04515    // return
04516    return rc;
04517 }
04518 
04519 //______________________________________________________________________________
04520 Int_t StdCheckSecCtx(const char *user, TRootSecContext *ctx)
04521 {
04522    // Standard version of CheckSecCtx to be passed to TAuthenticate::AuthExists
04523    // Check if User is matches the one in Ctx
04524    // Returns: 1 if ok, 0 if not
04525    // Deactivates Ctx is not valid
04526 
04527    Int_t rc = 0;
04528 
04529    if (ctx->IsActive()) {
04530       if (!strcmp(user,ctx->GetUser()) &&
04531           strncmp("AFS", ctx->GetID(), 3))
04532          rc = 1;
04533    }
04534    return rc;
04535 }
04536 
04537 //______________________________________________________________________________
04538 void TAuthenticate::MergeHostAuthList(TList *std, TList *nin, Option_t *opt)
04539 {
04540    // Tool for updating fgAuthInfo or fgProofAuthInfo
04541    // 'nin' contains list of last input information through (re)reading
04542    // of a rootauthrc-alike file. 'nin' info has priority.
04543    // 'std' is cleaned from inactive members.
04544    // 'nin' members used to update existing members in 'std' are
04545    // removed from 'nin', do that they do not leak
04546    // opt = "P" for proofauthinfo.
04547 
04548    // Remove inactive from the 'std'
04549    TIter nxstd(std);
04550    THostAuth *ha;
04551    while ((ha = (THostAuth *) nxstd())) {
04552       if (!ha->IsActive()) {
04553          std->Remove(ha);
04554          SafeDelete(ha);
04555       }
04556    }
04557 
04558    // Merge 'nin' info in 'std'
04559    TIter nxnew(nin);
04560    THostAuth *hanew;
04561    while ((hanew = (THostAuth *)nxnew())) {
04562       if (hanew->NumMethods()) {
04563          TString hostsrv(Form("%s:%d",hanew->GetHost(),hanew->GetServer()));
04564          THostAuth *hastd =
04565             TAuthenticate::HasHostAuth(hostsrv,hanew->GetUser(),opt);
04566          if (hastd) {
04567             // Update with new info
04568             hastd->Update(hanew);
04569             // Flag for removal
04570             hanew->DeActivate();
04571          } else {
04572             // Add new ThostAuth to std
04573             std->Add(hanew);
04574          }
04575       } else
04576          // Flag for removal empty objects
04577          hanew->DeActivate();
04578    }
04579 
04580    // Cleanup memory before quitting
04581    nxnew.Reset();
04582    while ((hanew = (THostAuth *)nxnew())) {
04583       if (!hanew->IsActive()) {
04584          nin->Remove(hanew);
04585          SafeDelete(hanew);
04586       }
04587    }
04588 
04589 }
04590 
04591 //______________________________________________________________________________
04592 void TAuthenticate::RemoveSecContext(TRootSecContext *ctx)
04593 {
04594    // Tool for removing SecContext ctx from THostAuth listed in
04595    // fgAuthInfo or fgProofAuthInfo
04596 
04597    THostAuth *ha = 0;
04598 
04599    // authinfo first
04600    TIter nxai(GetAuthInfo());
04601    while ((ha = (THostAuth *)nxai())) {
04602       TIter next(ha->Established());
04603       TRootSecContext *lctx = 0;
04604       while ((lctx = (TRootSecContext *) next())) {
04605          if (lctx == ctx) {
04606             ha->Established()->Remove(ctx);
04607             break;
04608          }
04609       }
04610    }
04611 
04612    // proofauthinfo second
04613    TIter nxpa(GetProofAuthInfo());
04614    while ((ha = (THostAuth *)nxpa())) {
04615       TIter next(ha->Established());
04616       TRootSecContext *lctx = 0;
04617       while ((lctx = (TRootSecContext *) next())) {
04618          if (lctx == ctx) {
04619             ha->Established()->Remove(ctx);
04620             break;
04621          }
04622       }
04623    }
04624 
04625 }
04626 
04627 //______________________________________________________________________________
04628 Int_t TAuthenticate::ProofAuthSetup()
04629 {
04630    // Authentication related stuff setup in TProofServ.
04631    // This is the place where the buffer send by the client / master is
04632    // decoded. It contains also password information, if the case requires.
04633    // Return 0 on success, -1 on failure.
04634 
04635    static Bool_t done = kFALSE;
04636 
04637    // Only once
04638    if (done)
04639       return 0;
04640    done = kTRUE;
04641 
04642    // Localise the buffer and decode it
04643    const char *p = gSystem->Getenv("ROOTPROOFAUTHSETUP");
04644    if (!p) {
04645       if (gDebug > 2)
04646          Info("ProofAuthSetup","Buffer not found: nothing to do");
04647       return 0;
04648    }
04649    TString mbuf = TBase64::Decode(p);
04650 
04651    // Create the message
04652    TMessage *mess = new TMessage((void*)mbuf.Data(), mbuf.Length()+sizeof(UInt_t));
04653 
04654    // Extract the information
04655    TString user = "";
04656    TString passwd = "";
04657    Bool_t  pwhash = kFALSE;
04658    Bool_t  srppwd = kFALSE;
04659    Int_t  rsakey = -1;
04660    *mess >> user >> passwd >> pwhash >> srppwd >> rsakey;
04661 
04662    // Set Globals for later use
04663    TAuthenticate::SetGlobalUser(user);
04664    TAuthenticate::SetGlobalPasswd(passwd);
04665    TAuthenticate::SetGlobalPwHash(pwhash);
04666    TAuthenticate::SetGlobalSRPPwd(srppwd);
04667    TAuthenticate::SetDefaultRSAKeyType(rsakey);
04668    const char *h = gSystem->Getenv("ROOTHOMEAUTHRC");
04669    if (h) {
04670       Bool_t rha = (Bool_t)(strtol(h, (char **)0, 10));
04671       TAuthenticate::SetReadHomeAuthrc(rha);
04672    }
04673 
04674    // Extract the list of THostAuth
04675    TList *pha = (TList *)mess->ReadObject(TList::Class());
04676    if (!pha) {
04677       if (gDebug > 0)
04678          Info("ProofAuthSetup","List of THostAuth not found");
04679       return 0;
04680    }
04681 
04682    Bool_t master = gROOT->IsProofServ();
04683    TIter next(pha);
04684    THostAuth *ha = 0;
04685    while ((ha = (THostAuth *)next())) {
04686 
04687       // Check if there is already one compatible
04688       Int_t kExact = 0;
04689       THostAuth *haex = 0;
04690       Bool_t fromProofAI = kFALSE;
04691       if (master) {
04692          // Look first in the proof list
04693          haex = TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"P",&kExact);
04694          // If nothing found, look also in the standard list
04695          if (!haex) {
04696             haex =
04697                TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"R",&kExact);
04698          } else
04699             fromProofAI = kTRUE;
04700       } else {
04701          // For slaves look first in the standard list only
04702          haex = TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"R",&kExact);
04703       }
04704 
04705       if (haex) {
04706          // If yes, action depends on whether it matches exactly or not
04707          if (kExact == 1) {
04708             // Update info in authinfo if Slave or in proofauthinfo
04709             // if Master and the entry was already in proofauthinfo
04710             if (!master || fromProofAI) {
04711                // update this existing one with the information found in
04712                // in the new one, if needed
04713                haex->Update(ha);
04714                // Delete temporary THostAuth
04715                SafeDelete(ha);
04716             } else
04717                // Master, entry not already in proofauthinfo,
04718                // Add it to the list
04719                TAuthenticate::GetProofAuthInfo()->Add(ha);
04720          } else {
04721             // update this new one with the information found in
04722             // in the existing one (if needed) and ...
04723             Int_t i = 0;
04724             for (; i < haex->NumMethods(); i++) {
04725                Int_t met = haex->GetMethod(i);
04726                if (!ha->HasMethod(met))
04727                   ha->AddMethod(met,haex->GetDetails(met));
04728             }
04729             if (master)
04730                // ... add the new one to the list
04731                TAuthenticate::GetProofAuthInfo()->Add(ha);
04732             else
04733                // We add this one to the standard list
04734                TAuthenticate::GetAuthInfo()->Add(ha);
04735          }
04736       } else {
04737          if (master)
04738             // We add this one to the list for forwarding
04739             TAuthenticate::GetProofAuthInfo()->Add(ha);
04740          else
04741             // We add this one to the standard list
04742             TAuthenticate::GetAuthInfo()->Add(ha);
04743       }
04744    }
04745 
04746    // We are done
04747    return 0;
04748 }
04749 
04750 //______________________________________________________________________________
04751 Int_t TAuthenticate::ProofAuthSetup(TSocket *sock, Bool_t client)
04752 {
04753    // Setup of authetication related stuff in PROOF run after a
04754    // successful authentication.
04755    // Return 0 on success, -1 on failure.
04756 
04757    // Fill some useful info
04758    TSecContext *sc    = sock->GetSecContext();
04759    TString user       = sc->GetUser();
04760    Int_t remoteOffSet = sc->GetOffSet();
04761 
04762    // send user name to remote host
04763    // for UsrPwd and SRP methods send also passwd, rsa encoded
04764    TMessage pubkey;
04765    TString passwd = "";
04766    Bool_t  pwhash = kFALSE;
04767    Bool_t  srppwd = kFALSE;
04768    Bool_t  sndsrp = kFALSE;
04769 
04770    Bool_t upwd = sc->IsA("UsrPwd");
04771    Bool_t srp = sc->IsA("SRP");
04772 
04773    TPwdCtx *pwdctx = 0;
04774    if (remoteOffSet > -1 && (upwd || srp))
04775       pwdctx = (TPwdCtx *)(sc->GetContext());
04776 
04777    if (client) {
04778       if ((gEnv->GetValue("Proofd.SendSRPPwd",0)) && (remoteOffSet > -1))
04779          sndsrp = kTRUE;
04780    } else {
04781       if (srp && pwdctx) {
04782          if (strcmp(pwdctx->GetPasswd(), "") && remoteOffSet > -1)
04783             sndsrp = kTRUE;
04784       }
04785    }
04786 
04787    if ((upwd && pwdctx) || (srp  && sndsrp)) {
04788       if (pwdctx) {
04789          passwd = pwdctx->GetPasswd();
04790          pwhash = pwdctx->IsPwHash();
04791       }
04792    }
04793 
04794    Int_t keytyp = ((TRootSecContext *)sc)->GetRSAKey();
04795 
04796    // Prepare buffer
04797    TMessage mess;
04798    mess << user << passwd << pwhash << srppwd << keytyp;
04799 
04800    // Add THostAuth info
04801    mess.WriteObject(TAuthenticate::GetProofAuthInfo());
04802 
04803    // Get buffer as a base 64 string
04804    char *mbuf = mess.Buffer();
04805    Int_t mlen = mess.Length();
04806    TString messb64 = TBase64::Encode(mbuf, mlen);
04807 
04808    if (gDebug > 2)
04809       ::Info("ProofAuthSetup","sending %d bytes", messb64.Length());
04810 
04811    // Send it over
04812    if (remoteOffSet > -1) {
04813       if (TAuthenticate::SecureSend(sock, 1, keytyp, messb64.Data()) == -1) {
04814          ::Error("ProofAuthSetup","problems secure-sending message buffer");
04815          return -1;
04816       }
04817    } else {
04818       // There is no encryption key: send it plain
04819       char buflen[20];
04820       snprintf(buflen,20, "%d", messb64.Length());
04821       if (sock->Send(buflen, kMESS_ANY) < 0) {
04822          ::Error("ProofAuthSetup","plain: problems sending message length");
04823          return -1;
04824       }
04825       if (sock->SendRaw(messb64.Data(), messb64.Length()) < 0) {
04826          ::Error("ProofAuthSetup","problems sending message buffer");
04827          return -1;
04828       }
04829    }
04830 
04831    // We are done
04832    return 0;
04833 }
04834 
04835 //______________________________________________________________________________
04836 Int_t TAuthenticate::GetClientProtocol()
04837 {
04838    // Static method returning supported client protocol.
04839 
04840    return TSocket::GetClientProtocol();
04841 }
04842 
04843 //
04844 // The code below is needed by TSlave and TProofServ for backward
04845 // compatibility.
04846 //
04847 
04848 //______________________________________________________________________________
04849 static Int_t SendHostAuth(TSocket *s)
04850 {
04851    // Sends the list of the relevant THostAuth objects to the master or
04852    // to the active slaves, typically data servers external to the proof
04853    // cluster. The list is of THostAuth to be sent is specified by
04854    // TAuthenticate::fgProofAuthInfo after directives found in the
04855    // .rootauthrc family files ('proofserv' key)
04856    // Returns -1 if a problem sending THostAuth has occured, -2 in case
04857    // of problems closing the transmission.
04858 
04859    Int_t retval = 0, ns = 0;
04860 
04861    if (!s) {
04862       Error("SendHostAuth","invalid input: socket undefined");
04863       return -1;
04864    }
04865 
04866 
04867    TIter next(TAuthenticate::GetProofAuthInfo());
04868    THostAuth *ha;
04869    while ((ha = (THostAuth *)next())) {
04870       TString buf;
04871       ha->AsString(buf);
04872       if((ns = s->Send(buf, kPROOF_HOSTAUTH)) < 1) {
04873          retval = -1;
04874          break;
04875       }
04876       if (gDebug > 2)
04877          Info("SendHostAuth","sent %d bytes (%s)",ns,buf.Data());
04878    }
04879 
04880    // End of transmission ...
04881    if ((ns = s->Send("END", kPROOF_HOSTAUTH)) < 1)
04882       retval = -2;
04883    if (gDebug > 2)
04884       Info("SendHostAuth","sent %d bytes for closing",ns);
04885 
04886    return retval;
04887 }
04888 
04889 //______________________________________________________________________________
04890 static Int_t RecvHostAuth(TSocket *s, Option_t *opt)
04891 {
04892    // Receive from client/master directives for authentications, create
04893    // related THostAuth and add them to the TAuthenticate::ProofAuthInfo
04894    // list. Opt = "M" or "m" if Master, "S" or "s" if Proof slave.
04895    // The 'proofconf' file is read only if Master
04896 
04897    if (!s) {
04898       Error("RecvHostAuth","invalid input: socket undefined");
04899       return -1;
04900    }
04901 
04902    // Check if Master
04903    Bool_t master = !strncasecmp(opt,"M",1) ? kTRUE : kFALSE;
04904 
04905    // First read directives from <rootauthrc>, <proofconf> and alike files
04906    TAuthenticate::ReadRootAuthrc();
04907 
04908    // Receive buffer
04909    Int_t kind;
04910    char buf[kMAXSECBUF];
04911    Int_t nr = s->Recv(buf, kMAXSECBUF, kind);
04912    if (nr < 0 || kind != kPROOF_HOSTAUTH) {
04913       Error("RecvHostAuth", "received: kind: %d (%d bytes)", kind, nr);
04914       return -1;
04915    }
04916    if (gDebug > 2)
04917       Info("RecvHostAuth","received %d bytes (%s)",nr,buf);
04918 
04919    while (strcmp(buf, "END")) {
04920       // Clean buffer
04921       Int_t nc = (nr >= kMAXSECBUF) ? kMAXSECBUF - 1 : nr ;
04922       buf[nc] = '\0';
04923 
04924       // Create THostAuth
04925       THostAuth *ha = new THostAuth((const char *)&buf);
04926 
04927       // Check if there is already one compatible
04928       Int_t kExact = 0;
04929       THostAuth *haex = 0;
04930       Bool_t fromProofAI = kFALSE;
04931       if (master) {
04932          // Look first in the proof list
04933          haex = TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"P",&kExact);
04934          // If nothing found, look also in the standard list
04935          if (!haex) {
04936             haex =
04937                TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"R",&kExact);
04938          } else
04939             fromProofAI = kTRUE;
04940       } else {
04941          // For slaves look first in the standard list only
04942          haex = TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"R",&kExact);
04943       }
04944 
04945       if (haex) {
04946          // If yes, action depends on whether it matches exactly or not
04947          if (kExact == 1) {
04948             // Update info in authinfo if Slave or in proofauthinfo
04949             // if master and the entry was already in proofauthinfo
04950             if (!master || fromProofAI) {
04951                // update this existing one with the information found in
04952                // in the new one, if needed
04953                haex->Update(ha);
04954                // Delete temporary THostAuth
04955                SafeDelete(ha);
04956             } else
04957                // master, entry not already in proofauthinfo,
04958                // Add it to the list
04959                TAuthenticate::GetProofAuthInfo()->Add(ha);
04960          } else {
04961             // update this new one with the information found in
04962             // in the existing one (if needed) and ...
04963             Int_t i = 0;
04964             for (; i < haex->NumMethods(); i++) {
04965                Int_t met = haex->GetMethod(i);
04966                if (!ha->HasMethod(met))
04967                   ha->AddMethod(met,haex->GetDetails(met));
04968             }
04969             if (master)
04970                // ... add the new one to the list
04971                TAuthenticate::GetProofAuthInfo()->Add(ha);
04972             else
04973                // We add this one to the standard list
04974                TAuthenticate::GetAuthInfo()->Add(ha);
04975          }
04976       } else {
04977          if (master)
04978             // We add this one to the list for forwarding
04979             TAuthenticate::GetProofAuthInfo()->Add(ha);
04980          else
04981             // We add this one to the standard list
04982             TAuthenticate::GetAuthInfo()->Add(ha);
04983       }
04984 
04985 
04986       // Get the next one
04987       nr = s->Recv(buf, kMAXSECBUF, kind);
04988       if (nr < 0 || kind != kPROOF_HOSTAUTH) {
04989          Info("RecvHostAuth","Error: received: kind: %d (%d bytes)", kind, nr);
04990          return -1;
04991       }
04992       if (gDebug > 2)
04993          Info("RecvHostAuth","received %d bytes (%s)",nr,buf);
04994    }
04995 
04996    return 0;
04997 }
04998 
04999 extern "C" {
05000 
05001 //______________________________________________________________________________
05002 Int_t OldSlaveAuthSetup(TSocket *sock,
05003                         Bool_t master, TString ord, TString conf)
05004 {
05005    // Setup of authetication in PROOF run after successful opening
05006    // of the socket. Provided for backward compatibility.
05007    // Return 0 on success, -1 on failure.
05008 
05009 
05010    // Fill some useful info
05011    TSecContext *sc    = sock->GetSecContext();
05012    TString user       = sc->GetUser();
05013    Int_t proofdProto  = sock->GetRemoteProtocol();
05014    Int_t remoteOffSet = sc->GetOffSet();
05015 
05016    // send user name to remote host
05017    // for UsrPwd and SRP methods send also passwd, rsa encoded
05018    TMessage pubkey;
05019    TString passwd = "";
05020    Bool_t  pwhash = kFALSE;
05021    Bool_t  srppwd = kFALSE;
05022    Bool_t  sndsrp = kFALSE;
05023 
05024    Bool_t upwd = sc->IsA("UsrPwd");
05025    Bool_t srp = sc->IsA("SRP");
05026 
05027    TPwdCtx *pwdctx = 0;
05028    if (remoteOffSet > -1 && (upwd || srp))
05029       pwdctx = (TPwdCtx *)(sc->GetContext());
05030 
05031    if (!master) {
05032       if ((gEnv->GetValue("Proofd.SendSRPPwd",0)) && (remoteOffSet > -1))
05033          sndsrp = kTRUE;
05034    } else {
05035       if (srp && pwdctx) {
05036          if (strcmp(pwdctx->GetPasswd(), "") && remoteOffSet > -1)
05037             sndsrp = kTRUE;
05038       }
05039    }
05040 
05041    if ((upwd && pwdctx) || (srp  && sndsrp)) {
05042 
05043       // Send offset to identify remotely the public part of RSA key
05044       if (sock->Send(remoteOffSet, kROOTD_RSAKEY) != 2*sizeof(Int_t)) {
05045          Error("OldAuthSetup", "failed to send offset in RSA key");
05046          return -1;
05047       }
05048 
05049       if (pwdctx) {
05050          passwd = pwdctx->GetPasswd();
05051          pwhash = pwdctx->IsPwHash();
05052       }
05053 
05054       Int_t keytyp = ((TRootSecContext *)sc)->GetRSAKey();
05055       if (TAuthenticate::SecureSend(sock, 1, keytyp, passwd.Data()) == -1) {
05056          if (remoteOffSet > -1)
05057             Warning("OldAuthSetup","problems secure-sending pass hash %s",
05058                     "- may result in failures");
05059          // If non RSA encoding available try passwd inversion
05060          if (upwd) {
05061             for (int i = 0; i < passwd.Length(); i++) {
05062                char inv = ~passwd(i);
05063                passwd.Replace(i, 1, inv);
05064             }
05065             TMessage mess;
05066             mess << passwd;
05067             if (sock->Send(mess) < 0) {
05068                Error("OldAuthSetup", "failed to send inverted password");
05069                return -1;
05070             }
05071          }
05072       }
05073 
05074    } else {
05075 
05076       // Send notification of no offset to be sent ...
05077       if (sock->Send(-2, kROOTD_RSAKEY) != 2*sizeof(Int_t)) {
05078          Error("OldAuthSetup", "failed to send no offset notification in RSA key");
05079          return -1;
05080       }
05081    }
05082 
05083    // Send ordinal (and config) info to slave (or master)
05084    TMessage mess;
05085    mess << user << pwhash << srppwd << ord << conf;
05086 
05087    if (sock->Send(mess) < 0) {
05088       Error("OldAuthSetup", "failed to send ordinal and config info");
05089       return -1;
05090    }
05091 
05092    if (proofdProto > 6) {
05093       // Now we send authentication details to access, e.g., data servers
05094       // not in the proof cluster and to be propagated to slaves.
05095       // This is triggered by the 'proofserv <dserv1> <dserv2> ...'
05096       // line in .rootauthrc
05097       if (SendHostAuth(sock) < 0) {
05098          Error("OldAuthSetup", "failed to send HostAuth info");
05099          return -1;
05100       }
05101    }
05102 
05103    // We are done
05104    return 0;
05105 }
05106 
05107 //______________________________________________________________________________
05108 Int_t OldProofServAuthSetup(TSocket *sock, Bool_t master, Int_t protocol,
05109                             TString &user, TString &ord, TString &conf)
05110 {
05111    // Authentication related setup in TProofServ run after successful
05112    // startup. Provided for backward compatibility.
05113    // Return 0 on success, -1 on failure.
05114 
05115    // First receive, decode and store the public part of RSA key
05116    Int_t retval, kind;
05117    if (sock->Recv(retval, kind) != 2*sizeof(Int_t)) {
05118       //other side has closed connection
05119       Info("OldProofServAuthSetup",
05120            "socket has been closed due to protocol mismatch - Exiting");
05121       return -1;
05122    }
05123 
05124    Int_t rsakey = 0;
05125    TString passwd;
05126    if (kind == kROOTD_RSAKEY) {
05127 
05128       if (retval > -1) {
05129          if (gSystem->Getenv("ROOTKEYFILE")) {
05130 
05131             TString keyfile = gSystem->Getenv("ROOTKEYFILE");
05132             keyfile += retval;
05133 
05134             FILE *fKey = 0;
05135             char pubkey[kMAXPATHLEN] = { 0 };
05136             if (!gSystem->AccessPathName(keyfile.Data(), kReadPermission)) {
05137                if ((fKey = fopen(keyfile.Data(), "r"))) {
05138                   Int_t klen = fread((void *)pubkey,1,sizeof(pubkey),fKey);
05139                   if (klen <= 0) {
05140                      Error("OldProofServAuthSetup",
05141                            "failed to read public key from '%s'", keyfile.Data());
05142                      fclose(fKey);
05143                      return -1;
05144                   }
05145                   pubkey[klen] = 0;
05146                   // Set RSA key
05147                   rsakey = TAuthenticate::SetRSAPublic(pubkey,klen);
05148                   fclose(fKey);
05149                } else {
05150                   Error("OldProofServAuthSetup", "failed to open '%s'", keyfile.Data());
05151                   return -1;
05152                }
05153             }
05154          }
05155 
05156          // Receive passwd
05157          char *pwd = 0;
05158          if (TAuthenticate::SecureRecv(sock, 2, rsakey, &pwd) < 0) {
05159             Error("OldProofServAuthSetup", "failed to receive password");
05160             return -1;
05161          }
05162          passwd = pwd;
05163          delete[] pwd;
05164 
05165       } else if (retval == -1) {
05166 
05167          // Receive inverted passwd
05168          TMessage *mess;
05169          if ((sock->Recv(mess) <= 0) || !mess) {
05170             Error("OldProofServAuthSetup", "failed to receive inverted password");
05171             return -1;
05172          }
05173          (*mess) >> passwd;
05174          delete mess;
05175 
05176          for (Int_t i = 0; i < passwd.Length(); i++) {
05177             char inv = ~passwd(i);
05178             passwd.Replace(i, 1, inv);
05179          }
05180 
05181       }
05182    }
05183 
05184    // Receive final information
05185    TMessage *mess;
05186    if ((sock->Recv(mess) <= 0) || !mess) {
05187       Error("OldProofServAuthSetup", "failed to receive ordinal and config info");
05188       return -1;
05189    }
05190 
05191    // Decode it
05192    Bool_t pwhash, srppwd;
05193    if (master) {
05194       if (protocol < 4) {
05195          (*mess) >> user >> pwhash >> srppwd >> conf;
05196          ord = "0";
05197       } else {
05198          (*mess) >> user >> pwhash >> srppwd >> ord >> conf;
05199       }
05200    } else {
05201       if (protocol < 4) {
05202          Int_t iord;
05203          (*mess) >> user >> pwhash >> srppwd >> iord;
05204          ord = "0.";
05205          ord += iord;
05206       } else {
05207          (*mess) >> user >> pwhash >> srppwd >> ord >> conf;
05208       }
05209    }
05210    delete mess;
05211 
05212    // Set Globals for later use
05213    TAuthenticate::SetGlobalUser(user);
05214    TAuthenticate::SetGlobalPasswd(passwd);
05215    TAuthenticate::SetGlobalPwHash(pwhash);
05216    TAuthenticate::SetGlobalSRPPwd(srppwd);
05217    TAuthenticate::SetDefaultRSAKeyType(rsakey);
05218    const char *h = gSystem->Getenv("ROOTHOMEAUTHRC");
05219    if (h) {
05220       Bool_t rha = (Bool_t)(strtol(h, (char **)0, 10));
05221       TAuthenticate::SetReadHomeAuthrc(rha);
05222    }
05223 
05224    // Read user or system authentication directives and
05225    // receive auth info transmitted from the client
05226    Int_t harc = master ? RecvHostAuth(sock, "M") : RecvHostAuth(sock, "S");
05227 
05228    if (harc < 0) {
05229       Error("OldProofServAuthSetup", "failed to receive HostAuth info");
05230       return -1;
05231    }
05232 
05233    // We are done
05234    return 0;
05235 }
05236 
05237 }  // extern "C"

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