diff --git a/README/ReleaseNotes/v640/index.md b/README/ReleaseNotes/v640/index.md index 12e79400493d6..1b0da1667bd6b 100644 --- a/README/ReleaseNotes/v640/index.md +++ b/README/ReleaseNotes/v640/index.md @@ -17,6 +17,7 @@ The following people have contributed to this new version: Olivier Couet, CERN/EP-SFT,\ Marta Czurylo, CERN/EP-SFT,\ Florine de Geus, CERN/EP-SFT and University of Twente,\ + Ned Ganchovski, Proektsoft EOOD,\ Andrei Gheata, CERN/EP-SFT,\ Jonas Hahnfeld, CERN/EP-SFT and Goethe University Frankfurt,\ Fernando Hueso Gonzalez, IFIC (CSIC-University of Valencia),\ @@ -29,11 +30,11 @@ The following people have contributed to this new version: Giacomo Parolini, CERN/EP-SFT,\ Danilo Piparo, CERN/EP-SFT,\ Jonas Rembser, CERN/EP-SFT,\ + Sebastian Alba Vives, Instituto Tecnologico de Costa Rica (TEC),\ Silia Taider, CERN/EP-SFT,\ Devajith Valaparambil Sreeramaswamy, CERN/EP-SFT,\ Vassil Vassilev, Princeton,\ Sandro Wenzel, CERN/EP-ALICE,\ - Ned Ganchovski, Proektsoft EOOD,\ ## Deprecations @@ -70,6 +71,7 @@ The following people have contributed to this new version: } ``` * The `compression_default` build option was removed. It was supposed to change the default compression algorithm, but didn't actually work with the default parameters of `TFile`. +* The `TNetFile` and `TNetFileStager` classes were removed: they depended on `rootd` removed in release 6.16.00. ## Build System diff --git a/config/mimes.unix.in b/config/mimes.unix.in index 0a13a0619f9ae..7e4c68221ed31 100644 --- a/config/mimes.unix.in +++ b/config/mimes.unix.in @@ -161,7 +161,7 @@ icon = rootdb_s.xpm rootdb_t.xpm action = THbookFile *ftmp = new THbookFile("%s") [root/tfile] -pattern = TFile TNetFile TWebFile +pattern = TFile TWebFile icon = rootdb_s.xpm rootdb_t.xpm action = ->Browse() diff --git a/config/mimes.win32.in b/config/mimes.win32.in index e4685a1250a19..7be5fc260bbf6 100644 --- a/config/mimes.win32.in +++ b/config/mimes.win32.in @@ -161,7 +161,7 @@ icon = rootdb_s.xpm rootdb_t.xpm action = THbookFile *ftmp = new THbookFile("%s") [root/tfile] -pattern = TFile TNetFile TWebFile +pattern = TFile TWebFile icon = rootdb_s.xpm rootdb_t.xpm action = ->Browse() diff --git a/config/rootrc.in b/config/rootrc.in index 265d80e5d4026..539ddc1762bd8 100644 --- a/config/rootrc.in +++ b/config/rootrc.in @@ -436,7 +436,7 @@ RSA.KeyType: 1 # UsrPwd: check of host equivalence via /etc/hosts.equiv or $HOME/.rhosts. #SrvAuth.CheckHostsEquivalence: 1 -# Force file opening via TNetFile (TNetXNGFile) if a hostname is specified +# Force file opening via TNetXNGFile if a hostname is specified # in the Url. # By default, for local files TFile::Open() invokes directly TFile #TFile.ForceRemote: yes diff --git a/etc/plugins/TFile/P120_TNetFile.C b/etc/plugins/TFile/P120_TNetFile.C deleted file mode 100644 index f7a2706078e4d..0000000000000 --- a/etc/plugins/TFile/P120_TNetFile.C +++ /dev/null @@ -1,17 +0,0 @@ -void P120_TNetFile() -{ - gPluginMgr->AddHandler("TFile", "^rootd:", "TNetFile", - "Net", "TNetFile(const char*,Option_t*,const char*,Int_t,Int_t)"); - gPluginMgr->AddHandler("TFile", "^rootup:", "TNetFile", - "Net", "TNetFile(const char*,Option_t*,const char*,Int_t,Int_t)"); - gPluginMgr->AddHandler("TFile", "^roots:", "TNetFile", - "Net", "TNetFile(const char*,Option_t*,const char*,Int_t,Int_t)"); - gPluginMgr->AddHandler("TFile", "^rootk:", "TNetFile", - "Net", "TNetFile(const char*,Option_t*,const char*,Int_t,Int_t)"); - gPluginMgr->AddHandler("TFile", "^rootg:", "TNetFile", - "Net", "TNetFile(const char*,Option_t*,const char*,Int_t,Int_t)"); - gPluginMgr->AddHandler("TFile", "^rooth:", "TNetFile", - "Net", "TNetFile(const char*,Option_t*,const char*,Int_t,Int_t)"); - gPluginMgr->AddHandler("TFile", "^rootug:", "TNetFile", - "Net", "TNetFile(const char*,Option_t*,const char*,Int_t,Int_t)"); -} diff --git a/etc/plugins/TFileStager/P020_TNetFileStager.C b/etc/plugins/TFileStager/P020_TNetFileStager.C deleted file mode 100644 index 2d467a1a9775b..0000000000000 --- a/etc/plugins/TFileStager/P020_TNetFileStager.C +++ /dev/null @@ -1,17 +0,0 @@ -void P020_TNetFileStager() -{ - gPluginMgr->AddHandler("TFileStager", "^rootd:", "TNetFileStager", - "Net", "TNetFileStager(const char *)"); - gPluginMgr->AddHandler("TFileStager", "^rootup:", "TNetFileStager", - "Net", "TNetFileStager(const char *)"); - gPluginMgr->AddHandler("TFileStager", "^roots:", "TNetFileStager", - "Net", "TNetFileStager(const char *)"); - gPluginMgr->AddHandler("TFileStager", "^rootk:", "TNetFileStager", - "Net", "TNetFileStager(const char *)"); - gPluginMgr->AddHandler("TFileStager", "^rootg:", "TNetFileStager", - "Net", "TNetFileStager(const char *)"); - gPluginMgr->AddHandler("TFileStager", "^rooth:", "TNetFileStager", - "Net", "TNetFileStager(const char *)"); - gPluginMgr->AddHandler("TFileStager", "^rootug:", "TNetFileStager", - "Net", "TNetFileStager(const char *)"); -} diff --git a/io/dcache/src/TDCacheFile.cxx b/io/dcache/src/TDCacheFile.cxx index 1515d150ddf02..7227e94f042a8 100644 --- a/io/dcache/src/TDCacheFile.cxx +++ b/io/dcache/src/TDCacheFile.cxx @@ -240,7 +240,7 @@ Bool_t TDCacheFile::ReadBuffer(char *buf, Long64_t pos, Int_t len) /// Read the nbuf blocks described in arrays pos and len, /// where pos[i] is the seek position of block i of length len[i]. /// Note that for nbuf=1, this call is equivalent to TFile::ReafBuffer. -/// This function is overloaded by TNetFile, TWebFile, etc. +/// This function is overloaded by TWebFile etc. /// Returns kTRUE in case of failure. Bool_t TDCacheFile::ReadBuffers(char *buf, Long64_t *pos, Int_t *len, Int_t nbuf) diff --git a/io/io/src/TFile.cxx b/io/io/src/TFile.cxx index 459919ca42541..8b3eea73a8f56 100644 --- a/io/io/src/TFile.cxx +++ b/io/io/src/TFile.cxx @@ -1868,7 +1868,7 @@ Bool_t TFile::ReadBuffer(char *buf, Int_t len) /// /// The value pos[i] is the seek position of block i of length len[i]. /// Note that for nbuf=1, this call is equivalent to TFile::ReafBuffer. -/// This function is overloaded by TNetFile, TWebFile, etc. +/// This function is overloaded by TWebFile etc. /// Returns kTRUE in case of failure. Bool_t TFile::ReadBuffers(char *buf, Long64_t *pos, Int_t *len, Int_t nbuf) @@ -2256,7 +2256,7 @@ Int_t TFile::ReOpen(Option_t *mode) } // open in READ mode - fOption = opt; // set fOption before SysOpen() for TNetFile + fOption = opt; // was setting fOption before SysOpen() for the old TNetFile #ifndef WIN32 fD = SysOpen(fRealName, O_RDONLY, 0666); #else @@ -2278,7 +2278,7 @@ Int_t TFile::ReOpen(Option_t *mode) } // open in UPDATE mode - fOption = opt; // set fOption before SysOpen() for TNetFile + fOption = opt; // was setting fOption before SysOpen() for the old TNetFile #ifndef WIN32 fD = SysOpen(fRealName, O_RDWR | O_CREAT, 0666); #else @@ -3751,24 +3751,19 @@ TFile *TFile::OpenFromCache(const char *name, Option_t *, const char *ftitle, /// Create / open a file /// /// The type of the file can be either a -/// TFile, TNetFile, TWebFile or any TFile derived class for which an +/// TFile, TWebFile or any TFile derived class for which an /// plugin library handler has been registered with the plugin manager /// (for the plugin manager see the TPluginManager class). The returned /// type of TFile depends on the file name specified by 'url'. /// If 'url' is a '|'-separated list of file URLs, the 'URLs' are tried /// sequentially in the specified order until a successful open. -/// If the file starts with "root:", "roots:" or "rootk:" a TNetFile object +/// If the file starts with "root:" a TNetXNGFile object /// will be returned, with "http:" a TWebFile, with "file:" a local TFile, /// etc. (see the list of TFile plugin handlers in $ROOTSYS/etc/system.rootrc /// for regular expressions that will be checked) and as last a local file will /// be tried. -/// Before opening a file via TNetFile a check is made to see if the URL -/// specifies a local file. If that is the case the file will be opened -/// via a normal TFile. To force the opening of a local file via a -/// TNetFile use either TNetFile directly or specify as host "localhost". -/// The netopt argument is only used by TNetFile. For the meaning of the -/// options and other arguments see the constructors of the individual -/// file classes. In case of error, it returns a nullptr. +/// For the meaning of the options and other arguments see the constructors +/// of the individual file classes. In case of error, it returns a nullptr. /// /// For TFile implementations supporting asynchronous file open, see /// TFile::AsyncOpen(...), it is possible to request a timeout with the @@ -3984,11 +3979,7 @@ TFile *TFile::Open(const char *url, Option_t *options, const char *ftitle, if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name.Data()))) { if (h->LoadPlugin() == -1) return nullptr; - TClass *cl = TClass::GetClass(h->GetClass()); - if (cl && cl->InheritsFrom("TNetFile")) - f = (TFile*) h->ExecPlugin(5, name.Data(), option, ftitle, compress, netopt); - else - f = (TFile*) h->ExecPlugin(4, name.Data(), option, ftitle, compress); + f = (TFile*) h->ExecPlugin(4, name.Data(), option, ftitle, compress); } else { // Just try to open it locally but via TFile::Open, so that we pick-up the correct // plug-in in the case file name contains information about a special backend (e.g.) diff --git a/io/io/src/TFileCacheRead.cxx b/io/io/src/TFileCacheRead.cxx index 351adbf2b7958..ef7889e235d1c 100644 --- a/io/io/src/TFileCacheRead.cxx +++ b/io/io/src/TFileCacheRead.cxx @@ -19,7 +19,7 @@ no operating system caching support (like the buffer cache for local disk I/O). The cache makes sure that every I/O is done with a (large) fixed length buffer thereby avoiding many small I/O's. - Currently the read cache system is used by the classes TNetFile, + Currently the read cache system is used by the classes TNetXNGFile and TWebFile (via TFile::ReadBuffers()). When processing TTree, TChain, a specialized class TTreeCache that derives from this class is automatically created. diff --git a/io/io/src/TFileCacheWrite.cxx b/io/io/src/TFileCacheWrite.cxx index 5aadb50ce8791..eccf10260740b 100644 --- a/io/io/src/TFileCacheWrite.cxx +++ b/io/io/src/TFileCacheWrite.cxx @@ -18,7 +18,7 @@ A caching system to speed up network I/O, i.e. when there is no operating system caching support (like the buffer cache for local disk I/O). The cache makes sure that every I/O is done with a (large) fixed length buffer thereby avoiding many small I/O's. -Currently the write cache system is used by the classes TNetFile, +Currently the write cache system is used by the classes TNetXNGFile and TWebFile (via TFile::WriteBuffers()). The write cache is automatically created when writing a remote file diff --git a/net/CMakeLists.txt b/net/CMakeLists.txt index af04402cfd8f1..2fe7e8b7d0860 100644 --- a/net/CMakeLists.txt +++ b/net/CMakeLists.txt @@ -7,10 +7,6 @@ add_subdirectory(net) add_subdirectory(auth) -if(NOT WIN32 AND ssl) - add_subdirectory(rpdutils) -endif() - if(davix) add_subdirectory(davix) endif() diff --git a/net/auth/src/TAuthenticate.cxx b/net/auth/src/TAuthenticate.cxx index 565acdad724bf..3747eaec880a7 100644 --- a/net/auth/src/TAuthenticate.cxx +++ b/net/auth/src/TAuthenticate.cxx @@ -13,7 +13,7 @@ // // // TAuthenticate // // // -// An authentication module for ROOT based network services, like rootd // // +// An authentication module for ROOT based network services, like rootd // // // ////////////////////////////////////////////////////////////////////////// @@ -24,7 +24,6 @@ #include "THostAuth.h" #include "TRootSecContext.h" #include "TPluginManager.h" -#include "TNetFile.h" #include "TPSocket.h" #include "TMessage.h" #include "TSystem.h" diff --git a/net/net/CMakeLists.txt b/net/net/CMakeLists.txt index ff871b1934bf9..b45189f1f973b 100644 --- a/net/net/CMakeLists.txt +++ b/net/net/CMakeLists.txt @@ -46,8 +46,6 @@ ROOT_STANDARD_LIBRARY_PACKAGE(Net TGridResult.h TMessage.h TMonitor.h - TNetFile.h - TNetFileStager.h TParallelMergingFile.h TPServerSocket.h TPSocket.h @@ -78,8 +76,6 @@ ROOT_STANDARD_LIBRARY_PACKAGE(Net src/TGridResult.cxx src/TMessage.cxx src/TMonitor.cxx - src/TNetFile.cxx - src/TNetFileStager.cxx src/TParallelMergingFile.cxx src/TPServerSocket.cxx src/TPSocket.cxx diff --git a/net/net/inc/LinkDef.h b/net/net/inc/LinkDef.h index d3e575916719a..727a505972c1a 100644 --- a/net/net/inc/LinkDef.h +++ b/net/net/inc/LinkDef.h @@ -26,8 +26,6 @@ #pragma link C++ class TPSocket; #pragma link C++ class TMessage; #pragma link C++ class TMonitor; -#pragma link C++ class TNetFile; -#pragma link C++ class TNetFileStager; #pragma link C++ class TNetSystem; #pragma link C++ class TWebFile; #pragma link C++ class TWebSystem; diff --git a/net/net/inc/TNetFile.h b/net/net/inc/TNetFile.h deleted file mode 100644 index f21fb07f48107..0000000000000 --- a/net/net/inc/TNetFile.h +++ /dev/null @@ -1,125 +0,0 @@ -// @(#)root/net:$Id$ -// Author: Fons Rademakers 14/08/97 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -#ifndef ROOT_TNetFile -#define ROOT_TNetFile - - -////////////////////////////////////////////////////////////////////////// -// // -// TNetFile // -// // -// A TNetFile is like a normal TFile except that it reads and writes // -// its data via a rootd server. // -// // -////////////////////////////////////////////////////////////////////////// - -#include "TFile.h" -#include "TUrl.h" -#include "TFTP.h" -#include "TSystem.h" -#include "MessageTypes.h" - -class TSocket; - - -class TNetFile : public TFile { - -protected: - TUrl fEndpointUrl; //URL of realfile (after possible redirection) - TString fUser; //remote user name - TSocket *fSocket; //connection to rootd server - Int_t fProtocol; //rootd protocol level - Int_t fErrorCode; //error code returned by rootd (matching gRootdErrStr) - Int_t fNetopt; //initial network options (used for ReOpen()) - - TNetFile(const TNetFile&); // NetFile cannot be copied - TNetFile& operator=(const TNetFile&); // NetFile cannot be copied - - TNetFile(const char *url, const char *ftitle, Int_t comp, Bool_t); - virtual void ConnectServer(Int_t *stat, EMessageTypes *kind, Int_t netopt, - Int_t tcpwindowsize, Bool_t forceOpen, - Bool_t forceRead); - virtual void Create(const char *url, Option_t *option, Int_t netopt); - virtual void Create(TSocket *s, Option_t *option, Int_t netopt); - void Init(Bool_t create) override; - void Print(Option_t *option) const override; - void PrintError(const char *where, Int_t err); - Int_t Recv(Int_t &status, EMessageTypes &kind); - Int_t SysOpen(const char *pathname, Int_t flags, UInt_t mode) override; - Int_t SysClose(Int_t fd) override; - Int_t SysStat(Int_t fd, Long_t *id, Long64_t *size, Long_t *flags, Long_t *modtime) override; - -public: - TNetFile(const char *url, Option_t *option = "", const char *ftitle = "", - Int_t compress = ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt = 0); - TNetFile() : fEndpointUrl(), fUser(), fSocket(nullptr), fProtocol(0), fErrorCode(0), fNetopt(0) { } - virtual ~TNetFile(); - - void Close(Option_t *option="") override; // *MENU* - void Flush() override; - Int_t GetErrorCode() const { return fErrorCode; } - Bool_t IsOpen() const override; - Bool_t Matches(const char *url) override; - Int_t ReOpen(Option_t *mode) override; - Bool_t ReadBuffer(char *buf, Int_t len) override; - Bool_t ReadBuffer(char *buf, Long64_t pos, Int_t len) override; - Bool_t ReadBuffers(char *buf, Long64_t *pos, Int_t *len, Int_t nbuf) override; - Bool_t WriteBuffer(const char *buf, Int_t len) override; - void Seek(Long64_t offset, ERelativeTo pos = kBeg) override; - - const TUrl *GetEndpointUrl() const override { return &fEndpointUrl; } - - ClassDefOverride(TNetFile,1) //A ROOT file that reads/writes via a rootd server -}; - - -class TNetSystem : public TSystem { - -private: - Bool_t fDir; // true if a directory is open remotely - void *fDirp; // directory handler - TFTP *fFTP; // Connection to rootd - TString fHost; // Remote host - Bool_t fFTPOwner; // True if owner of the FTP instance - TString fUser; // Remote user - Int_t fPort; // Remote port - - TNetSystem(const TNetSystem&) = delete; - TNetSystem& operator=(const TNetSystem&) = delete; - - void *GetDirPtr() const override { return fDirp; } - -protected: - Bool_t fIsLocal; // TRUE if the path points to this host - TString fLocalPrefix; // if fIsLocal, prefix to be prepend locally - - void Create(const char *url, TSocket *sock = nullptr); - void InitRemoteEntity(const char *url); - -public: - TNetSystem(Bool_t ftpowner = kTRUE); - TNetSystem(const char *url, Bool_t ftpowner = kTRUE); - virtual ~TNetSystem(); - - Bool_t ConsistentWith(const char *path, void *dirptr) override; - Int_t MakeDirectory(const char *name) override; - void *OpenDirectory(const char *name) override; - void FreeDirectory(void *dirp = nullptr) override; - const char *GetDirEntry(void *dirp = nullptr) override; - Int_t GetPathInfo(const char *path, FileStat_t &buf) override; - Bool_t AccessPathName(const char *path, EAccessMode mode) override; - int Unlink(const char *path) override; - - ClassDefOverride(TNetSystem,0) // Directory handler for NetSystem -}; - -#endif diff --git a/net/net/inc/TNetFileStager.h b/net/net/inc/TNetFileStager.h deleted file mode 100644 index 5f73f67a96765..0000000000000 --- a/net/net/inc/TNetFileStager.h +++ /dev/null @@ -1,51 +0,0 @@ -// @(#)root/netx:$Id$ -// Author: G. Ganis Feb 2011 - -/************************************************************************* - * Copyright (C) 1995-2002, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -#ifndef ROOT_TNetFileStager -#define ROOT_TNetFileStager - -////////////////////////////////////////////////////////////////////////// -// // -// TNetFileStager // -// // -// TFileStager implementation for a 'rootd' backend. // -// // -////////////////////////////////////////////////////////////////////////// - -#include "TFileStager.h" - -class TCollection; -class TNetSystem; - -class TNetFileStager : public TFileStager { - -private: - TString fPrefix; // prefix to prepend to requests - TNetSystem *fSystem; // instance of the admin interface - - static void GetPrefix(const char *url, TString &pfx); - -public: - TNetFileStager(const char *stager = ""); - virtual ~TNetFileStager(); - - Bool_t IsStaged(const char *path) override; - Int_t Locate(const char *path, TString &endpath) override; - Bool_t Matches(const char *s) override; - - Bool_t IsValid() const override { return fSystem ? kTRUE : kFALSE; } - - void Print(Option_t *option = "") const override; - - ClassDefOverride(TNetFileStager,0) // Implementation for a 'rootd' backend -}; - -#endif diff --git a/net/net/src/TNetFile.cxx b/net/net/src/TNetFile.cxx deleted file mode 100644 index 5ce7bbd0d77f7..0000000000000 --- a/net/net/src/TNetFile.cxx +++ /dev/null @@ -1,1162 +0,0 @@ -// @(#)root/net:$Id$ -// Author: Fons Rademakers 14/08/97 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -/** -\file TNetFile.cxx -\class TNetFile -\ingroup IO - -A TNetFile is like a normal TFile except that it reads and writes -its data via a rootd server (for more on the rootd daemon see the -source files in `root/rootd/src/`). TNetFile file names are in -standard URL format with protocol "root" or "roots". The following -are valid TNetFile URL's: -- `root://hpbrun.cern.ch/root/hsimple.root` -- `root://pcna49a:5151/~na49/data/run821.root` -- `root://pcna49d.cern.ch:5050//v1/data/run810.root` - -The only difference with the well known httpd URL's is that the root -of the remote file tree is the user's home directory. Therefore an -absolute pathname requires a // after the host or port specifier -(see last example). Further the expansion of the standard shell -characters, like ~, $, .., are handled as expected. -TNetFile (actually TUrl) uses 1094 as default port for rootd. - -Connecting to a rootd requires the remote user id and password. -TNetFile allows three ways for you to provide your login: - Setting it globally via the static functions: -1. TAuthenticate::SetGlobalUser() and TAuthenticate::SetGlobalPasswd() -2. Getting it from the `~/.netrc` file (same file as used by ftp) -3. Command line prompt -The different methods will be tried in the order given above. -On machines with AFS rootd will authenticate using AFS (if it was -compiled with AFS support). - -If the protocol is specified as "rootk" kerberos5 will be used for -authentication. - -The rootd daemon lives in the directory `$ROOTSYS/bin`. It can be -started either via inetd or by hand from the command line (no need -to be super user). -**/ - -#include - -#include "Bytes.h" -#include "NetErrors.h" -#include "TApplication.h" -#include "TEnv.h" -#include "TNetFile.h" -#include "TPSocket.h" -#include "TROOT.h" -#include "TSysEvtHandler.h" -#include "TSystem.h" -#include "TTimeStamp.h" -#include "TVirtualPerfStats.h" - -// fgClientProtocol is now in TAuthenticate - - -//////////////////////////////////////////////////////////////////////////////// -/// Create a TNetFile object. This is actually done inside Create(), so -/// for a description of the options and other arguments see Create(). -/// Normally a TNetFile is created via TFile::Open(). - -TNetFile::TNetFile(const char *url, Option_t *option, const char *ftitle, Int_t compress, Int_t netopt) - : TFile(url, strstr(option, "_WITHOUT_GLOBALREGISTRATION") != nullptr ? "NET_WITHOUT_GLOBALREGISTRATION" : "NET", - ftitle, compress), - fEndpointUrl(url) -{ - fSocket = 0; - Create(url, option, netopt); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Create a TNetFile object. To be used by derived classes, that need -/// to initialize the TFile base class but not open a connection at this -/// moment. - -TNetFile::TNetFile(const char *url, const char *ftitle, Int_t compress, Bool_t) - : TFile(url, "NET", ftitle, compress), fEndpointUrl(url) -{ - fSocket = 0; - fProtocol = 0; - fErrorCode = 0; - fNetopt = 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// TNetFile dtor. Send close message and close socket. - -TNetFile::~TNetFile() -{ - Close(); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Open a remote file. Requires fOption to be set correctly. - -Int_t TNetFile::SysOpen(const char * /*file*/, Int_t /*flags*/, UInt_t /*mode*/) -{ - if (!fSocket) { - - Create(fUrl.GetUrl(), fOption, fNetopt); - if (!fSocket) return -1; - - } else { - - if (fProtocol > 15) { - fSocket->Send(Form("%s %s", fUrl.GetFile(), ToLower(fOption).Data()), - kROOTD_OPEN); - } else { - // Old daemon versions expect an additional slash at beginning - fSocket->Send(Form("/%s %s", fUrl.GetFile(), ToLower(fOption).Data()), - kROOTD_OPEN); - } - - EMessageTypes kind; - int stat; - Recv(stat, kind); - - if (kind == kROOTD_ERR) { - PrintError("SysOpen", stat); - return -1; - } - } - - // This means ok for net files - return -2; // set as fD in ReOpen -} - -//////////////////////////////////////////////////////////////////////////////// -/// Close currently open file. - -Int_t TNetFile::SysClose(Int_t /*fd*/) -{ - if (fSocket) - fSocket->Send(kROOTD_CLOSE); - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Return file stat information. The interface and return value is -/// identical to TSystem::GetPathInfo(). - -Int_t TNetFile::SysStat(Int_t, Long_t *id, Long64_t *size, Long_t *flags, Long_t *modtime) -{ - if (fProtocol < 3) return 1; - - if (!fSocket) return 1; - - fSocket->Send(kROOTD_FSTAT); - - char msg[1024]; - Int_t kind; - fSocket->Recv(msg, sizeof(msg), kind); - - Int_t mode, uid, gid, islink; - Long_t dev, ino; - - if (fProtocol > 12) { -#ifdef R__WIN32 - sscanf(msg, "%ld %ld %d %d %d %I64d %ld %d", &dev, &ino, &mode, - &uid, &gid, size, modtime, &islink); -#else - sscanf(msg, "%ld %ld %d %d %d %lld %ld %d", &dev, &ino, &mode, - &uid, &gid, size, modtime, &islink); -#endif - if (dev == -1) - return 1; - if (id) - *id = (dev << 24) + ino; - if (flags) { - *flags = 0; - if (mode & (kS_IXUSR|kS_IXGRP|kS_IXOTH)) - *flags |= 1; - if (R_ISDIR(mode)) - *flags |= 2; - if (!R_ISREG(mode) && !R_ISDIR(mode)) - *flags |= 4; - } - } else { -#ifdef R__WIN32 - sscanf(msg, "%ld %I64d %ld %ld", id, size, flags, modtime); -#else - sscanf(msg, "%ld %lld %ld %ld", id, size, flags, modtime); -#endif - if (*id == -1) - return 1; - } - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Close remote file. - -void TNetFile::Close(Option_t *opt) -{ - if (!fSocket) return; - - TFile::Close(opt); - - if (fProtocol > 6) - fSocket->Send(kROOTD_BYE); - - SafeDelete(fSocket); - - fD = -1; // so TFile::IsOpen() returns false when in TFile::~TFile -} - -//////////////////////////////////////////////////////////////////////////////// -/// Flush file to disk. - -void TNetFile::Flush() -{ - FlushWriteCache(); - - if (fSocket && fWritable) - fSocket->Send(kROOTD_FLUSH); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Initialize a TNetFile object. - -void TNetFile::Init(Bool_t create) -{ - Seek(0); - - TFile::Init(create); - fD = -2; // so TFile::IsOpen() returns true when in TFile::~TFile -} - -//////////////////////////////////////////////////////////////////////////////// -/// Retruns kTRUE if file is open, kFALSE otherwise. - -Bool_t TNetFile::IsOpen() const -{ - return fSocket == 0 ? kFALSE : kTRUE; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Print some info about the net file. - -void TNetFile::Print(Option_t *) const -{ - const char *fname = fUrl.GetFile(); - Printf("URL: %s", ((TUrl*)&fUrl)->GetUrl()); - Printf("Remote file: %s", &fname[1]); - Printf("Remote user: %s", fUser.Data()); - Printf("Title: %s", fTitle.Data()); - Printf("Option: %s", fOption.Data()); - Printf("Bytes written: %lld", fBytesWrite); - Printf("Bytes read: %lld", fBytesRead); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Print error string depending on error code. - -void TNetFile::PrintError(const char *where, Int_t err) -{ - fErrorCode = err; - Error(where, "%s", gRootdErrStr[err]); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Reopen a file with a different access mode, like from READ to -/// UPDATE or from NEW, CREATE, RECREATE, UPDATE to READ. Thus the -/// mode argument can be either "READ" or "UPDATE". The method returns -/// 0 in case the mode was successfully modified, 1 in case the mode -/// did not change (was already as requested or wrong input arguments) -/// and -1 in case of failure, in which case the file cannot be used -/// anymore. - -Int_t TNetFile::ReOpen(Option_t *mode) -{ - if (fProtocol < 7) { - Error("ReOpen", "operation not supported by remote rootd (protocol = %d)", - fProtocol); - return 1; - } - - return TFile::ReOpen(mode); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Read specified byte range from remote file via rootd daemon. -/// Returns kTRUE in case of error. - -Bool_t TNetFile::ReadBuffer(char *buf, Int_t len) -{ - if (!fSocket) return kTRUE; - if (len == 0) - return kFALSE; - - Bool_t result = kFALSE; - - Int_t st; - if ((st = ReadBufferViaCache(buf, len))) { - if (st == 2) - return kTRUE; - return kFALSE; - } - - if (gApplication && gApplication->GetSignalHandler()) - gApplication->GetSignalHandler()->Delay(); - - Double_t start = 0; - if (gPerfStats) start = TTimeStamp(); - - if (fSocket->Send(Form("%lld %d", fOffset, len), kROOTD_GET) < 0) { - Error("ReadBuffer", "error sending kROOTD_GET command"); - result = kTRUE; - goto end; - } - - Int_t stat, n; - EMessageTypes kind; - - fErrorCode = -1; - if (Recv(stat, kind) < 0 || kind == kROOTD_ERR) { - PrintError("ReadBuffer", stat); - result = kTRUE; - goto end; - } - - while ((n = fSocket->RecvRaw(buf, len)) < 0 && TSystem::GetErrno() == EINTR) - TSystem::ResetErrno(); - - if (n != len) { - Error("ReadBuffer", "error receiving buffer of length %d, got %d", len, n); - result = kTRUE; - goto end; - } - - fOffset += len; - - fBytesRead += len; - fReadCalls++; -#ifdef R__WIN32 - SetFileBytesRead(GetFileBytesRead() + len); - SetFileReadCalls(GetFileReadCalls() + 1); -#else - fgBytesRead += len; - fgReadCalls++; -#endif - -end: - - if (gPerfStats) - gPerfStats->FileReadEvent(this, len, start); - - if (gApplication && gApplication->GetSignalHandler()) - gApplication->GetSignalHandler()->HandleDelayedSignal(); - - return result; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Read specified byte range from remote file via rootd daemon. -/// Returns kTRUE in case of error. - -Bool_t TNetFile::ReadBuffer(char *buf, Long64_t pos, Int_t len) -{ - SetOffset(pos); - return ReadBuffer(buf, len); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Read a list of buffers given in pos[] and len[] and return it in a single -/// buffer. -/// Returns kTRUE in case of error. - -Bool_t TNetFile::ReadBuffers(char *buf, Long64_t *pos, Int_t *len, Int_t nbuf) -{ - if (!fSocket) return kTRUE; - - // If it's an old version of the protocol try the default TFile::ReadBuffers - if (fProtocol < 17) - return TFile::ReadBuffers(buf, pos, len, nbuf); - - Int_t stat; - Int_t blockSize = 262144; //Let's say we transfer 256KB at the time - Bool_t result = kFALSE; - EMessageTypes kind; - TString data_buf; // buf to put the info - - if (gApplication && gApplication->GetSignalHandler()) - gApplication->GetSignalHandler()->Delay(); - - Double_t start = 0; - if (gPerfStats) start = TTimeStamp(); - - // Make the string with a list of offsets and lengths - Long64_t total_len = 0; - Long64_t actual_pos; - for(Int_t i = 0; i < nbuf; i++) { - data_buf += pos[i] + fArchiveOffset; - data_buf += "-"; - data_buf += len[i]; - data_buf += "/"; - total_len += len[i]; - } - - // Send the command with the length of the info and number of buffers - if (fSocket->Send(Form("%d %d %d", nbuf, data_buf.Length(), blockSize), - kROOTD_GETS) < 0) { - Error("ReadBuffers", "error sending kROOTD_GETS command"); - result = kTRUE; - goto end; - } - // Send buffer with the list of offsets and lengths - if (fSocket->SendRaw(data_buf, data_buf.Length()) < 0) { - Error("ReadBuffers", "error sending buffer"); - result = kTRUE; - goto end; - } - - fErrorCode = -1; - if (Recv(stat, kind) < 0 || kind == kROOTD_ERR) { - PrintError("ReadBuffers", stat); - result = kTRUE; - goto end; - } - - actual_pos = 0; - while (actual_pos < total_len) { - Long64_t left = total_len - actual_pos; - if (left > blockSize) - left = blockSize; - - Int_t n; - while ((n = fSocket->RecvRaw(buf + actual_pos, Int_t(left))) < 0 && - TSystem::GetErrno() == EINTR) - TSystem::ResetErrno(); - - if (n != Int_t(left)) { - Error("GetBuffers", "error receiving buffer of length %d, got %d", - Int_t(left), n); - result = kTRUE ; - goto end; - } - actual_pos += left; - } - - fBytesRead += total_len; - fReadCalls++; -#ifdef R__WIN32 - SetFileBytesRead(GetFileBytesRead() + total_len); - SetFileReadCalls(GetFileReadCalls() + 1); -#else - fgBytesRead += total_len; - fgReadCalls++; -#endif - -end: - - if (gPerfStats) - gPerfStats->FileReadEvent(this, total_len, start); - - if (gApplication && gApplication->GetSignalHandler()) - gApplication->GetSignalHandler()->HandleDelayedSignal(); - - // If found problems try the generic implementation - if (result) { - if (gDebug > 0) - Info("ReadBuffers", "Couldnt use the specific implementation, calling TFile::ReadBuffers"); - return TFile::ReadBuffers(buf, pos, len, nbuf); - } - - return result; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Write specified byte range to remote file via rootd daemon. -/// Returns kTRUE in case of error. - -Bool_t TNetFile::WriteBuffer(const char *buf, Int_t len) -{ - if (!fSocket || !fWritable) return kTRUE; - - Bool_t result = kFALSE; - - Int_t st; - if ((st = WriteBufferViaCache(buf, len))) { - if (st == 2) - return kTRUE; - return kFALSE; - } - - gSystem->IgnoreInterrupt(); - - if (fSocket->Send(Form("%lld %d", fOffset, len), kROOTD_PUT) < 0) { - SetBit(kWriteError); - Error("WriteBuffer", "error sending kROOTD_PUT command"); - result = kTRUE; - goto end; - } - if (fSocket->SendRaw(buf, len) < 0) { - SetBit(kWriteError); - Error("WriteBuffer", "error sending buffer"); - result = kTRUE; - goto end; - } - - Int_t stat; - EMessageTypes kind; - - fErrorCode = -1; - if (Recv(stat, kind) < 0 || kind == kROOTD_ERR) { - SetBit(kWriteError); - PrintError("WriteBuffer", stat); - result = kTRUE; - goto end; - } - - fOffset += len; - - fBytesWrite += len; -#ifdef R__WIN32 - SetFileBytesWritten(GetFileBytesWritten() + len); -#else - fgBytesWrite += len; -#endif - -end: - gSystem->IgnoreInterrupt(kFALSE); - - return result; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Return status from rootd server and message kind. Returns -1 in -/// case of error otherwise 8 (sizeof 2 words, status and kind). - -Int_t TNetFile::Recv(Int_t &status, EMessageTypes &kind) -{ - kind = kROOTD_ERR; - status = 0; - - if (!fSocket) return -1; - - Int_t what; - Int_t n = fSocket->Recv(status, what); - kind = (EMessageTypes) what; - return n; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Set position from where to start reading. - -void TNetFile::Seek(Long64_t offset, ERelativeTo pos) -{ - SetOffset(offset, pos); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Connect to remote rootd server. - -void TNetFile::ConnectServer(Int_t *stat, EMessageTypes *kind, Int_t netopt, - Int_t tcpwindowsize, Bool_t forceOpen, - Bool_t forceRead) -{ - TString fn = fUrl.GetFile(); - - // Create Authenticated socket - Int_t sSize = netopt < -1 ? -netopt : 1; - TString url(fUrl.GetProtocol()); - if (url.Contains("root")) { - url.Insert(4,"dp"); - } else { - url = "rootdp"; - } - url += TString(Form("://%s@%s:%d", - fUrl.GetUser(), fUrl.GetHost(), fUrl.GetPort())); - fSocket = TSocket::CreateAuthSocket(url, sSize, tcpwindowsize, fSocket, stat); - if (!fSocket || (fSocket && !fSocket->IsAuthenticated())) { - if (sSize > 1) - Error("TNetFile", "can't open %d-stream connection to rootd on " - "host %s at port %d", sSize, fUrl.GetHost(), fUrl.GetPort()); - else - Error("TNetFile", "can't open connection to rootd on " - "host %s at port %d", fUrl.GetHost(), fUrl.GetPort()); - *kind = kROOTD_ERR; - goto zombie; - } - - // Check if rootd supports new options - fProtocol = fSocket->GetRemoteProtocol(); - if (forceRead && fProtocol < 5) { - Warning("ConnectServer", "rootd does not support \"+read\" option"); - forceRead = kFALSE; - } - - // Open the file - if (fProtocol < 16) - // For backward compatibility we need to add a '/' at the beginning - fn.Insert(0,"/"); - if (forceOpen) - fSocket->Send(Form("%s %s", fn.Data(), - ToLower("f"+fOption).Data()), kROOTD_OPEN); - else if (forceRead) - fSocket->Send(Form("%s %s", fn.Data(), "+read"), kROOTD_OPEN); - else - fSocket->Send(Form("%s %s", fn.Data(), - ToLower(fOption).Data()), kROOTD_OPEN); - - EMessageTypes tmpkind; - int tmpstat; - Recv(tmpstat, tmpkind); - *stat = tmpstat; - *kind = tmpkind; - - return; - -zombie: - // error in file opening occurred, make this object a zombie - MakeZombie(); - SafeDelete(fSocket); - gDirectory = gROOT; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Create a NetFile object. A net file is the same as a TFile -/// except that it is being accessed via a rootd server. The url -/// argument must be of the form: root[k]://host.dom.ain/file.root. -/// When protocol is "rootk" try using kerberos5 authentication. -/// If the file specified in the URL does not exist, is not accessable -/// or can not be created the kZombie bit will be set in the TNetFile -/// object. Use IsZombie() to see if the file is accessable. -/// If the remote daemon thinks the file is still connected, while you are -/// sure this is not the case you can force open the file by preceding the -/// option argument with an "-", e.g.: "-recreate". Do this only -/// in cases when you are very sure nobody else is using the file. -/// To bypass the writelock on a file, to allow the reading of a file -/// that is being written by another process, explicitly specify the -/// "+read" option ("read" being the default option). -/// The netopt argument can be used to specify the size of the tcp window in -/// bytes (for more info see: http://www.psc.edu/networking/perf_tune.html). -/// The default and minimum tcp window size is 65535 bytes. -/// If netopt < -1 then |netopt| is the number of parallel sockets that will -/// be used to connect to rootd. This option should be used on fat pipes -/// (i.e. high bandwidth, high latency links). The ideal number of parallel -/// sockets depends on the bandwidth*delay product. Generally 5-7 is a good -/// number. -/// For a description of the option and other arguments see the TFile ctor. -/// The preferred interface to this constructor is via TFile::Open(). - -void TNetFile::Create(const char * /*url*/, Option_t *option, Int_t netopt) -{ - Int_t tcpwindowsize = 65535; - - fErrorCode = -1; - fNetopt = netopt; - fOption = option; - - Bool_t forceOpen = kFALSE; - if (option[0] == '-') { - fOption = &option[1]; - forceOpen = kTRUE; - } - // accept 'f', like 'frecreate' still for backward compatibility - if (option[0] == 'F' || option[0] == 'f') { - fOption = &option[1]; - forceOpen = kTRUE; - } - - Bool_t forceRead = kFALSE; - if (!strcasecmp(option, "+read")) { - fOption = &option[1]; - forceRead = kTRUE; - } - - fOption.ToUpper(); - - if (fOption == "NEW") - fOption = "CREATE"; - - Bool_t create = (fOption == "CREATE") ? kTRUE : kFALSE; - Bool_t recreate = (fOption == "RECREATE") ? kTRUE : kFALSE; - Bool_t update = (fOption == "UPDATE") ? kTRUE : kFALSE; - if (!create && !recreate && !update) { - fOption = "READ"; - } - - if (!fUrl.IsValid()) { - Error("Create", "invalid URL specified: %s", fUrl.GetUrl()); - goto zombie; - } - - if (netopt > tcpwindowsize) - tcpwindowsize = netopt; - - // Open connection to remote rootd server - EMessageTypes kind; - Int_t stat; - ConnectServer(&stat, &kind, netopt, tcpwindowsize, forceOpen, forceRead); - if (gDebug > 2) Info("Create", "got from host %d %d", stat, kind); - - if (kind == kROOTD_ERR) { - PrintError("Create", stat); - Error("Create", "failing on file %s", fUrl.GetUrl()); - goto zombie; - } - - if (recreate) { - create = kTRUE; - fOption = "CREATE"; - } - - if (update && stat > 1) { - create = kTRUE; - stat = 1; - } - - if (stat == 1) - fWritable = kTRUE; - else - fWritable = kFALSE; - - Init(create); - return; - -zombie: - // error in file opening occurred, make this object a zombie - MakeZombie(); - SafeDelete(fSocket); - gDirectory = gROOT; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Create a NetFile object using an existing connection (socket s). -/// Provided for use in TNetXNGFile. -/// See: -/// TNetFile::Create(const char *url, Option_t *option, Int_t netopt) -/// for details about the arguments. - -void TNetFile::Create(TSocket *s, Option_t *option, Int_t netopt) -{ - // Import socket - fSocket = s; - - // Create the connection - Create(s->GetUrl(), option, netopt); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Return kTRUE if 'url' matches the coordinates of this file. -/// Check the full URL, including port and FQDN. - -Bool_t TNetFile::Matches(const char *url) -{ - // Run standard check on fUrl, first - Bool_t rc = TFile::Matches(url); - if (rc) - // Ok, standard check enough - return kTRUE; - - // Check also endpoint URL - TUrl u(url); - if (!strcmp(u.GetFile(),fEndpointUrl.GetFile())) { - // Candidate info - TString fqdn = u.GetHostFQDN(); - - // Check ports - if (u.GetPort() == fEndpointUrl.GetPort()) { - TString fqdnref = fEndpointUrl.GetHostFQDN(); - if (fqdn == fqdnref) - // Ok, coordinates match - return kTRUE; - } - } - - // Default is not matching - return kFALSE; -} - -// -// TNetSystem: the directory handler for net files -// - -//////////////////////////////////////////////////////////////////////////////// -/// Create helper class that allows directory access via rootd. -/// Use ftpowner = TRUE (default) if this instance is responsible -/// for cleaning of the underlying TFTP connection; this allows -/// to have control on the order of the final cleaning. - -TNetSystem::TNetSystem(Bool_t ftpowner) - : TSystem("-root", "Net file Helper System") -{ - // name must start with '-' to bypass the TSystem singleton check - SetName("root"); - - fDir = kFALSE; - fDirp = 0; - fFTP = 0; - fFTPOwner = ftpowner; - fUser = ""; - fHost = ""; - fPort = -1; - fIsLocal = kFALSE; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Create helper class that allows directory access via rootd. -/// Use ftpowner = TRUE (default) if this instance is responsible -/// for cleaning of the underlying TFTP connection; this allows -/// to have control on the order of the final cleaning. - -TNetSystem::TNetSystem(const char *url, Bool_t ftpowner) - : TSystem("-root", "Net file Helper System") -{ - // name must start with '-' to bypass the TSystem singleton check - SetName("root"); - - fFTPOwner = ftpowner; - fIsLocal = kFALSE; - Create(url); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Parse and save coordinates of the remote entity (user, host, port, ...) - -void TNetSystem::InitRemoteEntity(const char *url) -{ - TUrl turl(url); - - // Remote username: local as default - fUser = turl.GetUser(); - if (!fUser.Length()) { - UserGroup_t *u = gSystem->GetUserInfo(); - if (u) - fUser = u->fUser; - delete u; - } - - // Check and save the host FQDN ... - fHost = turl.GetHostFQDN(); - - // Remote port: the default should be 1094 because we are here - // only if the protocol is "root://" - fPort = turl.GetPort(); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Create a TNetSystem object. - -void TNetSystem::Create(const char *url, TSocket *sock) -{ - // If we got here protocol must be at least its short form "^root.*:" : - // make sure that it is in the full form to avoid problems in TFTP - TString surl(url); - if (!surl.Contains("://")) { - surl.Insert(surl.Index(":")+1,"//"); - } - TUrl turl(surl); - - fDir = kFALSE; - fDirp = 0; - fFTP = 0; - - // Check locality, taking into account possible prefixes - fLocalPrefix = ""; - fIsLocal = kFALSE; - // We may have been asked explicitly to go through the daemon - Bool_t forceRemote = gEnv->GetValue("Path.ForceRemote", 0); - TString opts = TUrl(url).GetOptions(); - if (opts.Contains("remote=1")) - forceRemote = kTRUE; - else if (opts.Contains("remote=0")) - forceRemote = kFALSE; - if (!forceRemote) { - if ((fIsLocal = TSystem::IsPathLocal(url))) { - fLocalPrefix = gEnv->GetValue("Path.Localroot",""); - // Nothing more to do - return; - } - } - - // Fill in user, host, port - InitRemoteEntity(surl); - - // Build a TFTP url - if (fHost.Length()) { - TString eurl = ""; - // First the protocol - if (strlen(turl.GetProtocol())) { - eurl = turl.GetProtocol(); - eurl += "://"; - } else - eurl = "root://"; - // Add user, if specified - if (strlen(turl.GetUser())) { - eurl += turl.GetUser(); - eurl += "@"; - } - // Add host - eurl += fHost; - // Add port - eurl += ":"; - eurl += turl.GetPort(); - - fFTP = new TFTP(eurl, 1, TFTP::kDfltWindowSize, sock); - if (fFTP && fFTP->IsOpen()) { - if (fFTP->GetSocket()->GetRemoteProtocol() < 12) { - Error("Create", - "remote daemon does not support 'system' functionality"); - fFTP->Close(); - delete fFTP; - } else { - fUser = fFTP->GetSocket()->GetSecContext()->GetUser(); - fHost = fFTP->GetSocket()->GetSecContext()->GetHost(); - // If responsible for the TFTP connection, remove it from the - // socket global list to avoid problems with double deletion - // at final cleanup - if (fFTPOwner) - gROOT->GetListOfSockets()->Remove(fFTP); - } - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// Destructor - -TNetSystem::~TNetSystem() -{ - // Close FTP connection - if (fFTPOwner) { - if (fFTP) { - if (fFTP->IsOpen()) { - - // Close remote directory if still open - if (fDir) { - fFTP->FreeDirectory(kFALSE); - fDir = kFALSE; - } - fFTP->Close(); - } - delete fFTP; - } - } - fDirp = 0; - fFTP = 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Make a directory via rootd. - -Int_t TNetSystem::MakeDirectory(const char *dir) -{ - // If local, use the local TSystem - if (fIsLocal) { - TString edir = TUrl(dir).GetFile(); - if (!fLocalPrefix.IsNull()) - edir.Insert(0, fLocalPrefix); - return gSystem->MakeDirectory(edir); - } - - if (fFTP && fFTP->IsOpen()) { - // Extract the directory name - TString edir = TUrl(dir).GetFile(); - return fFTP->MakeDirectory(edir,kFALSE); - } - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Open a directory and return an opaque pointer to a dir structure. -/// Returns nullptr in case of error. - -void *TNetSystem::OpenDirectory(const char *dir) -{ - // If local, use the local TSystem - if (fIsLocal) { - TString edir = TUrl(dir).GetFile(); - if (!fLocalPrefix.IsNull()) - edir.Insert(0, fLocalPrefix); - return gSystem->OpenDirectory(edir); - } - - if (!fFTP || !fFTP->IsOpen()) - return nullptr; - - if (fDir) { - if (gDebug > 0) - Info("OpenDirectory", "a directory is already open: close it first"); - fFTP->FreeDirectory(kFALSE); - fDir = kFALSE; - } - - // Extract the directory name - TString edir = TUrl(dir).GetFile(); - - if (fFTP->OpenDirectory(edir,kFALSE)) { - fDir = kTRUE; - fDirp = (void *)&fDir; - return fDirp; - } else - return nullptr; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Free directory via rootd. - -void TNetSystem::FreeDirectory(void *dirp) -{ - // If local, use the local TSystem - if (fIsLocal) { - gSystem->FreeDirectory(dirp); - return; - } - - if (dirp != fDirp) { - Error("FreeDirectory", "invalid directory pointer (should never happen)"); - return; - } - - if (fFTP && fFTP->IsOpen()) { - if (fDir) { - fFTP->FreeDirectory(kFALSE); - fDir = kFALSE; - fDirp = 0; - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// Get directory entry via rootd. Returns 0 in case no more entries. - -const char *TNetSystem::GetDirEntry(void *dirp) -{ - // If local, use the local TSystem - if (fIsLocal) { - return gSystem->GetDirEntry(dirp); - } - - if (dirp != fDirp) { - Error("GetDirEntry", "invalid directory pointer (should never happen)"); - return 0; - } - - if (fFTP && fFTP->IsOpen() && fDir) { - return fFTP->GetDirEntry(kFALSE); - } - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Get info about a file. Info is returned in the form of a FileStat_t -/// structure (see TSystem.h). -/// The function returns 0 in case of success and 1 if the file could -/// not be stat'ed. - -Int_t TNetSystem::GetPathInfo(const char *path, FileStat_t &buf) -{ - // If local, use the local TSystem - if (fIsLocal) { - TString epath = TUrl(path).GetFile(); - if (!fLocalPrefix.IsNull()) - epath.Insert(0, fLocalPrefix); - return gSystem->GetPathInfo(epath, buf); - } - - if (fFTP && fFTP->IsOpen()) { - // Extract the directory name - TString epath = TUrl(path).GetFile(); - fFTP->GetPathInfo(epath, buf, kFALSE); - return 0; - } - return 1; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Returns FALSE if one can access a file using the specified access mode. -/// Mode is the same as for the Unix access(2) function. -/// Attention, bizarre convention of return value!! - -Bool_t TNetSystem::AccessPathName(const char *path, EAccessMode mode) -{ - // If local, use the local TSystem - if (fIsLocal) { - TString epath = TUrl(path).GetFile(); - if (!fLocalPrefix.IsNull()) - epath.Insert(0, fLocalPrefix); - return gSystem->AccessPathName(epath, mode); - } - - if (fFTP && fFTP->IsOpen()) { - // Extract the directory name - TString epath = TUrl(path).GetFile(); - return fFTP->AccessPathName(epath, mode, kFALSE); - } - return kTRUE; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Check consistency of this helper with the one required -/// by 'path' or 'dirptr'. - -Bool_t TNetSystem::ConsistentWith(const char *path, void *dirptr) -{ - // Standard check: only the protocol part of 'path' is required to match - Bool_t checkstd = TSystem::ConsistentWith(path, dirptr); - if (!checkstd) return kFALSE; - - // Require match of 'user' and 'host' - Bool_t checknet = path ? kFALSE : kTRUE; - if (path && strlen(path)) { - - // Get user name - TUrl url(path); - TString user = url.GetUser(); - if (user.IsNull() && !fUser.IsNull()) { - UserGroup_t *u = gSystem->GetUserInfo(); - if (u) - user = u->fUser; - delete u; - } - - // Get host name - TString host = url.GetHostFQDN(); - - // Get port - Int_t port = url.GetPort(); - if (gDebug > 1) - Info("ConsistentWith", "fUser:'%s' (%s), fHost:'%s' (%s), fPort:%d (%d)", - fUser.Data(), user.Data(), fHost.Data(), host.Data(), - fPort, port); - - if (user == fUser && host == fHost && port == fPort) - checknet = kTRUE; - } - - return (checkstd && checknet); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Remove a path - -Int_t TNetSystem::Unlink(const char *path) -{ - // If local, use the local TSystem - if (fIsLocal) { - TString epath = TUrl(path).GetFile(); - if (!fLocalPrefix.IsNull()) - epath.Insert(0, fLocalPrefix); - return gSystem->Unlink(epath); - } - - // Not implemented for rootd - Warning("Unlink", "functionality not implemented - ignored (path: %s)", path); - return -1; -} diff --git a/net/net/src/TNetFileStager.cxx b/net/net/src/TNetFileStager.cxx deleted file mode 100644 index 74babfbab0b11..0000000000000 --- a/net/net/src/TNetFileStager.cxx +++ /dev/null @@ -1,135 +0,0 @@ -// @(#)root/net:$Id$ -// Author: G. Ganis Feb 2011 - -/************************************************************************* - * Copyright (C) 1995-2002, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// TNetFileStager // -// // -// TFileStager implementation for a 'rootd' backend. // -// // -////////////////////////////////////////////////////////////////////////// - -#include "TError.h" -#include "TUrl.h" -#include "TNetFile.h" -#include "TNetFileStager.h" - -//////////////////////////////////////////////////////////////////////////////// -/// Constructor. Init a TNetSystem instance to the remote rootd. - -TNetFileStager::TNetFileStager(const char *url) : TFileStager("net") -{ - fSystem = 0; - if (url && strlen(url) > 0) { - GetPrefix(url, fPrefix); - - fSystem = new TNetSystem(fPrefix); - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// Destructor - -TNetFileStager::~TNetFileStager() -{ - SafeDelete(fSystem); - fPrefix = ""; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Check if the file defined by 'path' is ready to be used. - -Bool_t TNetFileStager::IsStaged(const char *path) -{ - if (!IsValid()) { - GetPrefix(path, fPrefix); - fSystem = new TNetSystem(path); - } - - if (IsValid()) { - TString p(path); - if (!p.BeginsWith(fPrefix)) p.Insert(0, fPrefix); - return (fSystem->AccessPathName(p, kReadPermission) ? kFALSE : kTRUE); - } - - // Failure - Warning("IsStaged","TNetSystem not initialized"); - return kFALSE; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Isolate prefix in url - -void TNetFileStager::GetPrefix(const char *url, TString &pfx) -{ - if (gDebug > 1) - ::Info("TNetFileStager::GetPrefix", "enter: %s", url); - - TUrl u(url); - pfx = TString::Format("%s://", u.GetProtocol()); - if (strlen(u.GetUser()) > 0) - pfx += TString::Format("%s@", u.GetUser()); - pfx += u.GetHost(); - if (u.GetPort() != TUrl("root://host").GetPort()) - pfx += TString::Format(":%d", u.GetPort()); - pfx += "/"; - - if (gDebug > 1) - ::Info("TNetFileStager::GetPrefix", "found prefix: %s", pfx.Data()); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Print basic info about this stager - -void TNetFileStager::Print(Option_t *) const -{ - Printf("+++ stager: %s %s", GetName(), fPrefix.Data()); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Get actual end-point url for a path -/// Returns 0 in case of success and 1 if any error occurred - -Int_t TNetFileStager::Locate(const char *path, TString &eurl) -{ - if (!IsValid()) { - GetPrefix(path, fPrefix); - fSystem = new TNetSystem(path); - } - - if (IsValid()) { - TString p(path); - if (!p.BeginsWith(fPrefix)) p.Insert(0, fPrefix); - if (!fSystem->AccessPathName(p, kReadPermission)) { - eurl = p; - return 0; - } - } - - // Unable to initialize TNetSystem or file does not exist - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Returns kTRUE if stager 's' is compatible with current stager. -/// Avoids multiple instantiations of the potentially the same TNetSystem. - -Bool_t TNetFileStager::Matches(const char *s) -{ - if (IsValid()) { - TString pfx; - GetPrefix(s, pfx); - return ((fPrefix == pfx) ? kTRUE : kFALSE); - } - - // Not valid - return kFALSE; -} diff --git a/net/net/src/TPServerSocket.cxx b/net/net/src/TPServerSocket.cxx index fc4819287306e..5e019c893043a 100644 --- a/net/net/src/TPServerSocket.cxx +++ b/net/net/src/TPServerSocket.cxx @@ -9,17 +9,19 @@ * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ -////////////////////////////////////////////////////////////////////////// -// // -// TPServerSocket // -// // -// This class implements parallel server sockets. A parallel server // -// socket waits for requests to come in over the network. It performs // -// some operation based on that request and then possibly returns a // -// full duplex parallel socket to the requester. The actual work is // -// done via the TSystem class (either TUnixSystem or TWinNTSystem). // -// // -////////////////////////////////////////////////////////////////////////// +/** +\file TPServerSocket.cxx +\class TPServerSocket +\brief This class implements parallel server sockets. +\note This class deals with sockets: the user is entirely responsible for the security of their usage, for example, but +not limited to, the management of the connections to said sockets. + +This class implements parallel server sockets. A parallel server +socket waits for requests to come in over the network. It performs +some operation based on that request and then possibly returns a +full duplex parallel socket to the requester. The actual work is +done via the TSystem class (either TUnixSystem or TWinNTSystem). +**/ #include "TPServerSocket.h" #include "TROOT.h" diff --git a/net/net/src/TPSocket.cxx b/net/net/src/TPSocket.cxx index 4e19b65852f0a..c8ad1ac560bc0 100644 --- a/net/net/src/TPSocket.cxx +++ b/net/net/src/TPSocket.cxx @@ -9,17 +9,19 @@ * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ -////////////////////////////////////////////////////////////////////////// -// // -// TPSocket // -// // -// This class implements parallel client sockets. A parallel socket is // -// an endpoint for communication between two machines. It is parallel // -// because several TSockets are open at the same time to the same // -// destination. This especially speeds up communication over Big Fat // -// Pipes (i.e. high bandwidth, high latency WAN connections). // -// // -////////////////////////////////////////////////////////////////////////// +/** +\file TPSocket.cxx +\class TPSocket +\brief This class implements parallel server sockets. +\note This class deals with sockets: the user is entirely responsible for the security of their usage, for example, but +not limited to, the management of the connections to said sockets. + +A parallel socket is an endpoint for communication between two machines. It is parallel +because several TSockets are open at the same time to the same +destination. This especially speeds up communication over Big Fat +Pipes (i.e. high bandwidth, high latency WAN connections). + +**/ #include "TPSocket.h" #include "TUrl.h" @@ -160,8 +162,6 @@ TPSocket::TPSocket(const char *host, Int_t port, Int_t size, //////////////////////////////////////////////////////////////////////////////// /// Create a parallel socket on a connection already opened via /// TSocket sock. -/// This constructor is provided to optimize TNetFile opening when -/// instatiated via a call to TNetXNGFile. /// Returns when connection has been accepted by remote side. Use IsValid() /// to check the validity of the socket. Every socket is added to the TROOT /// sockets list which will make sure that any open sockets are properly diff --git a/net/net/src/TSSLSocket.cxx b/net/net/src/TSSLSocket.cxx index 7e3febcad68e9..cd1efceb2219c 100644 --- a/net/net/src/TSSLSocket.cxx +++ b/net/net/src/TSSLSocket.cxx @@ -9,13 +9,14 @@ * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ -////////////////////////////////////////////////////////////////////////// -// // -// TSSLSocket // -// // -// A TSocket wrapped in by SSL. // -// // -////////////////////////////////////////////////////////////////////////// +/** +\file TSSLSocket.cxx +\class TSSLSocket +\brief A TSocket wrapped in by SSL. +\note This class deals with sockets: the user is entirely responsible for the security of their usage, for example, but +not limited to, the management of the connections to said sockets. +**/ + #include #include "TSSLSocket.h" diff --git a/net/net/src/TServerSocket.cxx b/net/net/src/TServerSocket.cxx index 6f2da016993d3..8342d45a59962 100644 --- a/net/net/src/TServerSocket.cxx +++ b/net/net/src/TServerSocket.cxx @@ -9,17 +9,21 @@ * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ -////////////////////////////////////////////////////////////////////////// -// // -// TServerSocket // -// // -// This class implements server sockets. A server socket waits for // -// requests to come in over the network. It performs some operation // -// based on that request and then possibly returns a full duplex socket // -// to the requester. The actual work is done via the TSystem class // -// (either TUnixSystem or TWinNTSystem). // -// // -////////////////////////////////////////////////////////////////////////// +/** +\file TServerSocket.cxx +\class TServerSocket +\brief This class implements server sockets. +\note This class deals with sockets: the user is entirely responsible for the security of their usage, for example, but +not limited to, the management of the connections to said sockets. + +This class implements server sockets. A server socket waits for +requests to come in over the network. It performs some operation +based on that request and then possibly returns a full duplex socket +to the requester. The actual work is done via the TSystem class +(either TUnixSystem or TWinNTSystem). + +**/ + #include "TServerSocket.h" #include "TSocket.h" diff --git a/net/net/src/TSocket.cxx b/net/net/src/TSocket.cxx index f58dc4ad2a50a..cabe71abeb551 100644 --- a/net/net/src/TSocket.cxx +++ b/net/net/src/TSocket.cxx @@ -9,16 +9,17 @@ * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ -////////////////////////////////////////////////////////////////////////// -// // -// TSocket // -// // -// This class implements client sockets. A socket is an endpoint for // -// communication between two machines. // -// The actual work is done via the TSystem class (either TUnixSystem // -// or TWinNTSystem). // -// // -////////////////////////////////////////////////////////////////////////// +/** +\file TSocket.cxx +\class TSocket +\brief This class implements client sockets. +\note This class deals with sockets: the user is entirely responsible for the security of their usage, for example, but +not limited to, the management of the connections to said sockets. + +A socket is an endpoint for communication between two machines. The actual work is done via the TSystem class (either +TUnixSystem or TWinNTSystem). + +**/ #include "Bytes.h" #include "Compression.h" @@ -43,7 +44,7 @@ ULong64_t TSocket::fgBytesRecv = 0; // // Client "protocol changes" // -// This was in TNetFile and TAuthenticate before, but after the introduction +// This was in the old TNetFile and TAuthenticate before, but after the introduction // of TSocket::CreateAuthSocket the common place for all the clients is TSocket, // so this seems to be the right place for a version number // diff --git a/net/net/src/TUDPSocket.cxx b/net/net/src/TUDPSocket.cxx index ef5676bfa36c4..abfa279a20eae 100644 --- a/net/net/src/TUDPSocket.cxx +++ b/net/net/src/TUDPSocket.cxx @@ -9,16 +9,16 @@ * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ -////////////////////////////////////////////////////////////////////////// -// // -// TUDPSocket // -// // -// This class implements UDP client sockets. A socket is an endpoint // -// for communication between two machines. // -// The actual work is done via the TSystem class (either TUnixSystem // -// or TWinNTSystem). // -// // -////////////////////////////////////////////////////////////////////////// +/** +\file TUDPSocket.cxx +\class TUDPSocket +\brief This class implements UDP client sockets. +\note This class deals with sockets: the user is entirely responsible for the security of their usage, for example, but +not limited to, the management of the connections to said sockets. + +A socket is an endpoint for communication between two machines. The actual work is done via the TSystem class (either +TUnixSystem or TWinNTSystem). +**/ #include "Bytes.h" #include "Compression.h" diff --git a/net/rpdutils/CMakeLists.txt b/net/rpdutils/CMakeLists.txt deleted file mode 100644 index ffde37d2e52a2..0000000000000 --- a/net/rpdutils/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. -# All rights reserved. -# -# For the licensing terms see $ROOTSYS/LICENSE. -# For the list of contributors see $ROOTSYS/README/CREDITS. - -############################################################################ -# CMakeLists.txt file for building ROOT net/rpdutils package -# @author Pere Mato, CERN -############################################################################ - -include_directories(res ../auth/res) - -if(MACOSX_SSL_DEPRECATED) - set_source_files_properties(src/rpdutils.cxx COMPILE_FLAGS "-Wno-deprecated-declarations") -endif() - -if(shadowpw) - add_definitions(-DR__SHADOWPW) -endif() - -if(ssl) - include_directories(${OPENSSL_INCLUDE_DIR}) -endif() - -add_library(rpdutil STATIC - src/daemon.cxx - src/error.cxx - src/net.cxx - src/netpar.cxx - src/rpdutils.cxx -) - -target_include_directories(rpdutil PRIVATE - ${CMAKE_SOURCE_DIR}/core/clib/inc # for snprintf.h - ${CMAKE_SOURCE_DIR}/core/base/inc # for RConfig.hxx - ${CMAKE_SOURCE_DIR}/core/foundation/inc # for TError.hxx - ${CMAKE_SOURCE_DIR}/core/meta/inc # for TGenericClassInfo.h - ${CMAKE_SOURCE_DIR}/net/net/inc # for NetErrors.h - ${CMAKE_SOURCE_DIR}/net/auth/inc # for NetErrors.h - ${CMAKE_BINARY_DIR}/ginclude # for RConfigure.h -) - -target_link_libraries(rpdutil INTERFACE $<$:crypt>) -set_property(TARGET rpdutil PROPERTY POSITION_INDEPENDENT_CODE ON) -add_dependencies(rpdutil move_headers) - -ROOT_LINKER_LIBRARY(SrvAuth rpdutils.cxx DaemonUtils.h DaemonUtils.cxx - LIBRARIES - ${OPENSSL_LIBRARIES} - rpdutil - rsa - DEPENDENCIES - Net - BUILTINS - OPENSSL -) - -target_include_directories(SrvAuth PRIVATE - ${CMAKE_SOURCE_DIR}/net/auth/res - ${CMAKE_SOURCE_DIR}/net/auth/inc - ${CMAKE_SOURCE_DIR}/rpdutils/res -) - -if (CMAKE_SYSTEM_NAME MATCHES FreeBSD) - target_link_libraries(SrvAuth PRIVATE crypt) -endif() - diff --git a/net/rpdutils/res/rpdconn.h b/net/rpdutils/res/rpdconn.h deleted file mode 100644 index 32ac8da5f4b89..0000000000000 --- a/net/rpdutils/res/rpdconn.h +++ /dev/null @@ -1,220 +0,0 @@ -// @(#)root/rpdutils:$Id$ -// Author: Gerardo Ganis, March 2011 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -#ifndef ROOT_rpdconn -#define ROOT_rpdconn - -////////////////////////////////////////////////////////////////////////// -// // -// rpdconn // -// // -// This header file contains the definition of some utility classes // -// used for process communication between rootd. // -// // -////////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include -#include - -// -// Basic mutex helper class -// - -class rpdmtxhelper { -private: - pthread_mutex_t *mtx; - bool ok; - - void rawlock(const pthread_mutex_t *m) { if (m) { - if (!pthread_mutex_lock((pthread_mutex_t *)m)) { - mtx = (pthread_mutex_t *)m; ok = 1; } } } - void rawunlock(const pthread_mutex_t *m) { if (m) { pthread_mutex_unlock((pthread_mutex_t *)m); } mtx = 0; ok = 0; } - -public: - rpdmtxhelper(const pthread_mutex_t *m = 0) { mtx = 0; ok = 0; rawlock(m); } - rpdmtxhelper(const pthread_mutex_t &m) { mtx = 0; ok = 0; rawlock(&m); } - virtual ~rpdmtxhelper() { rawunlock(mtx); } - - inline void lock() { rawlock(mtx); }; - inline void unlock() { rawunlock(mtx); } - inline bool isok() { return ok; } -}; - -// -// Class describing a basic message -// -class rpdconn; -class rpdmsg { -friend class rpdconn; -protected: - int type; // Message type (positive; -1 for undef) - std::string buf; // Internal buffer - int cur; // Offset while streaming out - -public: - rpdmsg(int t = -1) : type(t), cur(0) { } - rpdmsg(int t, const char *b) : type(t), buf(b), cur(0) { } - - bool empty() { return ((cur < 0 || - (cur >= 0 && (int) buf.length() <= cur)) ? 1 : 0); } - void reset(int t = -1) { if (t >= 0) type = t; buf = ""; cur = 0; } - void rewind() { cur = 0; } - void settype(int t) { type = t; } - - // Access content - int what() const { return type; } - const char *content() const { return buf.c_str(); } - - // in/out functions - void r_int(int &i); - void r_double(double &d); - void r_string(std::string &s); - void w_int(int i); - void w_double(double d); - void w_string(const std::string &s); -}; -// rpdmsg external operators -inline rpdmsg &operator>>(rpdmsg &m, int &i) { m.r_int(i); return m; } -inline rpdmsg &operator>>(rpdmsg &m, double &d) { m.r_double(d); return m; } -inline rpdmsg &operator>>(rpdmsg &m, std::string &s) { m.r_string(s); return m; } -inline rpdmsg &operator<<(rpdmsg &m, int i) { m.w_int(i); return m; } -inline rpdmsg &operator<<(rpdmsg &m, double d) { m.w_double(d); return m; } -inline rpdmsg &operator<<(rpdmsg &m, const std::string &s) { m.w_string(s); return m; } - -// -// Class describing a basic connection -// -class rpdconn { -protected: - pthread_mutex_t rdmtx; // Mutex for read operations - pthread_mutex_t wrmtx; // Mutex for write operations - int rdfd; // Descriptor for read operations - int wrfd; // Descriptor for write operations -public: - rpdconn(int r = -1, int w = -1); - virtual ~rpdconn() { } - - virtual void close() = 0; - virtual bool isvalid(bool rd) const { - int rc = 0; - if (rd) { - rpdmtxhelper mh(&rdmtx); - rc = (rdfd > 0) ? 1 : 0; - } else { - rpdmtxhelper mh(&wrmtx); - rc = (wrfd > 0) ? 1 : 0; - } - return rc; - } - void setdescriptors(int r = -1, int w = -1) { - { rpdmtxhelper mh(&rdmtx); rdfd = r; } - { rpdmtxhelper mh(&wrmtx); wrfd = w; } - } - - int pollrd(int to = -1); - - int send(int i); - int send(int type, const char *msg); - int send(const rpdmsg &msg); - virtual int send(const void *buf, int len); - int recv(int &i); - int recv(int &type, std::string &msg); - int recv(rpdmsg &msg); - virtual int recv(void *buffer, int len); - - int senddesc(int desc); - int recvdesc(int &desc); -}; - -// -// Class describing a TCP connection -// -class rpdtcp : public rpdconn { -protected: - std::string host; // Host name - int port; // Port - int fd; // Socket descriptor - struct sockaddr addr; // Structure describing the peer address -public: - rpdtcp(int d = -1) : rpdconn(), port(0), fd(d) { memset(&addr, 0, sizeof(addr)); - setdescriptors(d,d); } // Used by rpdtcpsrv - rpdtcp(const char *h, int p); - virtual ~rpdtcp() { close(); } - - void close() { if (fd > 0) ::close(fd); fd = -1; setdescriptors(); } - int exportfd() { int d = fd; fd = -1; setdescriptors(); return d; } - const struct sockaddr *address() const { return (const struct sockaddr *)&addr; } -}; - -// -// Class describing a server TCP connection -// -class rpdtcpsrv : public rpdtcp { -public: - rpdtcpsrv(int p, int backlog = 10); - virtual ~rpdtcpsrv() { rpdtcp::close(); } - - rpdtcp *accept(int to = -1, int *err = 0); -}; - -// -// Class describing a UNIX TCP connection -// -class rpdunix : public rpdtcp { -protected: - std::string sockpath; // Socket path -public: - rpdunix(int d = -1) : rpdtcp(d) { } - rpdunix(const char *p); - virtual ~rpdunix() { rpdtcp::close(); } - const char *path() const { return sockpath.c_str(); } -}; - -// -// Class describing a server UNIX TCP connection -// -class rpdunixsrv : public rpdunix { -protected: - int fd; // Socket descriptor -public: - rpdunixsrv(const char *p, int backlog = 10); - virtual ~rpdunixsrv() { rpdtcp::close(); } - - rpdunix *accept(int to = -1, int *err = 0); -}; - -// -// Class describing a UDP connection -// -class rpdudp : public rpdtcp { -public: - rpdudp(int d = -1) : rpdtcp(d) { } // Used by rpdudpsrv - rpdudp(const char *h, int p); - virtual ~rpdudp() { } - - int send(const void *buf, int len); - int recv(void *buffer, int len); -}; - -// -// Class describing a server UDP connection -// -class rpdudpsrv : public rpdudp { -public: - rpdudpsrv(int p); - virtual ~rpdudpsrv() { rpdudp::close(); } -}; - -#endif diff --git a/net/rpdutils/res/rpddefs.h b/net/rpdutils/res/rpddefs.h deleted file mode 100644 index fc09d26961d8c..0000000000000 --- a/net/rpdutils/res/rpddefs.h +++ /dev/null @@ -1,42 +0,0 @@ -// @(#)root/rpdutils:$Id$ -// Author: Gerardo Ganis 7/4/2003 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -#ifndef ROOT_rpddefs -#define ROOT_rpddefs - - -///////////////////////////////////////////////////////////////////// -// // -// Definition used by daemons // -// // -///////////////////////////////////////////////////////////////////// - -#include "AuthConst.h" - -// -// Typedefs -typedef void (*SigPipe_t)(int); - -// -// Global consts -const int kMAXRECVBUF = 1024; -const int kMAXUSERLEN = 128; - -// Masks for initialization options -const unsigned int kDMN_RQAUTH = 0x1; // Require authentication -const unsigned int kDMN_HOSTEQ = 0x2; // Allow host equivalence -const unsigned int kDMN_SYSLOG = 0x4; // Log messages to syslog i.o. stderr - -// -// type of service -enum EService { kSOCKD = 0, kROOTD }; - -#endif diff --git a/net/rpdutils/res/rpderr.h b/net/rpdutils/res/rpderr.h deleted file mode 100644 index 665db0b2bc410..0000000000000 --- a/net/rpdutils/res/rpderr.h +++ /dev/null @@ -1,29 +0,0 @@ -// @(#)root/rpdutils:$Id$ -// Author: Fons Rademakers 11/08/97 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -#ifndef ROOT_rpderr -#define ROOT_rpderr - - -////////////////////////////////////////////////////////////////////////// -// // -// rpderr // -// // -// This header file defines error codes generated by rootd. // -// NB: In case of change update also strings in net/inc/ErrStr.h // -// // -////////////////////////////////////////////////////////////////////////// - -#include "NetErrors.h" - -typedef void (*ErrorHandler_t)(int level, const char *msg, int size); - -#endif diff --git a/net/rpdutils/res/rpdp.h b/net/rpdutils/res/rpdp.h deleted file mode 100644 index ba2a6a881f758..0000000000000 --- a/net/rpdutils/res/rpdp.h +++ /dev/null @@ -1,188 +0,0 @@ -// @(#)root/rpdutils:$Id$ -// Author: Gerardo Ganis 7/4/2003 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -#ifndef ROOT_rpdp -#define ROOT_rpdp - - -////////////////////////////////////////////////////////////////////////// -// // -// rpdp // -// // -// This header file contains private definitions and declarations // -// used by modules in rpdutils/src. // -// // -////////////////////////////////////////////////////////////////////////// - -#include "Varargs.h" -#include "MessageTypes.h" -#include "rpderr.h" -#include - -///////////////////////////////////////////////////////////////////// -// // -// Definition used by daemons // -// // -///////////////////////////////////////////////////////////////////// - -#include "rpddefs.h" - -#include "Rtypes.h" //const int kMAXPATHLEN = kMAXSECBUF; - -///////////////////////////////////////////////////////////////////// -// // -// Prototypes used by daemons // -// // -///////////////////////////////////////////////////////////////////// - -// -// rpdutils globals -namespace ROOT { - -// Utility functions -int SPrintf(char *buf, size_t size, const char *va_(fmt), ...); - -// error handling functions -void Error(ErrorHandler_t ErrHand,int code,const char *va_(fmt), ...); -void ErrorInfo(const char *va_(fmt), ...); -void ErrorInit(const char *ident); -int GetErrno(); -void Perror(char *buf, int size = kMAXPATHLEN); -void ResetErrno(); - -// network functions -void NetClose(); -double NetGetBytesRecv(); -double NetGetBytesSent(); -void NetGetRemoteHost(std::string &host); -int NetGetSockFd(); -int NetInit(EService service, int port1, int port2, int tcpwindowsize); -int NetParOpen(int port, int size); -int NetOpen(int inetdflag, EService service); -int NetRecv(char *msg, int len, EMessageTypes &kind); -int NetRecvAllocate(void *&buf, int &len, EMessageTypes &kind); -int NetRecvRaw(void *buf, int len); -void NetResetByteCount(); -int NetSend(int code, EMessageTypes kind); -int NetSend(const char *msg, EMessageTypes kind = kMESS_STRING); -int NetSendError(ERootdErrors err); -int NetSendRaw(const void *buf, int len); -void NetSetSigPipeHook(SigPipe_t hook); - -// fork functionality -void DaemonStart(int ignsigcld, int fdkeep, EService service); - -// rpdutils.cxx -void RpdAuthCleanup(const char *sstr, int opt); -int RpdGenRSAKeys(int); -int RpdInitSession(int, std::string &, int &); -int RpdInitSession(int, std::string &, int &, int &, std::string &); -int RpdInitSession(int, std::string &, int &, int &, int &, std::string &); -void RpdInit(EService serv, int pid, int sproto, - unsigned int opts, int rumsk, int sshp, - const char *tmpd, const char *asrpp, int login = 0); -void RpdSetErrorHandler(ErrorHandler_t Err, ErrorHandler_t Sys, - ErrorHandler_t Fatal); -#ifdef R__KRB5 -void RpdSetKeytabFile(const char *keytabfile); -#endif -void RpdSetSysLogFlag(int syslog); -void RpdSetMethInitFlag(int methinit); -int RpdUpdateAuthTab(int opt, const char *line, char **token, int ilck = 0); - -} // namespace ROOT - - -///////////////////////////////////////////////////////////////////// -// // -// Internal Definition and prototypes used by modules in rpdutils // -// // -///////////////////////////////////////////////////////////////////// - -// -// Prototypes -// -namespace ROOT { - -// -// Utility functions -char *ItoA(int i); - -// -// net.cxx -int NetRecv(char *msg, int max); -int NetRecvRaw(int sock, void *buf, int len); -int NetSend(const void *buf, int len, EMessageTypes kind); -int NetSendAck(); -void NetSetOptions(EService service, int sock, int tcpwindowsize); - -// -// netpar.cxx -void NetParClose(); -int NetParRecv(void *buf, int len); -int NetParSend(const void *buf, int len); - -// -// rpdutils.cxx -int RpdAuthenticate(); -int RpdCheckAuthAllow(int Sec, const char *Host); -int RpdCheckAuthTab(int Sec, const char *User, const char *Host, - int RemId, int *OffSet); -int RpdCheckDaemon(const char *daemon); -int RpdCheckHost(const char *Host, const char *host); -int RpdCheckOffSet(int Sec, const char *User, const char *Host, int RemId, - int *OffSet, char **tkn, int *shmid, char **glbsuser); -int RpdCheckSpecialPass(const char *passwd); - int RpdRetrieveSpecialPass(const char *usr, const char *fpw, char *pwd, int lmx); -int RpdCheckSshd(int opt); -bool RpdCheckToken(char *tknin, char *tknref); -int RpdCleanupAuthTab(const char *crypttoken); -int RpdCleanupAuthTab(const char *Host, int RemId, int OffSet); -void RpdDefaultAuthAllow(); -int RpdDeleteKeyFile(int ofs); -void RpdFreeKeys(); -int RpdGetAuthMethod(int kind); -char *RpdGetIP(const char *host); -char *RpdGetRandString(int Opt, int Len); -int RpdGetRSAKeys(const char *PubKey, int Opt); -int RpdGlobusAuth(const char *sstr); -int RpdGuessClientProt(const char *buf, EMessageTypes kind); -void RpdInitAuth(); -void RpdInitRand(); -int RpdKrb5Auth(const char *sstr); -int RpdLogin(int,int); -int RpdNoAuth(int); -int RpdPass(const char *pass, int errheq = 0); -int RpdProtocol(int); -int RpdRecvClientRSAKey(); -int RpdRenameKeyFile(int oofs, int nofs); -int RpdReUseAuth(const char *sstr, int kind); -int RpdRfioAuth(const char *sstr); -int RpdSavePubKey(const char *PubKey, int OffSet, char *User); -int RpdSecureRecv(char **Str); -int RpdSecureSend(char *Str); -void RpdSendAuthList(); -int RpdSetUid(int uid); -int RpdSRPUser(const char *user); -int RpdSshAuth(const char *sstr); -int RpdUser(const char *sstr); - -// -// Ssh Utility Function prototypes ... -int SshToolAllocateSocket(unsigned int, unsigned int, char **); -void SshToolDiscardSocket(const char *, int); -int SshToolGetAuth(int); -int SshToolGetAuth(int, const char *); -int SshToolNotifyFailure(const char *); - -} // namespace ROOT - -#endif diff --git a/net/rpdutils/res/rpdpriv.h b/net/rpdutils/res/rpdpriv.h deleted file mode 100644 index a59a57fbc0bb8..0000000000000 --- a/net/rpdutils/res/rpdpriv.h +++ /dev/null @@ -1,81 +0,0 @@ -// @(#)root/rpdutils:$Id$ -// Author: Gerardo Ganis, March 2011 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -#ifndef ROOT_rpdpriv -#define ROOT_rpdpriv - -////////////////////////////////////////////////////////////////////////// -// // -// rpdpriv // -// // -// Implementation of a privileges handling API following the paper // -// "Setuid Demystified" by H.Chen, D.Wagner, D.Dean // -// also quoted in "Secure programming Cookbook" by J.Viega & M.Messier. // -// // -// NB: this not thread-safe: it is meant to be used in single-threaded // -// applications // -// // -////////////////////////////////////////////////////////////////////////// - -#if !defined(WINDOWS) -# include -#else -# define uid_t unsigned int -# define gid_t unsigned int -#endif - -class rpdpriv -{ - friend class rpdprivguard; - private: - - rpdpriv(); - - static bool debug; - - static int changeto(uid_t uid, gid_t gid); - static void dumpugid(const char *msg = 0); - static int restore(bool saved = 1); - - public: - virtual ~rpdpriv() { } - static int changeperm(uid_t uid, gid_t gid); -}; - -// -// Guard class; -// Usage: -// -// { rpdprivguard priv(tempuid); -// -// // Work as tempuid (maybe superuser) -// ... -// -// } -// -class rpdprivguard -{ - public: - rpdprivguard(uid_t uid, gid_t gid); - rpdprivguard(const char *user); - virtual ~rpdprivguard(); - bool isvalid() const { return valid; } - private: - bool dum; - bool valid; - void init(uid_t uid, gid_t gid); -}; - -#ifndef rpdbadpguard -#define rpdbadpguard(g,u) (!(g.isvalid()) && (geteuid() != (uid_t)u)) -#endif - -#endif diff --git a/net/rpdutils/src/DaemonUtils.cxx b/net/rpdutils/src/DaemonUtils.cxx deleted file mode 100644 index d9b45699f5484..0000000000000 --- a/net/rpdutils/src/DaemonUtils.cxx +++ /dev/null @@ -1,580 +0,0 @@ -// @(#)root/auth:$Id$ -// Author: Gerri Ganis 19/1/2004 - -/************************************************************************* - * Copyright (C) 1995-2003, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// DaemonUtils // -// // -// This file defines wrappers to client utils calls used by server // -// authentication daemons // -// // -////////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(linux) -# include -# if __GNU_LIBRARY__ == 6 -# ifndef R__GLIBC -# define R__GLIBC -# endif -# endif -#endif -#if defined(__MACH__) && !defined(__APPLE__) -# define R__GLIBC -#endif - -#ifdef __sun -# ifndef _REENTRANT -# if __SUNPRO_CC > 0x420 -# define GLOBAL_ERRNO -# endif -# endif -#endif - -#include "Rtypes.h" -#include "Varargs.h" -#include "DaemonUtils.h" -#include "TAuthenticate.h" -#include "TSecContext.h" -#include "TEnv.h" -#include "TROOT.h" - -//________________________________________________________________________ - -// --- Globals -------------------------------------------------------- -static TSocket *gSocket; - -// This is to be changed whenever something is changed -// in non-backward compatible way -// 0 -> 1: support for SSH authentication via SSH tunnel -static Int_t gSrvProtocol = 1; -static EService gService = kSOCKD; -static Int_t gReuseAllow = 0x1F; - -using namespace std; -using namespace ROOT; - -extern "C" { - Int_t SrvAuthenticate(TSocket *socket, - const char *confdir, const char *tmpdir, - string &user, Int_t &meth, Int_t &type, string &ctkn, - TSeqCollection *secctxlist) { - return SrvAuthImpl(socket, confdir, tmpdir, user, meth, type, ctkn, secctxlist); - } -} - -extern "C" { - Int_t SrvAuthCleanup(TSeqCollection *sls) { - return SrvClupImpl(sls); - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// Set relevant environment variables - -static Int_t SrvSetVars(string /*confdir*/) -{ - // Executables and conf dirs - - // Make rootbindir available to all the session via env - string execdir = TROOT::GetBinDir().Data(); - if (execdir.length()) { - int len = 15 + execdir.length(); - char *tmp = new char[len+1]; - if (tmp) { - snprintf(tmp,len+1, "ROOTBINDIR=%.*s", len, execdir.c_str()); - putenv(tmp); - } else - return -1; - } - - // Make rootetcdir available to all the session via env - string etcdir = TROOT::GetEtcDir().Data(); - if (etcdir.length()) { - int len = 15 + etcdir.length(); - char *tmp = new char[len+1]; - if (tmp) { - snprintf(tmp, len+1, "ROOTETCDIR=%.*s", len, etcdir.c_str()); - putenv(tmp); - } else - return -1; - } - - // If specified, set the special daemonrc file to be used - string daemonrc = string(gEnv->GetValue("SrvAuth.DaemonRc","")); - if (daemonrc.length()) { - int len = 15 + daemonrc.length(); - char *tmp = new char[len+1]; - if (tmp) { - snprintf(tmp, len+1, "ROOTDAEMONRC=%.*s", len, daemonrc.c_str()); - putenv(tmp); - } else - return -1; - } - - // If specified, set the special gridmap file to be used - string gridmap = string(gEnv->GetValue("SrvAuth.GridMap","")); - if (gridmap.length()) { - int len = 15 + gridmap.length(); - char *tmp = new char[len+1]; - if (tmp) { - snprintf(tmp, len+1, "GRIDMAP=%.*s", len, gridmap.c_str()); - putenv(tmp); - } else - return -1; - } - - // If specified, set the special hostcert.conf file to be used - string hcconf = string(gEnv->GetValue("SrvAuth.HostCert","")); - if (hcconf.length()) { - int len = 15 + hcconf.length(); - char *tmp = new char[len+1]; - if (tmp) { - snprintf(tmp, len+1, "ROOTHOSTCERT=%.*s", len, hcconf.c_str()); - putenv(tmp); - } else - return -1; - } - - return 0; -} - - -//////////////////////////////////////////////////////////////////////////////// - -void Err(int level, const char *msg, int size) -{ - Perror((char *)msg, size); - if (level > -1) NetSend(level, kROOTD_ERR); -} - -//////////////////////////////////////////////////////////////////////////////// - -void ErrFatal(int level, const char *msg, int size) -{ - Perror((char *)msg, size); - if (level > -1) NetSend(msg, kMESS_STRING); -} - -//////////////////////////////////////////////////////////////////////////////// - -void ErrSys(int level, const char *msg, int size) -{ - Perror((char *)msg, size); - ErrFatal(level, msg, size); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Wrapper to cleanup code - -Int_t SrvClupImpl(TSeqCollection *secls) -{ - TIter next(secls); - TSecContext *nsc ; - while ((nsc = (TSecContext *)next())) { - if (!strncmp(nsc->GetID(),"server",6)) { - int rc = RpdCleanupAuthTab(nsc->GetToken()); - if (gDebug > 0 && rc < 0) - ErrorInfo("SrvClupImpl: operation unsuccessful (rc: %d, ctkn: %s)", - rc, nsc->GetToken()); - } - } - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Server authentication code. -/// Returns 0 in case authentication failed -/// 1 in case of success -/// On success, returns authenticated username in user - -Int_t SrvAuthImpl(TSocket *socket, const char *confdir, const char *tmpdir, - string &user, Int_t &meth, Int_t &type, string &ctoken, - TSeqCollection *secctxlist) -{ - Int_t rc = 0; - - // Check if hosts equivalence is required - Bool_t hequiv = gEnv->GetValue("SrvAuth.CheckHostsEquivalence",0); - - // Pass file for SRP - string altSRPpass = string(gEnv->GetValue("SrvAuth.SRPpassfile","")); - - // Port for the SSH daemon - Int_t sshdport = gEnv->GetValue("SrvAuth.SshdPort",22); - - // Set envs - if (SrvSetVars(string(confdir)) == -1) - // Problems setting environment - return rc; - - // Parent ID - int parentid = getpid(); // Process identifier - - // default job options - unsigned int options = kDMN_RQAUTH | kDMN_HOSTEQ; - if (!hequiv) - options &= ~kDMN_HOSTEQ; - - // Init error handlers - RpdSetErrorHandler(Err, ErrSys, ErrFatal); - - // Init daemon code - RpdInit(gService, parentid, gSrvProtocol, options, - gReuseAllow, sshdport, - tmpdir, altSRPpass.c_str()); - - // Generate Local RSA keys for the session - if (RpdGenRSAKeys(0)) - // Problems generating keys - return rc; - - // Reset check of the available method list - RpdSetMethInitFlag(0); - - // Trasmit relevant socket details - SrvSetSocket(socket); - - // Init Session (get protocol, run authentication, ...) - // type of authentication: - // 0 (new), 1 (existing), 2 (updated offset) - int clientprotocol = 0; - rc = RpdInitSession(gService, user, clientprotocol, meth, type, ctoken); - - TSecContext *seccontext = 0; - if (rc > 0) { - string openhost(socket->GetInetAddress().GetHostName()); - - if (type == 1) { - // An existing authentication has been re-used: retrieve - // the related security context - TIter next(gROOT->GetListOfSecContexts()); - while ((seccontext = (TSecContext *)next())) { - if (!(strncmp(seccontext->GetID(),"server",6))) { - if (seccontext->GetMethod() == meth) { - if (!strcmp(openhost.c_str(),seccontext->GetHost())) { - if (!strcmp(user.c_str(),seccontext->GetUser())) - break; - } - } - } - } - } - - if (!seccontext) { - // New authentication: Fill a SecContext for cleanup - // in case of interrupt - seccontext = new TSecContext(user.c_str(), openhost.c_str(), meth, -1, - "server", ctoken.c_str()); - if (seccontext) { - // Add to the list - secctxlist->Add(seccontext); - // Store SecContext - socket->SetSecContext(seccontext); - } else { - if (gDebug > 0) - ErrorInfo("SrvAuthImpl: could not create sec context object" - ": potential problems in cleaning"); - } - } - } - - - // Done - return rc; -} - - -namespace ROOT { - - static int gSockFd = -1; - -//////////////////////////////////////////////////////////////////////////////// -/// Fill socket parameters - - void SrvSetSocket(TSocket *Socket) - { - gSocket = Socket; - gSockFd = Socket->GetDescriptor(); - } - -//////////////////////////////////////////////////////////////////////////////// -/// Receive exactly length bytes into buffer. Returns number of bytes -/// received. Returns -1 in case of error. - - static int Recvn(int sock, void *buffer, int length) - { - if (sock < 0) return -1; - - int n, nrecv = 0; - char *buf = (char *)buffer; - - for (n = 0; n < length; n += nrecv) { - while ((nrecv = recv(sock, buf+n, length-n, 0)) == -1 - && GetErrno() == EINTR) - ResetErrno(); // probably a SIGCLD that was caught - if (nrecv < 0) { - Error(gErrFatal,-1, - "Recvn: error (sock: %d): errno: %d",sock,GetErrno()); - return nrecv; - } else if (nrecv == 0) - break; // EOF - } - - return n; - } - -//////////////////////////////////////////////////////////////////////////////// -/// Empty call, for consistency - - void NetClose() - { - return; - } - -//////////////////////////////////////////////////////////////////////////////// -/// return open socket descriptor - - int NetGetSockFd() - { - return gSockFd; - } - -//////////////////////////////////////////////////////////////////////////////// -/// Empty call, for consistency - - int NetParOpen(int port, int size) - { - if (port+size) - return (port+size); - else - return 1; - } - -//////////////////////////////////////////////////////////////////////////////// -/// Receive a string of maximum length max. - - int NetRecv(char *msg, int max) - { - return gSocket->Recv(msg, max); - } - -//////////////////////////////////////////////////////////////////////////////// -/// Receive a string of maximum len length. Returns message type in kind. -/// Return value is msg length. - - int NetRecv(char *msg, int len, EMessageTypes &kind) - { - Int_t tmpkind; - Int_t rc = gSocket->Recv(msg, len, tmpkind); - kind = (EMessageTypes)tmpkind; - return rc; - } - -//////////////////////////////////////////////////////////////////////////////// -/// Receive a buffer. Returns the newly allocated buffer, the length -/// of the buffer and message type in kind. - - int NetRecv(void *&buf, int &len, EMessageTypes &kind) - { - int hdr[2]; - - if (NetRecvRaw(hdr, sizeof(hdr)) < 0) - return -1; - - len = ntohl(hdr[0]) - sizeof(int); - kind = (EMessageTypes) ntohl(hdr[1]); - if (len) { - buf = new char* [len]; - return NetRecvRaw(buf, len); - } - buf = 0; - return 0; - - } - -//////////////////////////////////////////////////////////////////////////////// -/// Receive a buffer of maximum len bytes. - - int NetRecvRaw(void *buf, int len) - { - return gSocket->RecvRaw(buf,len); - } - -//////////////////////////////////////////////////////////////////////////////// -/// Receive a buffer of maximum len bytes from generic socket sock. - - int NetRecvRaw(int sock, void *buf, int len) - { - if (sock == -1) return -1; - - if (Recvn(sock, buf, len) < 0) { - Error(gErrFatal,-1, - "NetRecvRaw: Recvn error (sock: %d, errno: %d)",sock,GetErrno()); - } - - return len; - } - -//////////////////////////////////////////////////////////////////////////////// -/// Send integer. Message will be of type "kind". - - int NetSend(int code, EMessageTypes kind) - { - int hdr[3]; - int hlen = sizeof(int) + sizeof(int); - hdr[0] = htonl(hlen); - hdr[1] = htonl(kind); - hdr[2] = htonl(code); - - return gSocket->SendRaw(hdr, sizeof(hdr)); - } - -//////////////////////////////////////////////////////////////////////////////// -/// Send a string. Message will be of type "kind". - - int NetSend(const char *msg, EMessageTypes kind) - { - return gSocket->Send(msg, kind); - } - -//////////////////////////////////////////////////////////////////////////////// -/// Send buffer of len bytes. Message will be of type "kind". - - int NetSend(const void *buf, int len, EMessageTypes kind) - { - int hdr[2]; - int hlen = sizeof(int) + len; - hdr[0] = htonl(hlen); - hdr[1] = htonl(kind); - if (gSocket->SendRaw(hdr, sizeof(hdr)) < 0) - return -1; - - return gSocket->SendRaw(buf, len); - } - -//////////////////////////////////////////////////////////////////////////////// -/// Send acknowledge code - - int NetSendAck() - { - return NetSend(0, kROOTD_ACK); - } - -//////////////////////////////////////////////////////////////////////////////// -/// Send error code - - int NetSendError(ERootdErrors err) - { - return NetSend(err, kROOTD_ERR); - } - -//////////////////////////////////////////////////////////////////////////////// -/// Send buffer of len bytes. - - int NetSendRaw(const void *buf, int len) - { - return gSocket->SendRaw(buf, len); - } - -//////////////////////////////////////////////////////////////////////////////// -/// Return name of connected host - - void NetGetRemoteHost(std::string &openhost) - { - // Get Host name - openhost = string(gSocket->GetInetAddress().GetHostName()); - } - -//////////////////////////////////////////////////////////////////////////////// -/// return errno - - int GetErrno() - { -#ifdef GLOBAL_ERRNO - return ::errno; -#else - return errno; -#endif - } -//////////////////////////////////////////////////////////////////////////////// -/// reset errno - - void ResetErrno() - { -#ifdef GLOBAL_ERRNO - ::errno = 0; -#else - errno = 0; -#endif - } - -//////////////////////////////////////////////////////////////////////////////// -/// Return in buf the message belonging to errno. - - void Perror(char *buf, int size) - { - int len = strlen(buf); -#if (defined(__sun) && defined (__SVR4)) || defined (__linux) || \ - defined(_AIX) || defined(__MACH__) - snprintf(buf+len, size, " (%s)", strerror(GetErrno())); -#else - if (GetErrno() >= 0 && GetErrno() < sys_nerr) - snprintf(buf+len, size, " (%s)", sys_errlist[GetErrno()]); -#endif - } - -//////////////////////////////////////////////////////////////////////////////// -/// Formats a string in a circular formatting buffer and prints the string. -/// Appends a newline. -/// Cut & Paste from Printf in base/src/TString.cxx - - void ErrorInfo(const char *va_(fmt), ...) - { - char buf[1024]; - va_list ap; - va_start(ap,va_(fmt)); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - printf("%s\n", buf); - fflush(stdout); - } - -//////////////////////////////////////////////////////////////////////////////// -/// Write error message and call a handler, if required - - void Error(ErrorHandler_t func,int code,const char *va_(fmt), ...) - { - char buf[1024]; - va_list ap; - va_start(ap,va_(fmt)); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - printf("%s\n", buf); - fflush(stdout); - - // Actions are defined by the specific error handler ( - // see rootd.cxx) - if (func) (*func)(code,(const char *)buf, sizeof(buf)); - } - -} // namespace ROOT diff --git a/net/rpdutils/src/DaemonUtils.h b/net/rpdutils/src/DaemonUtils.h deleted file mode 100644 index d28622b0f63a8..0000000000000 --- a/net/rpdutils/src/DaemonUtils.h +++ /dev/null @@ -1,53 +0,0 @@ -// @(#)root/auth:$Id$ -// Author: Gerri Ganis 19/1/2004 - -/************************************************************************* - * Copyright (C) 1995-2003, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -#ifndef ROOT_DaemonUtils -#define ROOT_DaemonUtils - - -////////////////////////////////////////////////////////////////////////// -// // -// DaemonUtils // -// // -// This file defines wrappers to client utils calls used by server // -// authentication daemons. // -// // -////////////////////////////////////////////////////////////////////////// - -#include - -#include "TSocket.h" -#include "TSeqCollection.h" -#include "NetErrors.h" -#include "rpddefs.h" - -#include "rpdp.h" - - -extern Int_t SrvAuthImpl(TSocket *socket, const char *, const char *, - std::string &user, Int_t &meth, - Int_t &type, std::string &ctoken, TSeqCollection *); -extern Int_t SrvClupImpl(TSeqCollection *); - -typedef void (*ErrorHandler_t)(int level, const char *msg, int size); - - -namespace ROOT { - -// Error handlers prototypes ... -extern ErrorHandler_t gErrSys; -extern ErrorHandler_t gErrFatal; -extern ErrorHandler_t gErr; -void SrvSetSocket(TSocket *socket); - -} - -#endif diff --git a/net/rpdutils/src/daemon.cxx b/net/rpdutils/src/daemon.cxx deleted file mode 100644 index c64b3d80f7045..0000000000000 --- a/net/rpdutils/src/daemon.cxx +++ /dev/null @@ -1,198 +0,0 @@ -// @(#)root/rpdutils:$Id$ -// Author: Fons Rademakers 11/08/97 -// Modifified: Gerardo Ganis 8/04/2003 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// DaemonStart // -// // -// Detach a daemon process from login session context. // -// // -////////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include -#include -#include - -#if defined(__linux__) && !defined(linux) -# define linux -#endif - -#ifdef SIGTSTP -#include -#include -#include -#endif - -#include - -#ifndef NOFILE -# define NOFILE 0 -#endif - -#if defined(linux) || defined(__hpux) || defined(__sun) || defined(__sgi) || \ - defined(_AIX) || defined(__FreeBSD__) || defined(__OpenBSD__) || \ - defined(__APPLE__) || defined(__MACH__) || \ - (defined(__CYGWIN__) && defined(__GNUC__)) -#define USE_SETSID -#endif - - -#include "rpdp.h" - -extern int gDebug; - -namespace ROOT { - -extern ErrorHandler_t gErrSys; - -//////////////////////////////////////////////////////////////////////////////// - -static void SigChild(int) -{ - int pid; - int status; - - while ((pid = wait3(&status, WNOHANG, 0)) > 0) - ; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Detach a daemon process from login session context. - -void DaemonStart(int ignsigcld, int fdkeep, EService service) -{ - // If we were started by init (process 1) from the /etc/inittab file - // there's no need to detach. - // This test is unreliable due to an unavoidable ambiguity - // if the process is started by some other process and orphaned - // (i.e. if the parent process terminates before we are started). - - int fd; - -#if !(defined(__CYGWIN__) && defined(__GNUC__)) - if (getppid() == 1) { - if (service == kROOTD) printf ("ROOTD_PID=%ld\n", (long) getpid()); - goto out; - } -#endif - - // Ignore the terminal stop signals (BSD). - -#ifdef SIGTTOU - signal(SIGTTOU, SIG_IGN); -#endif -#ifdef SIGTTIN - signal(SIGTTIN, SIG_IGN); -#endif -#ifdef SIGTSTP - signal(SIGTSTP, SIG_IGN); -#endif - - // If we were not started in the background, fork and let the parent - // exit. This also guarantees the first child is not a process - // group leader. - - int childpid; - if ((childpid = fork()) < 0) { - if (service == kROOTD) fprintf(stderr, "DaemonStart: can't fork first child\n"); - Error(gErrSys,kErrFatal, "DaemonStart: can't fork first child"); - } else if (childpid > 0) { -#ifdef SIGTSTP - if (service == kROOTD) printf("ROOTD_PID=%d\n", childpid); -#endif - exit(0); // parent - } else { - if (gDebug > 2) - ErrorInfo("DaemonStart: this is the child thread ... socket is: %d",fdkeep); - } - - // First child process... - - // Disassociate from controlling terminal and process group. - // Ensure the process can't reacquire a new controlling terminal. - -#ifdef SIGTSTP - -#ifdef USE_SETSID - if (setsid() == -1) { -#else - if (setpgrp(0, getpid()) == -1) { -#endif - if (service == kROOTD) - fprintf(stderr, "DaemonStart: can't change process group\n"); - Error(gErrSys,kErrFatal, "DaemonStart: can't change process group"); - } - - if ((fd = open("/dev/tty", O_RDWR)) >= 0) { -#if !defined(__hpux) && !defined(__sun) && \ - !(defined(__CYGWIN__) && defined(__GNUC__)) - ioctl(fd, TIOCNOTTY, 0); // loose controlling tty -#endif - close(fd); - } - -#else - - if (setpgrp() == -1) { - if (service == kROOTD) - fprintf(stderr,"DaemonStart: can't change process group\n"); - Error(gErrSys,kErrFatal, "DaemonStart: can't change process group"); - } - - signal(SIGHUP, SIG_IGN); // immune from pgrp leader death - - if ((childpid = fork()) < 0) { - if (service == kROOTD) - fprintf(stderr, "DaemonStart: can't fork second child\n"); - Error(gErrSys,kErrFatal, "DaemonStart: can't fork second child"); - } else if (childpid > 0) { - if (service == kROOTD) printf("ROOTD_PID=%d (2nd fork)\n", childpid); - exit(0); // first child - } - -#endif -out: - // Close any open file descriptors - for (fd = 0; fd < NOFILE; fd++) { - if ((fd != fdkeep)) close(fd); - } - - ResetErrno(); // probably got set to EBADF from a close - - // Move current directory to root, make sure we aren't on a mounted - // file system. - - if (chdir("/") == -1) - fprintf(stderr, "DaemonStart: cannot chdir to /\n"); - - // Clear any inherited file mode creation mask - - umask(0); - - // See if the caller isn't interested in the exit status of its - // children and doesn't want to have them become zombies and - // clog up the system. - // With SysV all we need to do is ignore the signal. - // With BSD, however, we have to catch each signal - // and execute the wait3() system call. - - if (ignsigcld) { - signal(SIGCHLD, SigChild); - } -} - -} // namespace ROOT - diff --git a/net/rpdutils/src/error.cxx b/net/rpdutils/src/error.cxx deleted file mode 100644 index 92e8f31b3a759..0000000000000 --- a/net/rpdutils/src/error.cxx +++ /dev/null @@ -1,125 +0,0 @@ -// @(#)root/rpdutils:$Id$ -// Author: Fons Rademakers 11/08/97 -// Modifified: Gerardo Ganis 8/04/2003 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// error // -// // -// Set of error handling routines for daemon process. // -// // -////////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include -#include -#include "snprintf.h" - -#if defined(hpux9) -extern "C" { - extern void openlog(const char *, int, int); - extern void syslog(int, const char *, ...); -} -#endif - -#include "rpderr.h" -#include "rpdp.h" - -// This is the only really global -extern int gDebug; - -namespace ROOT { - -extern bool gSysLog; - -//////////////////////////////////////////////////////////////////////////////// - -int GetErrno() -{ - return errno; -} - -//////////////////////////////////////////////////////////////////////////////// - -void ResetErrno() -{ - errno = 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Write info message to syslog. - -void ErrorInfo(const char *va_(fmt), ...) -{ - char buf[kMAXSECBUF]; - va_list ap; - - va_start(ap,va_(fmt)); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - - if (gSysLog) { - syslog(LOG_INFO, "%s\n", buf); - } else { - fprintf(stderr, "%s\n", buf); - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// Open syslog. - -void ErrorInit(const char *ident) -{ - openlog(ident, (LOG_PID | LOG_CONS), LOG_DAEMON); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Return in buf the message belonging to errno. - -void Perror(char *buf, int size) -{ - int len = strlen(buf); -#if (defined(__sun) && defined (__SVR4)) || defined (__linux) || \ - defined(_AIX) || defined(__MACH__) - snprintf(buf+len, size, " (%s)", strerror(GetErrno())); -#else - if (GetErrno() >= 0 && GetErrno() < sys_nerr) - snprintf(buf+len, size, " (%s)", sys_errlist[GetErrno()]); -#endif -} - -//////////////////////////////////////////////////////////////////////////////// -/// Write fatal message to syslog and exit. - -void Error(ErrorHandler_t func, int code, const char *va_(fmt), ...) -{ - char buf[kMAXSECBUF]; - va_list ap; - - va_start(ap,va_(fmt)); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - - if (gSysLog) { - syslog(LOG_ERR, "%s\n", buf); - } else { - fprintf(stderr, "%s\n", buf); - } - - // Actions are defined by the specific error handler function - // (see rootd.cxx) - if (func) (*func)(code,(const char *)buf, sizeof(buf)); -} - -} // namespace ROOT diff --git a/net/rpdutils/src/net.cxx b/net/rpdutils/src/net.cxx deleted file mode 100644 index 02f4c43b939a4..0000000000000 --- a/net/rpdutils/src/net.cxx +++ /dev/null @@ -1,586 +0,0 @@ -// @(#)root/rpdutils:$Id$ -// Author: Fons Rademakers 12/08/97 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// net // -// // -// Set of network routines for rootd daemon process. // -// // -////////////////////////////////////////////////////////////////////////// - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rpdp.h" -#include "rpderr.h" - -extern int gDebug; - -namespace ROOT { - -extern std::string gServName[3]; - -extern ErrorHandler_t gErrSys; -extern ErrorHandler_t gErrFatal; - -static double gBytesSent = 0; -static double gBytesRecv = 0; - -static std::string gOpenhost = "????"; - -static int gTcpSrvSock; -static struct sockaddr_in gTcpSrvAddr; -static struct sockaddr_in gTcpCliAddr; - -static int gSockFd = -1; -static SigPipe_t gSigPipeHook = 0; -extern int gParallel; - -//////////////////////////////////////////////////////////////////////////////// -/// return received bytes - -double NetGetBytesRecv() -{ - return gBytesRecv; -} - -//////////////////////////////////////////////////////////////////////////////// -/// return sent bytes - -double NetGetBytesSent() -{ - return gBytesSent; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Return name of connected host - -void NetGetRemoteHost(std::string &OpenHost) -{ - OpenHost = gOpenhost; -} - -//////////////////////////////////////////////////////////////////////////////// -/// return open socket descriptor - -int NetGetSockFd() -{ - return gSockFd; -} - -//////////////////////////////////////////////////////////////////////////////// -/// reset byte counts - -void NetResetByteCount() -{ - gBytesRecv = 0; - gBytesSent = 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Set hook for SIGPIPE calls - -void NetSetSigPipeHook(SigPipe_t Hook) -{ - gSigPipeHook = Hook; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Send exactly length bytes from buffer. - -static int Sendn(int sock, const void *buffer, int length) -{ - if (sock < 0) return -1; - - int n, nsent = 0; - const char *buf = (const char *)buffer; - - for (n = 0; n < length; n += nsent) { - if ((nsent = send(sock, buf+n, length-n, 0)) <= 0) { - Error(gErrFatal, -1, "Sendn: error (sock: %d): errno: %d", - sock, GetErrno()); - return nsent; - } - } - - gBytesSent += n; - - return n; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Receive exactly length bytes into buffer. Returns number of bytes -/// received or 0 in case connection is closed. Returns -1 in case of error. - -static int Recvn(int sock, void *buffer, int length) -{ - if (sock < 0) return -1; - - int n, nrecv = 0; - char *buf = (char *)buffer; - - for (n = 0; n < length; n += nrecv) { - while ((nrecv = recv(sock, buf+n, length-n, 0)) == -1 && GetErrno() == EINTR) - ResetErrno(); // probably a SIGCLD that was caught - if (nrecv == 0) - break; // EOF - if (nrecv < 0) { - Error(gErrFatal,-1,"Recvn: error (sock: %d): errno: %d",sock,GetErrno()); - return nrecv; - } - } - - gBytesRecv += n; - - return n; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Send buffer of len bytes. - -int NetSendRaw(const void *buf, int len) -{ - if (gParallel > 0) { - - if (NetParSend(buf, len) != len) { - Error(gErrFatal,-1,"NetSendRaw: NetParSend error"); - } - - } else { - - if (gSockFd == -1 || !buf) return -1; - if (Sendn(gSockFd, buf, len) != len) { - Error(gErrFatal,-1,"NetSendRaw: Sendn error"); - } - } - - return len; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Receive a buffer of maximum len bytes. - -int NetRecvRaw(void *buf, int len) -{ - if (gParallel > 0) { - - if (NetParRecv(buf, len) != len) { - Error(gErrFatal,-1,"NetRecvRaw: NetParRecv error"); - } - - } else { - - if (gSockFd == -1) return -1; - if (Recvn(gSockFd, buf, len) < 0) { - Error(gErrFatal,-1,"NetRecvRaw: Recvn error (gSockFd: %d)",gSockFd); - } - } - - return len; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Receive a buffer of maximum len bytes from generic socket sock. - -int NetRecvRaw(int sock, void *buf, int len) -{ - if (sock == -1) return -1; - - if (Recvn(sock, buf, len) < 0) { - Error(gErrFatal,-1,"NetRecvRaw: Recvn error (sock: %d, errno: %d)",sock,GetErrno()); - } - - return len; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Send buffer of len bytes. Message will be of type "kind". - -int NetSend(const void *buf, int len, EMessageTypes kind) -{ - int hdr[2]; - int hlen = sizeof(int) + len; - hdr[0] = htonl(hlen); - hdr[1] = htonl(kind); - if (NetSendRaw(hdr, sizeof(hdr)) < 0) - return -1; - - return NetSendRaw(buf, len); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Send integer. Message will be of type "kind". - -int NetSend(int code, EMessageTypes kind) -{ - int hdr[3]; - int hlen = sizeof(int) + sizeof(int); - hdr[0] = htonl(hlen); - hdr[1] = htonl(kind); - hdr[2] = htonl(code); - return NetSendRaw(hdr, sizeof(hdr)); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Send a string. Message will be of type "kind". - -int NetSend(const char *msg, EMessageTypes kind) -{ - int len = 0; - - if (msg) - len = strlen(msg)+1; - - return NetSend(msg, len, kind); -} - -//////////////////////////////////////////////////////////////////////////////// - -int NetSendAck() -{ - return NetSend(0, kROOTD_ACK); -} - -//////////////////////////////////////////////////////////////////////////////// - -int NetSendError(ERootdErrors err) -{ - return NetSend(err, kROOTD_ERR); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Receive a buffer. Returns the newly allocated buffer, the length -/// of the buffer and message type in kind. - -int NetRecvAllocate(void *&buf, int &len, EMessageTypes &kind) -{ - int hdr[2] = { 0, 0 }; - - if (NetRecvRaw(hdr, sizeof(hdr)) < 0) - return -1; - - len = ntohl(hdr[0]) - sizeof(int); - if (len < 0) len = 0; - kind = (EMessageTypes) ntohl(hdr[1]); - if (len) { - buf = new char* [len]; - return NetRecvRaw(buf, len); - } - buf = 0; - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Receive a string of maximum len length. Returns message type in kind. -/// Return value is msg length. - -int NetRecv(char *msg, int len, EMessageTypes &kind) -{ - int mlen = 0; - void *tmpbuf = nullptr; - - int res = NetRecvAllocate(tmpbuf, mlen, kind); - char *buf = static_cast(tmpbuf); - - if (res < 0) { - delete [] buf; - return -1; - } - - if (mlen == 0) { - msg[0] = 0; - delete [] buf; - return 0; - } else if (mlen > len-1) { - strncpy(msg, buf, len-1); - msg[len-1] = 0; - mlen = len; - } else { - strncpy(msg, buf, mlen); - msg[mlen] = 0; - } - - delete [] buf; - - return mlen - 1; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Simulate TSocket::Recv(char *str, int max). - -int NetRecv(char *msg, int max) -{ - EMessageTypes kind; - - return NetRecv((char *)msg, max, kind); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Initialize the server's end. -/// We are passed a flag that says whether or not we are started -/// by a "master daemon" such as inetd. A master daemon will have -/// already waited for a message to arrive for us and will have -/// already set up the connection to the client. If we weren't -/// started by a master daemon, then we must wait for a client's -/// request to arrive. - -int NetOpen(int inetdflag, EService service) -{ - socklen_t clilen = sizeof(gTcpCliAddr); - - if (inetdflag) { - - // When we're fired up by inetd, file decriptors 0, 1 and 2 - // are sockets to the client. - - gSockFd = 0; - if (!getpeername(gSockFd, (struct sockaddr *)&gTcpCliAddr, &clilen)) { - struct hostent *hp; - if ((hp = gethostbyaddr((const char *)&gTcpCliAddr.sin_addr, - sizeof(gTcpCliAddr.sin_addr), AF_INET))) - gOpenhost = std::string(hp->h_name); - else { - struct in_addr *host_addr = (struct in_addr*)&gTcpCliAddr.sin_addr; - gOpenhost = std::string(inet_ntoa(*host_addr)); - } - } - - // Notify, if requested ... - if (gDebug > 1) - ErrorInfo("NetOpen: fired by inetd: connection from host %s" - " via socket %d", gOpenhost.data(),gSockFd); - - // Set several general performance network options - NetSetOptions(service,gSockFd, 65535); - - return 0; - } - - // For the concurrent server that's not initiated by inetd, - // we have to wait for a connection request to arrive, then - // fork a child to handle the client's request. - // Beware that the accept() can be interrupted, such as by - // a previously spawned child process that has terminated - // (for which we caught the SIGCLD signal). - -again: - int newsock = accept(gTcpSrvSock, (struct sockaddr *)&gTcpCliAddr, &clilen); - if (newsock < 0) { - if (GetErrno() == EINTR) { - ResetErrno(); - goto again; // probably a SIGCLD that was caught - } - Error(gErrSys,kErrFatal, "NetOpen: accept error (errno: %d) ... socket %d", - GetErrno(),gTcpSrvSock); - return 0; - } - - struct hostent *hp; - if ((hp = gethostbyaddr((const char *)&gTcpCliAddr.sin_addr, - sizeof(gTcpCliAddr.sin_addr), AF_INET))) - gOpenhost = std::string(hp->h_name); - else { - struct in_addr *host_addr = (struct in_addr*)&gTcpCliAddr.sin_addr; - gOpenhost = std::string(inet_ntoa(*host_addr)); - } - - // Fork a child process to handle the client's request. - // The parent returns the child pid to the caller, which is - // probably a concurrent server that'll call us again, to wait - // for the next client request to this well-known port. - - int childpid; - if ((childpid = fork()) < 0) - Error(gErrSys,kErrFatal, "NetOpen: server can't fork"); - else if (childpid > 0) { // parent - close(newsock); - return childpid; - } - - // Child process continues here. - // First close the original socket so that the parent - // can accept any further requests that arrive there. - // Then set "gSockFd" in our process to be the descriptor - // that we are going to process. - - close(gTcpSrvSock); - - gSockFd = newsock; - - // Notify, if requested ... - if (gDebug > 1) - ErrorInfo("NetOpen: concurrent server: connection from host %s" - " via socket %d", gOpenhost.data(), gSockFd); - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Close the network connection. - -void NetClose() -{ - if (gParallel > 0) { - - NetParClose(); - - } else { - - close(gSockFd); - if (gDebug > 0) - ErrorInfo("NetClose: host = %s, fd = %d", - gOpenhost.data(), gSockFd); - gSockFd = -1; - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// Initialize the network connection for the server, when it has *not* -/// been invoked by inetd. Used by rootd. - -int NetInit(EService servtype, int port1, int port2, int tcpwindowsize) -{ - // We weren't started by a master daemon. - // We have to create a socket ourselves and bind our well-known - // address to it. - - std::string service = gServName[servtype]; - - if (port1 <= 0) { - if (service.length()) { - struct servent *sp = getservbyname(service.data(), "tcp"); - if (!sp) { - if (servtype == kROOTD) { - port1 = 1094; - } else { - fprintf(stderr,"NetInit: unknown service: %s/tcp\n", service.data()); - Error(gErrFatal, kErrFatal, - "NetInit: unknown service: %s/tcp", service.data()); - } - } else { - port1 = ntohs(sp->s_port); - } - port2 += port1; // in this case, port2 is relative to service port - } else { - fprintf(stderr, "NetInit: must specify either service or port\n"); - Error(gErrFatal,kErrFatal, - "NetInit: must specify either service or port"); - } - } - - // Create the socket and bind our local address so that any client can - // send to us. - - if ((gTcpSrvSock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - fprintf(stderr, "NetInit: can't create socket\n"); - Error(gErrSys,kErrFatal, "NetInit: can't create socket"); - return gTcpSrvSock; - } - - int val = 1; - if (setsockopt(gTcpSrvSock, SOL_SOCKET, SO_REUSEADDR, (char*) &val, - sizeof(val)) == -1) { - fprintf(stderr, "NetInit: can't set SO_REUSEADDR socket option\n"); - Error(gErrSys, kErrFatal, "NetInit: can't set SO_REUSEADDR socket option"); - } - - // Set several general performance network options - NetSetOptions(kROOTD,gTcpSrvSock, tcpwindowsize); - - memset(&gTcpSrvAddr, 0, sizeof(gTcpSrvAddr)); - gTcpSrvAddr.sin_family = AF_INET; - gTcpSrvAddr.sin_addr.s_addr = htonl(INADDR_ANY); - - int port; - for (port= port1; port <= port2; port++) { - gTcpSrvAddr.sin_port = htons(port); - if (bind(gTcpSrvSock, (struct sockaddr *) &gTcpSrvAddr, - sizeof(gTcpSrvAddr)) == 0) break; - } - - if (port > port2) { - fprintf(stderr, "NetInit: can't bind local address to ports %d-%d\n", port1, port2); - Error(gErrSys, kErrFatal, "NetInit: can't bind local address to ports %d-%d", port1, port2); - } - - printf("ROOTD_PORT=%d\n", port); - port1 = port; - - // And set the listen parameter, telling the system that we're - // ready to accept incoming connection requests. - - // listen(gTcpSrvSock, 5); - if (listen(gTcpSrvSock, 5)==-1) { - ErrorInfo("NetInit: listen: error (errno: %d)",GetErrno()); - } - - if (gDebug > 0) - ErrorInfo("NetInit: socket %d listening on port %d", gTcpSrvSock, - ntohs(gTcpSrvAddr.sin_port)); - - return gTcpSrvSock; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Set some options for network socket. - -void NetSetOptions(EService serv, int sock, int tcpwindowsize) -{ - int val = 1; - - if (serv == kROOTD) { - if (!setsockopt(sock,IPPROTO_TCP,TCP_NODELAY,(char *)&val,sizeof(val))) - if (gDebug > 0) - ErrorInfo("NetSetOptions: set TCP_NODELAY"); - if (!setsockopt(sock,SOL_SOCKET,SO_KEEPALIVE,(char *)&val,sizeof(val))) { - if (gDebug > 0) - ErrorInfo("NetSetOptions: set SO_KEEPALIVE"); - if (gSigPipeHook != 0) - signal(SIGPIPE, (*gSigPipeHook)); // handle SO_KEEPALIVE failure - } - } - - val = tcpwindowsize; - if (!setsockopt(sock,SOL_SOCKET,SO_SNDBUF,(char *)&val,sizeof(val))) - if (gDebug > 0) - ErrorInfo("NetSetOptions: set SO_SNDBUF %d", val); - if (!setsockopt(sock,SOL_SOCKET,SO_RCVBUF,(char *)&val,sizeof(val))) - if (gDebug > 0) - ErrorInfo("NetSetOptions: set SO_RCVBUF %d", val); - - if (gDebug > 0) { - socklen_t optlen = sizeof(val); - if (serv == kROOTD) { - getsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&val, &optlen); - ErrorInfo("NetSetOptions: get TCP_NODELAY: %d", val); - getsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, &optlen); - ErrorInfo("NetSetOptions: get SO_KEEPALIVE: %d", val); - } - getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&val, &optlen); - ErrorInfo("NetSetOptions: get SO_SNDBUF: %d", val); - getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&val, &optlen); - ErrorInfo("NetSetOptions: get SO_RCVBUF: %d", val); - } -} - -} // namespace ROOT diff --git a/net/rpdutils/src/netpar.cxx b/net/rpdutils/src/netpar.cxx deleted file mode 100644 index 465bcdf797972..0000000000000 --- a/net/rpdutils/src/netpar.cxx +++ /dev/null @@ -1,264 +0,0 @@ -// @(#)root/rpdutils:$Id$ -// Author: Fons Rademakers 06/02/2001 - -/************************************************************************* - * Copyright (C) 1995-2001, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// netpar // -// // -// Set of parallel network routines for rootd daemon process. To be // -// used when remote uses TPSocket to connect to rootd. // -// // -////////////////////////////////////////////////////////////////////////// - -#include - -// avoid warning due to wrong bzero prototype (used by FD_ZERO macro) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(_AIX) -#include -#endif - -#include "rpdp.h" - -extern int gDebug; - -namespace ROOT { - -extern ErrorHandler_t gErrSys; - -int gParallel = 0; - -static int gMaxFd; -static int *gPSockFd; -static int *gWriteBytesLeft; -static int *gReadBytesLeft; -static char **gWritePtr; -static char **gReadPtr; -static fd_set gFdSet; - -//////////////////////////////////////////////////////////////////////////////// -/// Setup select masks. - -static void InitSelect(int nsock) -{ - FD_ZERO(&gFdSet); - gMaxFd = -1; - for (int i = 0; i < nsock; i++) { - FD_SET(gPSockFd[i], &gFdSet); - if (gPSockFd[i] > gMaxFd) - gMaxFd = gPSockFd[i]; - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// Send buffer of specified length over the parallel sockets. -/// Returns len in case of success and -1 in case of error. - -int NetParSend(const void *buf, int len) -{ - int i, alen = len, nsock = gParallel; - - if (!buf) return -1; - - // If data buffer is < 4K use only one socket - if (len < 4096) - nsock = 1; - - for (i = 0; i < nsock; i++) { - gWriteBytesLeft[i] = len/nsock; - gWritePtr[i] = (char *)buf + (i*gWriteBytesLeft[i]); - } - gWriteBytesLeft[i-1] += len%nsock; - - InitSelect(nsock); - - // Send the data on the parallel sockets - while (len > 0) { - - fd_set writeReady = gFdSet; - - int isel = select(gMaxFd+1, 0, &writeReady, 0, 0); - if (isel < 0) { - ErrorInfo("NetParSend: error on select"); - return -1; - } - - for (i = 0; i < nsock; i++) { - if (FD_ISSET(gPSockFd[i], &writeReady)) { - if (gWriteBytesLeft[i] > 0) { - int ilen; -again: - ilen = send(gPSockFd[i], gWritePtr[i], gWriteBytesLeft[i], 0); - if (ilen < 0) { - if (GetErrno() == EAGAIN) - goto again; - ErrorInfo("NetParSend: error sending for socket %d (%d)", - i, gPSockFd[i]); - return -1; - } - gWriteBytesLeft[i] -= ilen; - gWritePtr[i] += ilen; - len -= ilen; - } - } - } - } - - return alen; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Receive buffer of specified length over parallel sockets. -/// Returns len in case of success and -1 in case of error. - -int NetParRecv(void *buf, int len) -{ - int i, alen = len, nsock = gParallel; - - // If data buffer is < 4K use only one socket - if (len < 4096) - nsock = 1; - - for (i = 0; i < nsock; i++) { - gReadBytesLeft[i] = len/nsock; - gReadPtr[i] = (char *)buf + (i*gReadBytesLeft[i]); - } - gReadBytesLeft[i-1] += len%nsock; - - InitSelect(nsock); - - // Recieve the data on the parallel sockets - while (len > 0) { - - fd_set readReady = gFdSet; - - int isel = select(gMaxFd+1, &readReady, 0, 0, 0); - if (isel < 0) { - ErrorInfo("NetParRecv: error on select"); - return -1; - } - - for (i = 0; i < nsock; i++) { - if (FD_ISSET(gPSockFd[i], &readReady)) { - if (gReadBytesLeft[i] > 0) { - int ilen = recv(gPSockFd[i], gReadPtr[i], gReadBytesLeft[i], 0); - if (ilen < 0) { - ErrorInfo("NetParRecv: error receiving for socket %d (%d)", - i, gPSockFd[i]); - return -1; - } else if (ilen == 0) { - ErrorInfo("NetParRecv: EOF on socket %d (%d)", - i, gPSockFd[i]); - return 0; - } - gReadBytesLeft[i] -= ilen; - gReadPtr[i] += ilen; - len -= ilen; - } - } - } - } - - return alen; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Open size parallel sockets back to client. Returns 0 in case of error, -/// and number of parallel sockets in case of success. - -int NetParOpen(int port, int size) -{ - struct sockaddr_in remote_addr; - memset(&remote_addr, 0, sizeof(remote_addr)); - - socklen_t remlen = sizeof(remote_addr); - - if (!getpeername(NetGetSockFd(), (struct sockaddr *)&remote_addr, &remlen)) { - remote_addr.sin_family = AF_INET; - remote_addr.sin_port = htons(port); - - gPSockFd = new int[size]; - - for (int i = 0; i < size; i++) { - if ((gPSockFd[i] = socket(AF_INET, SOCK_STREAM, 0)) < 0) - Error(gErrSys, kErrFatal, "NetParOpen: can't create socket %d (%d)", - i, gPSockFd[i]); - - NetSetOptions(kROOTD, gPSockFd[i], 65535); - - if (connect(gPSockFd[i], (struct sockaddr *)&remote_addr, remlen) < 0) - Error(gErrSys, kErrFatal, "NetParOpen: can't connect socket %d (%d)", - i, gPSockFd[i]); - - // Set non-blocking - int val; - if ((val = fcntl(gPSockFd[i], F_GETFL, 0)) < 0) - Error(gErrSys, kErrFatal, "NetParOpen: can't get control flags"); - val |= O_NONBLOCK; - if (fcntl(gPSockFd[i], F_SETFL, val) < 0) - Error(gErrSys, kErrFatal, "NetParOpen: can't make socket non blocking"); - } - - gWriteBytesLeft = new int[size]; - gReadBytesLeft = new int[size]; - gWritePtr = new char*[size]; - gReadPtr = new char*[size]; - - // Close initial setup socket - NetClose(); - - gParallel = size; - - if (gDebug > 0) - ErrorInfo("NetParOpen: %d parallel connections established", size); - - } else - Error(gErrSys, kErrFatal, "NetParOpen: can't get peer name"); - - return gParallel; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Close parallel sockets. - -void NetParClose() -{ - for (int i = 0; i < gParallel; i++) - close(gPSockFd[i]); - - if (gDebug > 0) { - std::string host; - NetGetRemoteHost(host); - ErrorInfo("NetParClose: closing %d-stream connection to host %s", - gParallel, host.data()); - } - - delete [] gPSockFd; - delete [] gWriteBytesLeft; - delete [] gReadBytesLeft; - delete [] gWritePtr; - delete [] gReadPtr; - - gParallel = 0; -} - -} // namespace ROOT diff --git a/net/rpdutils/src/rpdconn.cxx b/net/rpdutils/src/rpdconn.cxx deleted file mode 100644 index 0eb8b9e85f63a..0000000000000 --- a/net/rpdutils/src/rpdconn.cxx +++ /dev/null @@ -1,1094 +0,0 @@ -// @(#)root/rpdutils:$Id$ -// Author: Gerardo Ganis, March 2011 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// rpdconn // -// // -// This header file contains the definition of some utility classes // -// used for process communication between rootd. // -// // -////////////////////////////////////////////////////////////////////////// - -#include "rpdconn.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define RPD_MAXLEN 8192 - -// -// Control meaning of the msghdr structure -// -#if defined(__sun) -#define HAVE_MSGHDR_ACCRIGHT -#endif - -// -// To make socklen_t portable use SOCKLEN_t -// -#if defined(__solaris__) && !defined(__linux__) -# if __GNUC__ >= 3 || __GNUC_MINOR__ >= 90 -# define XR__SUNGCC3 -# endif -#endif -#if defined(__linux__) -# include -# if __GNU_LIBRARY__ == 6 -# ifndef XR__GLIBC -# define XR__GLIBC -# endif -# endif -#endif -#if defined(__MACH__) && defined(__i386__) -# define R__GLIBC -#endif -#if defined(_AIX) || (defined(XR__SUNGCC3) && !defined(__arch64__)) -# define SOCKLEN_t size_t -#elif defined(XR__GLIBC) || defined(__FreeBSD__) || \ - (defined(XR__SUNGCC3) && defined(__arch64__)) || defined(__APPLE__) || \ - (defined(__sun) && defined(_SOCKLEN_T)) -# ifndef SOCKLEN_t -# define SOCKLEN_t socklen_t -# endif -#elif !defined(SOCKLEN_t) -# define SOCKLEN_t int -#endif - -// -// Class describing a basic connection -// - -//////////////////////////////////////////////////////////////////////////////// -/// Constructor - -rpdconn::rpdconn(int r, int w) : rdfd(r), wrfd(w) -{ - int rc = 0; - pthread_mutexattr_t attr; - if (!(rc = pthread_mutexattr_init(&attr))) { - if (!(rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE))) { - pthread_mutex_init(&wrmtx, &attr); - pthread_mutex_init(&rdmtx, &attr); - } - } - pthread_mutexattr_destroy(&attr); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Send an integer -/// Return: -/// 0 if OK -/// -1 if invalid descriptor -/// -2 if failed to acquire mutex lock - -int rpdconn::send(int i) -{ - rpdmtxhelper mh(&wrmtx); - if (isvalid(0)) { - if (mh.isok()) { - // Send the integer - i = htonl(i); - if (write(wrfd, &i, sizeof(i)) != sizeof(i)) - return -errno; - // Done - return 0; - } - // Could acquire the mutex lock - return -2; - } - // Invalid descriptor - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Send a typed message -/// Return: -/// 0 if OK -/// -1 if invalid descriptor -/// -2 if failed to acquire mutex lock - -int rpdconn::send(int type, const char *msg) -{ - rpdmtxhelper mh(&wrmtx); - if (isvalid(0)) { - if (mh.isok()) { - // Send the type - type = htonl(type); - if (write(wrfd, &type, sizeof(type)) != sizeof(type)) - return -errno; - // Send the message, if any - int len = (msg) ? strlen(msg) : 0; - int mlen = len; - // Send the length - len = htonl(len); - if (write(wrfd, &len, sizeof(len)) != sizeof(len)) - return -errno; - if (msg && mlen > 0) - if (write(wrfd, msg, mlen) != mlen) - return -errno; - // Done - return 0; - } - // Could acquire the mutex lock - return -2; - } - // Invalid descriptor - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Send message -/// Return: -/// 0 if OK -/// -1 if invalid descriptor -/// -2 if failed to acquire mutex lock - -int rpdconn::send(const rpdmsg &msg) -{ - return send(msg.type, msg.buf.c_str()); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Send 'len' bytes at 'buf' -/// Return: -/// 0 if OK -/// -1 if invalid descriptor -/// -2 if failed to acquire mutex lock -/// -3 if the operation would block -/// -4 if connection broken -/// -errno if any another failure - -int rpdconn::send(const void *buf, int len) -{ - rpdmtxhelper mh(&wrmtx); - if (isvalid(0)) { - if (mh.isok()) { - // Send the buffer - int n, nsnt = 0; - const char *b = (const char *)buf; - for (n = 0; n < len; n += nsnt) { - errno = 0; - if ((nsnt = ::send(wrfd, b+n, len-n, 0)) <= 0) { - if (nsnt == 0) break; - if (errno != EINTR) { - if (errno == EPIPE || errno == ECONNRESET) - return -4; - else if (errno == EWOULDBLOCK) - return -3; - else - return -errno; - } - } - } - // Done - return 0; - } - // Could acquire the mutex lock - return -2; - } - // Invalid descriptor - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Receive an integer -/// Return: -/// 0 if OK -/// -1 if invalid descriptor -/// -2 if failed to acquire mutex lock - -int rpdconn::recv(int &i) -{ - rpdmtxhelper mh(&rdmtx); - if (isvalid(1)) { - if (mh.isok()) { - // Read the integer - if (read(rdfd, &i, sizeof(i)) != sizeof(i)) - return -errno; - i = ntohl(i); - // Done - return 0; - } - // Could acquire the mutex lock - return -2; - } - // Invalid descriptor - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Receive a typed message -/// Return: -/// 0 if OK -/// -1 if invalid descriptor -/// -2 if failed to acquire mutex lock -/// -3 if failed to receive the full message (the partial message -/// is stored in 'msg') - -int rpdconn::recv(int &type, std::string &msg) -{ - rpdmtxhelper mh(&rdmtx); - if (isvalid(1)) { - if (mh.isok()) { - // Read message type - if (read(rdfd, &type, sizeof(type)) != sizeof(type)) - return -errno; - type = ntohl(type); - // Read message len - int len = 0; - if (read(rdfd, &len, sizeof(len)) != sizeof(len)) - return -errno; - len = ntohl(len); - int rc = 0; - if (len > 0) { - msg = ""; - // Read message - char buf[RPD_MAXLEN]; - int nr = -1; - do { - int wanted = (len > RPD_MAXLEN-1) ? RPD_MAXLEN-1 : len; - while ((nr = read(rdfd, buf, wanted)) < 0 && - errno == EINTR) - errno = 0; - if (nr < wanted) { - if (nr < 0) rc = -3; - break; - } else { - buf[nr] = '\0'; - msg += buf; - } - // Update counters - len -= nr; - } while (nr > 0 && len > 0); - - } - // Done - return rc; - } - // Could acquire the mutex lock - return -2; - } - // Invalid descriptor - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Recv message -/// Return: -/// 0 if OK -/// -1 if invalid descriptor -/// -2 if failed to acquire mutex lock - -int rpdconn::recv(rpdmsg &msg) -{ - return recv(msg.type, msg.buf); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Receive 'len' bytes at 'buf' -/// Return: -/// 0 if OK -/// -1 if invalid descriptor -/// -2 if failed to acquire mutex lock -/// -3 if the operation would block -/// -4 if connection broken -/// -errno if any another failure - -int rpdconn::recv(void *buf, int len) -{ - rpdmtxhelper mh(&rdmtx); - if (isvalid(1)) { - if (mh.isok()) { - int n, nrcv = 0; - char *b = (char *)buf; - for (n = 0; n < len; n += nrcv) { - errno = 0; - if ((nrcv = ::recv(rdfd, b+n, len-n, 0)) <= 0) { - if (nrcv == 0) break; // EOF - if (errno != EINTR) { - if (errno == EPIPE || errno == ECONNRESET) - return -4; - else if (errno == EWOULDBLOCK) - return -3; - else - return -errno; - } - } - } - // Done - return 0; - } - // Could acquire the mutex lock - return -2; - } - // Invalid descriptor - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Poll over the read descriptor for to secs; -/// Return: -/// >0 ready to poll -/// 0 timeout -/// -1 invalid descriptor -/// <-1 -errno from 'poll' - -int rpdconn::pollrd(int to) -{ - if (isvalid(1)) { - - // Read descriptor - struct pollfd fds_r; - fds_r.fd = rdfd; - fds_r.events = POLLIN; - - // We wait for processes to communicate a session status change - int pollrc = 0; - int xto = (to > 0) ? to * 1000 : -1; - while ((pollrc = poll(&fds_r, 1, xto)) < 0 && (errno == EINTR)) { - errno = 0; - } - // Done - return (pollrc >= 0) ? pollrc : -errno; - } - // Invalid pipe - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Send a descriptor to a the connected peer -/// Return: -/// 0 if OK -/// -1 if invalid -/// -2 if failed to acquire mutex lock -/// <-2 -errno from sendmsg - -int rpdconn::senddesc(int desc) -{ - rpdmtxhelper mh(&wrmtx); - if (isvalid(0)) { - if (mh.isok()) { - // Create the structure - struct msghdr msg; - memset(&msg, 0, sizeof(msg)); - // Set the descriptor pointers -#ifndef HAVE_MSGHDR_ACCRIGHT - struct cmsghdr *cmsg; - int myfds[1] = {desc}; // Contains the file descriptor to pass -#ifdef R__MACOSX - char buf[sizeof(struct cmsghdr) + sizeof (myfds)]; -#else - char buf[CMSG_SPACE(sizeof myfds)]; // ancillary data buffer -#endif - int *fdptr = 0; - msg.msg_control = buf; - msg.msg_controllen = sizeof buf; - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - // Initialize the payload: - fdptr = (int *) CMSG_DATA(cmsg); - memcpy(fdptr, myfds, sizeof(int)); - // Sum of the length of all control messages in the buffer - msg.msg_controllen = cmsg->cmsg_len; -#else - msg.msg_accrights = (caddr_t) &desc; - msg.msg_accrightslen = sizeof(desc); -#endif - struct iovec iov[1]; - memset(iov, 0, sizeof(iov)); - // The recvmsg() call will NOT block unless a non-zero length data - // buffer is specified - char c = '\0'; - iov[0].iov_base = &c; - iov[0].iov_len = 1; - msg.msg_iov = iov; - msg.msg_iovlen = 1; - // Send it over - if (sendmsg(wrfd, &msg, 0) < 0) - return -errno; - // We can close the descriptor in this process - ::close(desc); - // Done - return 0; - } - // Could acquire the mutex lock - return -2; - } - // Invalid descriptor - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Receive a descriptor from a the connected peer -/// Return: -/// 0 if OK -/// -1 if invalid -/// -2 if failed to acquire mutex lock -/// <-2 -errno from recvmsg - -int rpdconn::recvdesc(int &desc) -{ - rpdmtxhelper mh(&rdmtx); - if (isvalid(1)) { - if (mh.isok()) { - // Create the structures and initialize them - struct msghdr msg; - memset(&msg, 0, sizeof(msg)); -#ifndef HAVE_MSGHDR_ACCRIGHT - union { - struct cmsghdr cm; -#ifdef R__MACOSX - char control[sizeof(struct cmsghdr) + sizeof (int)]; -#else - char control[CMSG_SPACE(sizeof (int))]; -#endif - } control_un; - struct cmsghdr *cmptr; - - msg.msg_control = control_un.control; - msg.msg_controllen = sizeof(control_un.control); -#else - int tmpdesc = 0; - msg.msg_accrights = (caddr_t) &tmpdesc; - msg.msg_accrightslen = sizeof(tmpdesc); -#endif - struct iovec iov[1]; - memset(iov, 0, sizeof(iov)); - // The recvmsg() call will NOT block unless a non-zero length data - // buffer is specified - char c; - iov[0].iov_base = &c; - iov[0].iov_len = 1; - msg.msg_iov = iov; - msg.msg_iovlen = 1; - // Receive it - if (recvmsg(rdfd, &msg, 0) < 0) - return -errno; -#ifndef HAVE_MSGHDR_ACCRIGHT - if ((cmptr = CMSG_FIRSTHDR(&msg)) != 0 && - cmptr->cmsg_len == CMSG_LEN(sizeof(int))) { - if (cmptr->cmsg_level != SOL_SOCKET) - return -errno; - if (cmptr->cmsg_type != SCM_RIGHTS) - return -errno; - memcpy((void *)&desc, CMSG_DATA(cmptr), sizeof(int)); - } else - desc = -1; // descriptor was not passed -#else - if (msg.msg_accrightslen == sizeof(int)) - desc = tmpdesc; - else - desc = -1; // descriptor was not passed -#endif - // Done - return 0; - } - // Could acquire the mutex lock - return -2; - } - // Invalid descriptor - return -1; -} - -// -// Class describing a UNIX connection -// - -//////////////////////////////////////////////////////////////////////////////// -/// Constructor - -rpdtcp::rpdtcp(const char *h, int p) : rpdconn(), host(h), port(p), fd(-1) -{ - struct hostent *hent = 0; - if (!(hent = gethostbyname(h))) { - fprintf(stderr, "rpdtcp::rpdtcp: ERROR: failure resolving host address (errno: %d)\n", errno); - return; - } - memset(&addr, 0, sizeof(addr)); - - // The structure - struct sockaddr_in server; - memset(&server, 0, sizeof(server)); - server.sin_family = hent->h_addrtype; - memcpy((char *) &server.sin_addr.s_addr, hent->h_addr_list[0], hent->h_length); - server.sin_port = htons(port); - - // Open socket - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - fprintf(stderr, "rpdtcp::rpdtcp: ERROR: failure getting socket descriptor (errno: %d)\n", errno); - return; - } - - // Connect - errno = 0; - while (connect(fd, (struct sockaddr*) &server, sizeof(server)) == -1) { - if (errno == EINTR) { - errno = 0; - } else { - fprintf(stderr, "rpdtcp::rpdtcp: ERROR: failure while connecting to '%s:%d' (errno: %d)\n", - h, p, errno); - ::close(fd); - return; - } - } - - // Set descriptors - setdescriptors(fd, fd); - - // Done - return; -} - -// -// Class describing a server TCP connection -// - -//////////////////////////////////////////////////////////////////////////////// -/// Constructor - -rpdtcpsrv::rpdtcpsrv(int p, int backlog) : rpdtcp(p) -{ - // The structure - struct sockaddr_in inserver; - memset(&inserver, 0, sizeof(inserver)); - inserver.sin_family = AF_INET; - inserver.sin_addr.s_addr = htonl(INADDR_ANY); - inserver.sin_port = htons(p); - - // Open socket - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - fprintf(stderr, "rpdtcpsrv::rpdtcpsrv: ERROR: failure getting socket descriptor (errno: %d)\n", errno); - return; - } - - if (bind(fd, (struct sockaddr*) &inserver, sizeof(inserver))) { - fprintf(stderr, "rpdtcpsrv::rpdtcpsrv: ERROR: failure binding socket (errno: %d)\n", errno); - ::close(fd); - fd = -1; - return; - } - - // Start accepting connections - if (listen(fd, backlog)) { - fprintf(stderr, "rpdtcpsrv::rpdtcpsrv: ERROR: failure enabling listening on socket (errno: %d)\n", errno); - ::close(fd); - fd = -1; - return; - } - - // Set descriptors - setdescriptors(fd, fd); - - // Done - return; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Accept a connection on the server socket. -/// If to > 0, wait max to secs (granularity 1 sec). -/// Return a rpdtcp object describing the open connection (to be destroyed -/// by the caller). -/// On error return a NULL pointer and the errno in *err, if defined; - -rpdtcp *rpdtcpsrv::accept(int to, int *err) -{ - int d = -1; - // Wait for incoming connections in steps of 1 sec - int tw = 0, rc = 0; - while (d < 0 && (to <= 0 || tw < to)) { - struct pollfd sfd = {fd, POLLIN|POLLRDNORM|POLLRDBAND|POLLPRI|POLLHUP, 0}; - do { - errno = 0; - rc = poll(&sfd, 1, 1000); - } while (rc < 0 && (errno == EAGAIN || errno == EINTR)); - if (rc > 0) { - errno = 0; - SOCKLEN_t addrlen = sizeof(addr); - while ((d = ::accept(fd, &addr, &addrlen)) == -1 && errno == EINTR) { - errno = 0; - } - } - // Count waited time - tw++; - } - - // Create the socket - rpdtcp *c = 0; - if (d < 0 && err) { - if (rc == 0) { - *err = ETIME; // Timed out - } else if (errno > 0) { - *err = (int) errno; - } else { - *err = -1; - } - } else { - c = new rpdtcp(d); - printf("rpdtcpsrv::accept: got descriptor %d\n", d); - } - - // Done - return c; -} - -// -// Class describing a UNIX connection -// - -//////////////////////////////////////////////////////////////////////////////// -/// Constructor - -rpdunix::rpdunix(const char *p) : rpdtcp(0), sockpath(p) -{ - // Need a valid path - unsigned int plen = 0; - if (!p || (p && (plen = strlen(p)) <= 0)) { - fprintf(stderr, "rpdunix::rpdunix: ERROR: path is undefined\n"); - return; - } - - struct sockaddr_un unserver; - memset(&unserver, 0, sizeof(unserver)); - unserver.sun_family = AF_UNIX; - - if (plen > sizeof(unserver.sun_path)-1) { - fprintf(stderr, "rpdunix::rpdunix: ERROR: socket path %s, longer than max allowed length (%u)\n", - p, (unsigned int)sizeof(unserver.sun_path)-1); - return; - } - strcpy(unserver.sun_path, p); - - // Open socket - if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { - fprintf(stderr, "rpdunix::rpdunix: ERROR: failure getting socket descriptor (errno: %d)\n", errno); - return; - } - - // Connect - errno = 0; - while (connect(fd, (struct sockaddr*) &unserver, strlen(unserver.sun_path)+2) == -1) { - if (errno == EINTR) { - errno = 0; - } else { - fprintf(stderr, "rpdunix::rpdunix: ERROR: failure while connecting over '%s' (errno: %d)\n", - p, errno); - ::close(fd); - fd = -1; - return; - } - } - - // Set descriptors - setdescriptors(fd, fd); - - // Done - return; -} - -// -// Class describing a server UNIX connection -// - -//////////////////////////////////////////////////////////////////////////////// -/// Constructor - -rpdunixsrv::rpdunixsrv(const char *p, int backlog) : rpdunix() -{ - // Need a valid path - unsigned int plen = 0; - if (!p || (p && (plen = strlen(p)) <= 0)) { - fprintf(stderr, "rpdunixsrv::rpdunixsrv: ERROR: path is undefined\n"); - return; - } - - // Clean the path, if already existing - struct stat st; - if (stat(p, &st) != 0) { - if (errno != ENOENT) { - fprintf(stderr, "rpdunixsrv::rpdunixsrv: ERROR: cannot operate on (parts of) path '%s' (errno: %d)\n", p, errno); - return; - } - } else { - // Remove it - if (unlink(p)) { - fprintf(stderr, "rpdunixsrv::rpdunixsrv: ERROR: cannot unlink path '%s'\n", p); - return; - } - } - - // Prepare the structure - struct sockaddr_un unserver; - memset(&unserver, 0, sizeof(unserver)); - unserver.sun_family = AF_UNIX; - - if (plen > sizeof(unserver.sun_path)-1) { - fprintf(stderr, "rpdunixsrv::rpdunixsrv: ERROR: socket path %s, longer than max allowed length (%u)\n", - p, (unsigned int)sizeof(unserver.sun_path)-1); - return; - } - strcpy(unserver.sun_path, p); - - // Open socket - if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { - fprintf(stderr, "rpdunixsrv::rpdunixsrv: ERROR: failure getting socket descriptor (errno: %d)\n", errno); - return; - } - - // Should be able to reuse this - int val = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof(val)) == -1) { - fprintf(stderr, "rpdunixsrv::rpdunixsrv: ERROR: failure setting SO_REUSEADDR (errno: %d)\n", errno); - return; - } - - // Bind - if (bind(fd, (struct sockaddr*) &unserver, strlen(unserver.sun_path)+2)) { - fprintf(stderr, "rpdunixsrv::rpdunixsrv: ERROR: failure binding socket (errno: %d)\n", errno); - ::close(fd); - fd = -1; - return; - } - - // Start accepting connections - if (listen(fd, backlog)) { - fprintf(stderr, "rpdunixsrv::rpdunixsrv: ERROR: failure enabling listening on socket (errno: %d)\n", errno); - ::close(fd); - fd = -1; - return; - } - - // Set descriptors - setdescriptors(fd, fd); - - // Save the path - sockpath = p; - - // Done - return; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Accept a connection on the server socket. -/// If to > 0, wait max to secs (granularity 1 sec). -/// Return a rpdunix object describing the open connection (to be destroyed -/// by the caller). -/// On error return a NULL pointer and the errno in *err, if defined; - -rpdunix *rpdunixsrv::accept(int to, int *err) -{ - int d = -1; - - // Wait for incoming connections in steps of 1 sec - int tw = 0, rc = 0; - while (d < 0 && (to <= 0 || tw < to)) { - struct pollfd sfd = {fd, POLLIN|POLLRDNORM|POLLRDBAND|POLLPRI|POLLHUP, 0}; - do { - errno = 0; - rc = poll(&sfd, 1, 1000); - } while (rc < 0 && (errno == EAGAIN || errno == EINTR)); - if (rc > 0) { - SOCKLEN_t addrlen = sizeof(addr); - errno = 0; - while ((d = ::accept(fd, &addr, &addrlen)) == -1 && errno == EINTR) { - errno = 0; - } - } - // Count waited time - tw++; - } - - // Create the socket - rpdunix *c = 0; - if (d < 0 && err) { - if (rc == 0) { - *err = ETIME; // Timed out - } else if (errno > 0) { - *err = (int) errno; - } else { - *err = -1; - } - } else { - c = new rpdunix(d); - } - - // Done - return c; -} - -// -// Class describing a UDP connection -// - -//////////////////////////////////////////////////////////////////////////////// -/// Constructor - -rpdudp::rpdudp(const char *h, int p) : rpdtcp(h,p) -{ - struct hostent *hent = 0; - if (!(hent = gethostbyname(h))) { - fprintf(stderr, "rpdtcp::rpdtcp: ERROR: failure resolving host address (errno: %d)\n", errno); - return; - } - - // The structure - struct sockaddr_in server; - memset(&server, 0, sizeof(server)); - server.sin_family = hent->h_addrtype; - memcpy((char *) &server.sin_addr.s_addr, hent->h_addr_list[0], hent->h_length); - server.sin_port = htons(port); - - // Open socket - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - fprintf(stderr, "rpdudp::rpdudp: ERROR: failure getting socket descriptor (errno: %d)\n", errno); - return; - } - - // Connect - errno = 0; - while (connect(fd, (struct sockaddr*) &server, sizeof(server)) == -1) { - if (errno == EINTR) { - errno = 0; - } else { - fprintf(stderr, "rpdudp::rpdudp: ERROR: failure while connecting to '%s:%d' (errno: %d)\n", - h, p, errno); - ::close(fd); - return; - } - } - - // Set descriptors - setdescriptors(fd, fd); - - // Done - return; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Constructor - -rpdudpsrv::rpdudpsrv(int p) : rpdudp(p) -{ - // The structure - struct sockaddr_in inserver; - memset(&inserver, 0, sizeof(inserver)); - inserver.sin_family = AF_INET; - inserver.sin_addr.s_addr = htonl(INADDR_ANY); - inserver.sin_port = htons(p); - - // Open socket - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - fprintf(stderr, "rpdudpsrv::rpdudpsrv: ERROR: failure getting socket descriptor (errno: %d)\n", errno); - return; - } - - if (bind(fd, (struct sockaddr*) &inserver, sizeof(inserver))) { - fprintf(stderr, "rpdudpsrv::rpdudpsrv: ERROR: failure binding socket (errno: %d)\n", errno); - ::close(fd); - fd = -1; - return; - } - - // Set descriptors - setdescriptors(fd, fd); - - // Done - return; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Send 'len' bytes at 'buf' -/// Return: -/// 0 if OK -/// -1 if invalid descriptor -/// -2 if failed to acquire mutex lock -/// -errno if any another failure - -int rpdudp::send(const void *buf, int len) -{ - rpdmtxhelper mh(&wrmtx); - if (isvalid(0)) { - if (mh.isok()) { - // Send the buffer - int n, nsnt = 0; - const char *b = (const char *)buf; - for (n = 0; n < len; n += nsnt) { - errno = 0; - if ((nsnt = ::sendto(wrfd, b+n, len-n, 0, 0, 0)) <= 0) { - if (nsnt == 0) break; - return -errno; - } - } - // Done - return 0; - } - // Could acquire the mutex lock - return -2; - } - // Invalid descriptor - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Receive 'len' bytes at 'buf' -/// Return: -/// 0 if OK -/// -1 if invalid descriptor -/// -2 if failed to acquire mutex lock -/// -errno if any another failure - -int rpdudp::recv(void *buf, int len) -{ - rpdmtxhelper mh(&rdmtx); - if (isvalid(1)) { - if (mh.isok()) { - int n, nrcv = 0; - char *b = (char *)buf; - for (n = 0; n < len; n += nrcv) { - errno = 0; - SOCKLEN_t addrlen = sizeof(addr); - if ((nrcv = recvfrom(rdfd, b+n, len-n, 0, &addr, &addrlen)) <= 0) { - if (nrcv == 0) break; // EOF - return -errno; - } - } - // Done - return 0; - } - // Could acquire the mutex lock - return -2; - } - // Invalid descriptor - return -1; -} - -// -// Class describing a basic message -// - -//////////////////////////////////////////////////////////////////////////////// -/// Add int 'i' to the internal buffer - -void rpdmsg::w_int(int i) -{ - char b[64] = {0}; - snprintf(b, 64, "%d", i); - if (!buf.empty()) buf += " "; - buf += b; - if (cur < 0) cur = 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Add double 'd' to the internal buffer - -void rpdmsg::w_double(double d) -{ - char b[128] = {0}; - snprintf(b, 128, "%f", d); - if (!buf.empty()) buf += " "; - buf += b; - if (cur < 0) cur = 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Add string 's' to the internal buffer - -void rpdmsg::w_string(const std::string &s) -{ - if (!buf.empty()) buf += " "; - buf += "'"; - buf += s; - buf += "'"; - if (cur < 0) cur = 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Retrieve an int from the internal buffer - -void rpdmsg::r_int(int &i) -{ - if (cur < 0 || cur > (int) buf.length()) return; - - char *p= ((char *)buf.c_str()) + cur; - while (*p == ' ') p++; - sscanf(p, "%d", &i); - if ((p = (char *) strchr(p+1, ' '))) while (*p == ' ') p++; - - // Update pointer - if (p) { - cur = (int) (p - (char *)buf.c_str()); - } else { - cur = (int) buf.length(); - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// Retrieve a double from the internal buffer - -void rpdmsg::r_double(double &d) -{ - if (cur < 0 || cur > (int) buf.length()) return; - - char *p= ((char *)buf.c_str()) + cur; - while (*p == ' ') p++; - float f; - sscanf(p, "%f", &f); - d = (double) f; - if ((p = (char *) strchr(p+1, ' '))) while (*p == ' ') p++; - - // Update pointer - if (p) { - cur = (int) (p - (char *)buf.c_str()); - } else { - cur = (int) buf.length(); - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// Retrieve a string from the internal buffer - -void rpdmsg::r_string(std::string &s) -{ - if (cur < 0 || cur > (int) buf.length()) return; - - s = ""; - int from = cur; - char *p = ((char *)buf.c_str()) + cur; - while (*p == ' ') { from++; p++; } - char *e = strchr(p, ' '); - int len = buf.length() - from; - len = (e) ? (int) (e - p) : buf.length() - from; - if (len > 0) s.assign(buf, from, len); - // Remove single quotes, if any - if (s[0] == '\'') s.erase(0,1); - if (s.length() > 0 && s[s.length() - 1] == '\'') s.erase(s.length() - 1, std::string::npos); - - // Update pointer - if (e) { - cur = (int) (e - (char *)buf.c_str()) + 1; - } else { - cur = (int) buf.length(); - } -} - diff --git a/net/rpdutils/src/rpdpriv.cxx b/net/rpdutils/src/rpdpriv.cxx deleted file mode 100644 index 8ca082792d22b..0000000000000 --- a/net/rpdutils/src/rpdpriv.cxx +++ /dev/null @@ -1,384 +0,0 @@ -// @(#)root/rpdutils:$Id$ -// Author: Gerardo Ganis, March 2011 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// rpdpriv // -// // -// Implementation of a privileges handling API following the paper // -// "Setuid Demystified" by H.Chen, D.Wagner, D.Dean // -// also quoted in "Secure programming Cookbook" by J.Viega & M.Messier. // -// // -////////////////////////////////////////////////////////////////////////// - -#include "rpdpriv.h" -#include "RConfigure.h" - -#if !defined(WINDOWS) -#include -#include -#include -#include -#include -#include -using std::cout, std::endl; - -#define NOUC ((uid_t)(-1)) -#define NOGC ((gid_t)(-1)) -#define RPPERR(x) ((x == 0) ? -1 : -x) - -// Some machine specific stuff -#if defined(__sgi) && !defined(__GNUG__) && (SGI_REL<62) -extern "C" { - int seteuid(int euid); - int setegid(int egid); - int geteuid(); - int getegid(); -} -#endif - -#if defined(_AIX) -extern "C" { - int seteuid(uid_t euid); - int setegid(gid_t egid); - uid_t geteuid(); - gid_t getegid(); -} -#endif - -#if !defined(R__HAS_SETRESUID) -static int setresgid(gid_t r, gid_t e, gid_t) -{ - if (r != NOGC && setgid(r) == -1) - return RPPERR(errno); - return ((e != NOGC) ? setegid(e) : 0); -} - -static int setresuid(uid_t r, uid_t e, uid_t) -{ - if (r != NOUC && setuid(r) == -1) - return RPPERR(errno); - return ((e != NOUC) ? seteuid(e) : 0); -} - -static int getresgid(gid_t *r, gid_t *e, gid_t *) -{ - *r = getgid(); - *e = getegid(); - return 0; -} - -static int getresuid(uid_t *r, uid_t *e, uid_t *) -{ - *r = getuid(); - *e = geteuid(); - return 0; -} - -#else -#if (defined(__linux__) || \ - (defined(__CYGWIN__) && defined(__GNUC__))) && !defined(linux) -# define linux -#endif -#if defined(linux) && !defined(R__HAS_SETRESUID) -extern "C" { - int setresgid(gid_t r, gid_t e, gid_t s); - int setresuid(uid_t r, uid_t e, uid_t s); - int getresgid(gid_t *r, gid_t *e, gid_t *s); - int getresuid(uid_t *r, uid_t *e, uid_t *s); -} -#endif -#endif -#endif // not WINDOWS - -bool rpdpriv::debug = 0; // debug switch - -//////////////////////////////////////////////////////////////////////////////// -/// Restore the 'saved' (saved = TRUE) or 'real' entity as effective. -/// Return 0 on success, < 0 (== -errno) if any error occurs. - -int rpdpriv::restore(bool saved) -{ -#if !defined(WINDOWS) - // Get the UIDs - uid_t ruid = 0, euid = 0, suid = 0; - if (getresuid(&ruid, &euid, &suid) != 0) - return RPPERR(errno); - - // Set the wanted value - uid_t uid = saved ? suid : ruid; - - // Act only if a change is needed - if (euid != uid) { - - // Set uid as effective - if (setresuid(NOUC, uid, NOUC) != 0) - return RPPERR(errno); - - // Make sure the new effective UID is the one wanted - if (geteuid() != uid) - return RPPERR(errno); - } - - // Get the GIDs - uid_t rgid = 0, egid = 0, sgid = 0; - if (getresgid(&rgid, &egid, &sgid) != 0) - return RPPERR(errno); - - // Set the wanted value - gid_t gid = saved ? sgid : rgid; - - // Act only if a change is needed - if (egid != gid) { - - // Set newuid as effective, saving the current effective GID - if (setresgid(NOGC, gid, NOGC) != 0) - return RPPERR(errno); - - // Make sure the new effective GID is the one wanted - if (getegid() != gid) - return RPPERR(errno); - } - -#endif - // Done - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Change effective to entity newuid. Current entity is saved. -/// Real entity is not touched. Use RestoreSaved to go back to -/// previous settings. -/// Return 0 on success, < 0 (== -errno) if any error occurs. - -int rpdpriv::changeto(uid_t newuid, gid_t newgid) -{ -#if !defined(WINDOWS) - // Current UGID - uid_t oeuid = geteuid(); - gid_t oegid = getegid(); - - // Restore privileges, if needed - if (oeuid && rpdpriv::restore(0) != 0) - return RPPERR(errno); - - // Act only if a change is needed - if (newgid != oegid) { - - // Set newgid as effective, saving the current effective GID - if (setresgid(NOGC, newgid, oegid) != 0) - return RPPERR(errno); - - // Get the GIDs - uid_t rgid = 0, egid = 0, sgid = 0; - if (getresgid(&rgid, &egid, &sgid) != 0) - return RPPERR(errno); - - // Make sure the new effective GID is the one wanted - if (egid != newgid) - return RPPERR(errno); - } - - // Act only if a change is needed - if (newuid != oeuid) { - - // Set newuid as effective, saving the current effective UID - if (setresuid(NOUC, newuid, oeuid) != 0) - return RPPERR(errno); - - // Get the UIDs - uid_t ruid = 0, euid = 0, suid = 0; - if (getresuid(&ruid, &euid, &suid) != 0) - return RPPERR(errno); - - // Make sure the new effective UID is the one wanted - if (euid != newuid) - return RPPERR(errno); - } - -#endif - // Done - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Change permanently to entity newuid. Requires super-userprivileges. -/// Provides a way to drop permanently su privileges. -/// Return 0 on success, < 0 (== -errno) if any error occurs. - -int rpdpriv::changeperm(uid_t newuid, gid_t newgid) -{ - // Atomic action -#if !defined(WINDOWS) - // Get UIDs - uid_t cruid = 0, ceuid = 0, csuid = 0; - if (getresuid(&cruid, &ceuid, &csuid) != 0) { - return RPPERR(errno); - } - - // Get GIDs - uid_t crgid = 0, cegid = 0, csgid = 0; - if (getresgid(&crgid, &cegid, &csgid) != 0) { - return RPPERR(errno); - } - // Restore privileges, if needed - if (ceuid && rpdpriv::restore(0) != 0) { - return RPPERR(errno); - } - // Act only if needed - if (newgid != cegid || newgid != crgid) { - - // Set newgid as GID, all levels - if (setresgid(newgid, newgid, newgid) != 0) { - return RPPERR(errno); - } - // Get GIDs - uid_t rgid = 0, egid = 0, sgid = 0; - if (getresgid(&rgid, &egid, &sgid) != 0) { - return RPPERR(errno); - } - // Make sure the new GIDs are all equal to the one asked - if (rgid != newgid || egid != newgid) { - return RPPERR(errno); - } - } - - // Act only if needed - if (newuid != ceuid || newuid != cruid) { - - // Set newuid as UID, all levels - if (setresuid(newuid, newuid, newuid) != 0) { - return RPPERR(errno); - } - // Get UIDs - uid_t ruid = 0, euid = 0, suid = 0; - if (getresuid(&ruid, &euid, &suid) != 0) { - return RPPERR(errno); - } - // Make sure the new UIDs are all equal to the one asked - if (ruid != newuid || euid != newuid) { - return RPPERR(errno); - } - } -#endif - - // Done - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Dump current entity - -void rpdpriv::dumpugid(const char *msg) -{ -#if !defined(WINDOWS) - // Get the UIDs - uid_t ruid = 0, euid = 0, suid = 0; - if (getresuid(&ruid, &euid, &suid) != 0) - return; - - // Get the GIDs - uid_t rgid = 0, egid = 0, sgid = 0; - if (getresgid(&rgid, &egid, &sgid) != 0) - return; - - cout << "rpdpriv: " << endl; - cout << "rpdpriv: dump values: " << (msg ? msg : "") << endl; - cout << "rpdpriv: " << endl; - cout << "rpdpriv: real = (" << ruid <<","<< rgid <<")" << endl; - cout << "rpdpriv: effective = (" << euid <<","<< egid <<")" << endl; - cout << "rpdpriv: saved = (" << suid <<","<< sgid <<")" << endl; - cout << "rpdpriv: " << endl; -#endif -} - -// -// Guard class -//////////////////////////////////////////////////////////////////////////////// -/// Constructor. Create a guard object for temporarly change to privileges -/// of {'uid', 'gid'} - -rpdprivguard::rpdprivguard(uid_t uid, gid_t gid) -{ - dum = 1; - valid = 0; - - init(uid, gid); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Constructor. Create a guard object for temporarly change to privileges -/// of 'usr' - -rpdprivguard::rpdprivguard(const char *usr) -{ - dum = 1; - valid = 0; - -#if !defined(WINDOWS) - if (usr && strlen(usr) > 0) { - struct passwd *pw = getpwnam(usr); - if (pw) - init(pw->pw_uid, pw->pw_gid); - } -#else - if (usr) { } -#endif -} - -//////////////////////////////////////////////////////////////////////////////// -/// Destructor. Restore state and unlock the global mutex. - -rpdprivguard::~rpdprivguard() -{ - if (!dum) { - rpdpriv::restore(); - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// Init a change of privileges guard. Act only if superuser. -/// The result of initialization can be tested with the Valid() method. - -void rpdprivguard::init(uid_t uid, gid_t gid) -{ - dum = 1; - valid = 1; - - // Debug hook - if (rpdpriv::debug) - rpdpriv::dumpugid("before init()"); - -#if !defined(WINDOWS) - uid_t ruid = 0, euid = 0, suid = 0; - gid_t rgid = 0, egid = 0, sgid = 0; - if (getresuid(&ruid, &euid, &suid) == 0 && - getresgid(&rgid, &egid, &sgid) == 0) { - if ((euid != uid) || (egid != gid)) { - if (!ruid) { - // Change temporarly identity - if (rpdpriv::changeto(uid, gid) != 0) - valid = 0; - dum = 0; - } else { - // Change requested but not enough privileges - valid = 0; - } - } - } else { - // Something bad happened: memory corruption? - valid = 0; - } -#endif - // Debug hook - if (rpdpriv::debug) - rpdpriv::dumpugid("after init()"); -} diff --git a/net/rpdutils/src/rpdutils.cxx b/net/rpdutils/src/rpdutils.cxx deleted file mode 100644 index 5ef6c9f84cd63..0000000000000 --- a/net/rpdutils/src/rpdutils.cxx +++ /dev/null @@ -1,4633 +0,0 @@ -// @(#)root/rpdutils:$Id$ -// Author: Gerardo Ganis 7/4/2003 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// rpdutils // -// // -// Set of utilities for rootd daemon authentication. // -// // -////////////////////////////////////////////////////////////////////////// - -#include "RConfigure.h" -#include "TError.h" -#include -#include "strlcpy.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "snprintf.h" - -#if defined(__CYGWIN__) && defined(__GNUC__) -# define cygwingcc -#endif - -#if defined(__linux__) && !defined(linux) -# define linux -#endif - -#if defined(linux) || defined(__sun) || defined(__sgi) || \ - defined(_AIX) || defined(__FreeBSD__) || defined(__OpenBSD__) || \ - defined(__APPLE__) || defined(__MACH__) || defined(cygwingcc) -#include -#include -#include -#endif - -#ifdef _AIX -extern "C" int ruserok(char *, int, char *, char *); -#endif - -#if defined(__APPLE__) -#include -extern "C" int fstatfs(int file_descriptor, struct statfs *buffer); -#elif defined(linux) || defined(__hpux) -#include -#elif defined(__FreeBSD__) || defined(__OpenBSD__) -#include -#include -#else -#include -#endif - -#if defined(linux) -# include -# if __GNU_LIBRARY__ == 6 -# ifndef R__GLIBC -# define R__GLIBC -# endif -# endif -#endif -#if defined(cygwingcc) || (defined(__MACH__) && !defined(__APPLE__)) -# define R__GLIBC -#endif - -#if (defined(__FreeBSD__) && (__FreeBSD__ < 4)) || defined(__OpenBSD__) || \ - (defined(__APPLE__) && (!defined(MAC_OS_X_VERSION_10_3) || \ - (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_3))) -#include -#define lockf(fd, op, sz) flock((fd), (op)) -#ifndef F_LOCK -#define F_LOCK (LOCK_EX | LOCK_NB) -#endif -#ifndef F_ULOCK -#define F_ULOCK LOCK_UN -#endif -#endif - -#if defined(cygwingcc) && !defined(F_LOCK) && !defined(F_ULOCK) -#define F_LOCK F_WRLCK -#define F_ULOCK F_UNLCK -int ruserok(const char *, int, const char *, const char *) { - return 0; -} -static int fcntl_lockf(int fd, int op, off_t off) -{ - flock fl; - fl.l_whence = SEEK_SET; - fl.l_start = off; - fl.l_len = 0; // whole file - fl.l_pid = getpid(); - fl.l_type = op; - return fcntl(fd, F_SETLK, &fl); -} -#define lockf fcntl_lockf -#endif - -#if defined(__sun) || defined(R__GLIBC) -#include -#endif - -#if defined(__osf__) || defined(__sgi) || defined(R__MACOSX) -extern "C" char *crypt(const char *, const char *); -#endif - -#ifdef R__WIN32 -#define R__NOCRYPT -#endif - -#ifdef R__NOCRYPT -static std::string gRndmSalt = std::string("ABCDEFGH"); -#endif - -#if defined(__sun) -#ifndef R__SHADOWPW -#define R__SHADOWPW -#endif -#endif - -#ifdef R__SHADOWPW -#include -#endif - -#ifdef R__SSL -// SSL specific headers for RSA keys -#include -#include -#include -#include -#include -#include -#include -#endif - -#include "rpdp.h" -#include "rsadef.h" -#include "rsalib.h" -// -// To improve error logging for UsrPwd on the client side -static ERootdErrors gUsrPwdErr[4][4] = { - {kErrNoPasswd, kErrNoPassHEquNoFiles, kErrNoPassHEquBadFiles, kErrNoPassHEquFailed}, - {kErrBadPasswd, kErrBadPassHEquNoFiles, kErrBadPassHEquBadFiles, kErrBadPassHEquFailed}, - {kErrBadRtag, kErrBadRtagHEquNoFiles, kErrBadRtagHEquBadFiles, kErrBadRtagHEquFailed}, - {kErrBadPwdFile, kErrBadPwdFileHEquNoFiles, kErrBadPwdFileHEquBadFiles, - kErrBadPwdFileHEquFailed}}; - -//--- Machine specific routines ------------------------------------------------ - -#if defined(__sgi) && !defined(__GNUG__) && (SGI_REL<62) -extern "C" { - int seteuid(int euid); - int setegid(int egid); -} -#endif - -#if defined(_AIX) -extern "C" { - int seteuid(uid_t euid); - int setegid(gid_t egid); -} -#endif - -#if !defined(__hpux) && !defined(linux) && !defined(__FreeBSD__) && \ - !defined(__OpenBSD__) || defined(cygwingcc) -static int setresgid(gid_t r, gid_t e, gid_t) -{ - if (setgid(r) == -1) - return -1; - return setegid(e); -} - -static int setresuid(uid_t r, uid_t e, uid_t) -{ - if (setuid(r) == -1) - return -1; - return seteuid(e); -} -#else -#if defined(linux) && !defined(R__HAS_SETRESUID) -extern "C" { - int setresgid(gid_t r, gid_t e, gid_t s); - int setresuid(uid_t r, uid_t e, uid_t s); -} -#endif -#endif - -#if defined(__sun) -#if defined(R__SUNGCC3) -extern "C" int gethostname(char *, unsigned int); -#endif -#endif - -extern int gDebug; - -namespace ROOT { - -// -// rpdutils module globals -ErrorHandler_t gErrSys = 0; -ErrorHandler_t gErrFatal = 0; -ErrorHandler_t gErr = 0; -bool gSysLog = 0; -std::string gServName[3] = { "sockd", "rootd" }; - -// -// Local global consts -static const int gAUTH_CLR_MSK = 0x1; // Masks for authentication methods -static const int gMAXTABSIZE = 50000000; - -static const std::string gAuthMeth[kMAXSEC] = { "UsrPwd", "Unsupported", "Unsupported", - "Unsupported", "Unsupported", "Unsupported" }; -static const std::string gAuthTab = "/rpdauthtab"; // auth table -static const std::string gDaemonRc = ".rootdaemonrc"; // daemon access rules -static const std::string gRootdPass = ".rootdpass"; // special rootd passwd -static const std::string gKeyRoot = "/rpk."; // Root for key files - -// -// RW dir for temporary files (needed by gRpdAuthTab: do not move) -static std::string gTmpDir = "/tmp"; - -// -// Local global vars -static int gAuthProtocol = -1; // Protocol used fro a successful authentication -static char gBufOld[kMAXRECVBUF] = {0}; // msg sync for old client (<=3.05/07) -static bool gCheckHostsEquiv = 1; -static int gClientOld = 0; // msg sync for old client (<=3.05/07) -static int gClientProtocol = -1; -static int gCryptRequired = -1; -static std::string gCryptToken; -static int gAllowMeth[kMAXSEC]; -static int gAnon = 0; -static int gExistingAuth = 0; -static int gAuthListSent = 0; -static int gHaveMeth[kMAXSEC]; -static EMessageTypes gKindOld; // msg sync for old client (<=3.05/07) -static int gMethInit = 0; -static int gNumAllow = -1; -static int gNumLeft = -1; -static int gOffSet = -1; -static std::string gOpenHost = "????"; -static int gParentId = -1; -static char gPasswd[kMAXUSERLEN] = { 0 }; -static char gPubKey[kMAXPATHLEN] = { 0 }; -static int gPubKeyLen = 0; -static int gRandInit = 0; -static int gRemPid = -1; -static bool gRequireAuth = 1; -static int gReUseAllow = 0x1F; // define methods for which tokens can be asked -static int gReUseRequired = -1; -static int gDoLogin = 0; // perform login -static std::string gRpdAuthTab = std::string(gTmpDir).append(gAuthTab); -static std::string gRpdKeyRoot = std::string(gTmpDir).append(gKeyRoot); -static rsa_NUMBER gRSA_d; -static rsa_NUMBER gRSA_n; -static int gRSAInit = 0; -static int gRSAKey = 0; -static rsa_KEY gRSAPriKey; -static rsa_KEY_export gRSAPubExport[2] = {{0,0},{0,0}}; -static rsa_KEY gRSAPubKey; -#ifdef R__SSL -static BF_KEY gBFKey; // Session symmetric key -static RSA *gRSASSLKey = 0; // Local RSA SSL key -#endif -static int gSaltRequired = -1; -static int gSec = -1; -static int gServerProtocol = -1; -static EService gService = kROOTD; -static int gTriedMeth[kMAXSEC]; -static char gUser[64] = { 0 }; -static char *gUserAllow[kMAXSEC] = { 0 }; // User access control -static unsigned int gUserAlwLen[kMAXSEC] = { 0 }; -static unsigned int gUserIgnLen[kMAXSEC] = { 0 }; -static char *gUserIgnore[kMAXSEC] = { 0 }; - -//////////////////////////////////////////////////////////////////////////////// -/// rand() implementation using /udev/random or /dev/random, if available - -static int rpd_rand() -{ -#ifndef WIN32 - int frnd = open("/dev/urandom", O_RDONLY); - if (frnd < 0) frnd = open("/dev/random", O_RDONLY); - int r; - if (frnd >= 0) { - ssize_t rs = read(frnd, (void *) &r, sizeof(int)); - close(frnd); - if (r < 0) r = -r; - if (rs == sizeof(int)) return r; - } - ErrorInfo("+++ERROR+++ : rpd_rand: neither /dev/urandom nor /dev/random are available or readable!"); - struct timeval tv; - if (gettimeofday(&tv,0) == 0) { - int t1, t2; - memcpy((void *)&t1, (void *)&tv.tv_sec, sizeof(int)); - memcpy((void *)&t2, (void *)&tv.tv_usec, sizeof(int)); - r = t1 + t2; - if (r < 0) r = -r; - return r; - } - return -1; -#else - // No special random device available: use rand() - return rand(); -#endif -} - -//////////////////////////////////////////////////////////////////////////////// -/// reads in at most one less than len characters from open -/// descriptor fd and stores them into the buffer pointed to by buf. -/// Reading stops after an EOF or a newline. If a newline is -/// read, it is stored into the buffer. -/// A '\0' is stored after the last character in the buffer. -/// The number of characters read is returned (newline included). -/// Returns < 0 in case of error. - -static int reads(int fd, char *buf, int len) -{ - int k = 0; - int nread = -1; - int nr = read(fd,buf,1); - while (nr > 0 && buf[k] != '\n' && k < (len-1)) { - k++; - nr = read(fd,buf+k,1); - } - if (k >= len-1) { - buf[k] = 0; - nread = len-1; - } else if (buf[k] == '\n'){ - if (k <= len-2) { - buf[k+1] = 0; - nread = k+1; - } else { - buf[k] = 0; - nread = k; - } - } else if (nr == 0) { - if (k > 0) { - buf[k-1] = 0; - nread = k-1; - } else { - buf[0] = 0; - nread = 0; - } - } else if (nr < 0) { - if (k > 0) { - buf[k] = 0; - nread = -(k-1); - } else { - buf[0] = 0; - nread = -1; - } - } - // Fix the lengths - if (nread >= 0) buf[nread] = 0; - - return nread; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Case insensitive string compare of n characters. - -static int rpdstrncasecmp(const char *str1, const char *str2, int n) -{ - while (n > 0) { - int c1 = *str1; - int c2 = *str2; - - if (isupper(c1)) - c1 = tolower(c1); - - if (isupper(c2)) - c2 = tolower(c2); - - if (c1 != c2) - return c1 - c2; - - str1++; - str2++; - n--; - } - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Case insensitive string compare. - -static int rpdstrcasecmp(const char *str1, const char *str2) -{ - return rpdstrncasecmp(str1, str2, strlen(str2) + 1); -} - -//////////////////////////////////////////////////////////////////////////////// -/// To avoid problems due to compiler optmization -/// Taken from Viega&Messier, "Secure Programming Cookbook", O'Really, #13.2 -/// (see discussion there) - -static volatile void *rpdmemset(volatile void *dst, int c, int len) -{ - volatile char *buf; - - for (buf = (volatile char *)dst; len;) { buf[--len] = c; } - return dst; -} - -#ifdef R__NOCRYPT -//////////////////////////////////////////////////////////////////////////////// -/// This applies simple nor encryption with sa to the first 64 bytes -/// pw. Returns the hex of the result (max length 128). -/// This is foreseen for systms where crypt is not available -/// (on windows ...), to provide some protection of tokens. - -char *rpdcrypt(const char *pw, const char *sa) -{ - static char buf[129]; - char tbuf[64]; - int np = (strlen(pw) < 64) ? strlen(pw) : 64; - int ns = strlen(sa); - char c; - - int i = 0; - for (i=0; i> 4; - if (j < 10) - c = 48 + j; - else - c = 55 + j; - k = 2*i + 1; - buf[k] = c; - } - // Null termination - buf[np*2] = 0; - - return buf; -} -#endif - -//////////////////////////////////////////////////////////////////////////////// -/// Change the value of the static gSysLog to syslog. -/// Recognized values: -/// 0 log to syslog (for root started daemons) -/// 1 log to stderr (for user started daemons) - -void RpdSetSysLogFlag(int syslog) -{ - gSysLog = syslog; - if (gDebug > 2) - ErrorInfo("RpdSetSysLogFlag: gSysLog set to %d", gSysLog); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Change the value of the static gMethInit to methinit. -/// Recognized values: -/// 0 reset -/// 1 initialized already - -void RpdSetMethInitFlag(int methinit) -{ - gMethInit = methinit; - if (gDebug > 2) - ErrorInfo("RpdSetMethInitFlag: gMethInit set to %d", gMethInit); -} - -//////////////////////////////////////////////////////////////////////////////// - -int RpdGetAuthMethod(int kind) -{ - int method = -1; - - if (kind == kROOTD_USER) - method = 0; - - return method; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Delete Public Key file -/// Returns: 0 if ok -/// 1 if error unlinking (check errno); - -int RpdDeleteKeyFile(int ofs) -{ - int retval = 0; - - std::string pukfile = gRpdKeyRoot; - pukfile.append(ItoA(ofs)); - - // Some debug info - if (gDebug > 2) { - ErrorInfo("RpdDeleteKeyFile: proc uid:%d gid:%d", - getuid(),getgid()); - } - - // Unlink - if (unlink(pukfile.c_str()) == -1) { - if (gDebug > 0 && GetErrno() != ENOENT) { - ErrorInfo("RpdDeleteKeyFile: problems unlinking pub" - " key file '%s' (errno: %d)", - pukfile.c_str(),GetErrno()); - } - retval = 1; - } - return retval; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Update tab file. -/// If ilck <= 0 open and lock the file; if ilck > 0, use file -/// descriptor ilck, which should correspond to an open and locked file. -/// If opt = -1 : delete file (backup saved in `.bak`); -/// If opt = 0 : eliminate all inactive entries -/// (if line="size" act only if size > gMAXTABSIZE) -/// if opt = 1 : append 'line'. -/// Returns -1 in case of error. -/// Returns offset for 'line' and token for opt = 1. -/// Returns new file size for opt = 0. - -int RpdUpdateAuthTab(int opt, const char *line, char **token, int ilck) -{ - int retval = -1; - int itab = 0; - char fbuf[kMAXPATHLEN]; - - if (gDebug > 2) - ErrorInfo("RpdUpdateAuthTab: analyzing: opt: %d, line: %s, ilck: %d", - opt, line, ilck); - - if (ilck <= 0) { - - // Open file for reading/ writing - itab = open(gRpdAuthTab.c_str(), O_RDWR); - if (itab == -1) { - if (opt == 1 && GetErrno() == ENOENT) { - // Try creating the file - itab = open(gRpdAuthTab.c_str(), O_RDWR | O_CREAT, 0600); - if (itab == -1) { - ErrorInfo("RpdUpdateAuthTab: opt=%d: error opening %s" - "(errno: %d)", - opt, gRpdAuthTab.c_str(), GetErrno()); - return retval; - } - } else { - ErrorInfo("RpdUpdateAuthTab: opt=%d: error opening %s" - " (errno: %d)", - opt, gRpdAuthTab.c_str(), GetErrno()); - return retval; - } - } - - // lock tab file - if (lockf(itab, F_LOCK, (off_t) 1) == -1) { - ErrorInfo("RpdUpdateAuthTab: opt=%d: error locking %s" - " (errno: %d)", opt, gRpdAuthTab.c_str(), GetErrno()); - close(itab); - return retval; - } - if (gDebug > 0) - ErrorInfo("RpdUpdateAuthTab: opt= %d - file LOCKED", opt); - } else { - itab = ilck; - } - - // File size - int fsize = 0; - if ((fsize = lseek(itab, 0, SEEK_END)) == -1) { - ErrorInfo("RpdUpdateAuthTab: opt=%d: lseek error (errno: %d)", - opt, GetErrno()); - goto goingout; - } - - // Set indicator to beginning - if (lseek(itab, 0, SEEK_SET) == -1) { - ErrorInfo("RpdUpdateAuthTab: opt=%d: lseek error (errno: %d)", - opt, GetErrno()); - goto goingout; - } - - if (opt == -1) { - - // - // Save file in .bak and delete its content - - // Open backup file - std::string bak = std::string(gRpdAuthTab).append(".bak"); - int ibak = open(bak.c_str(), O_RDWR | O_CREAT, 0600); - if (ibak == -1) { - ErrorInfo("RpdUpdateAuthTab: opt=%d: error opening/creating %s" - " (errno: %d)", opt, bak.c_str(), GetErrno()); - goto goingout; - } - - // Truncate file to new length - if (ftruncate(ibak, 0) == -1) - ErrorInfo("RpdUpdateAuthTab: opt=%d: ftruncate error (%s)" - " (errno: %d)", opt, bak.c_str(), GetErrno()); - - // Copy the content - char buf[kMAXPATHLEN]; - int ofs = 0, nr = 0; - while ((nr = reads(itab, buf, sizeof(buf)))) { - int slen = strlen(buf); - - // Make sure there is a '\n' before writing - if (buf[slen-1] != '\n') { - if (slen >= kMAXPATHLEN -1) - buf[slen-1] = '\n'; - else { - buf[slen] = '\n'; - buf[slen+1] = '\0'; - } - } - if (slen) { - while (write(ibak, buf, slen) < 0 && GetErrno() == EINTR) - ResetErrno(); - } - - // Delete Public Key file - RpdDeleteKeyFile(ofs); - // Next OffSet - ofs += slen; - } - close(ibak); - - // Truncate file to new length - if (ftruncate(itab, 0) == -1) - ErrorInfo("RpdUpdateAuthTab: opt=%d: ftruncate error (%s)" - " (errno: %d)", opt, gRpdAuthTab.c_str(), GetErrno()); - retval = 0; - - } else if (opt == 0) { - - // - // Cleanup the file (remove inactive entries) - - // Now scan over entries - int pr = 0, pw = 0; - int lsec, act = 0, oldofs = 0, bytesread = 0; - char ln[kMAXPATHLEN], dumm[kMAXPATHLEN]; - bool fwr = 0; - - while ((bytesread = reads(itab, ln, sizeof(ln)))) { - - bool ok = 1; - // Current position - if ((pr = lseek(itab,0,SEEK_CUR)) < 0) { - ErrorInfo("RpdUpdateAuthTab: opt=%d: problems lseeking file %s" - " (errno: %d)", opt, gRpdAuthTab.c_str(), errno); - fwr = 1; - ok = 0; - } - - // Check file corruption: length and number of items - int slen = bytesread; - if (ok && slen < 1) { - ErrorInfo("RpdUpdateAuthTab: opt=%d: file %s seems corrupted" - " (slen: %d)", opt, gRpdAuthTab.c_str(), slen); - fwr = 1; - ok = 0; - } - if (ok) { - // Check file corruption: number of items - int ns = sscanf(ln, "%d %d %4095s", &lsec, &act, dumm); - if (ns < 3 ) { - ErrorInfo("RpdUpdateAuthTab: opt=%d: file %s seems corrupted" - " (ns: %d)", opt, gRpdAuthTab.c_str(), ns); - fwr = 1; - ok = 0; - } - } - - if (ok && act > 0) { - if (fwr) { - // We have to update the key file name - int nr = 0; - if ((nr = RpdRenameKeyFile(oldofs,pw)) == 0) { - // Write the entry at new position - lseek(itab, pw, SEEK_SET); - - if (ln[slen-1] != '\n') { - if (slen >= kMAXPATHLEN -1) - ln[slen-1] = '\n'; - else { - ln[slen] = '\n'; - ln[slen+1] = '\0'; - } - } - while (write(itab, ln, strlen(ln)) < 0 - && GetErrno() == EINTR) - ResetErrno(); - pw += strlen(ln); - } else - RpdDeleteKeyFile(oldofs); - lseek(itab, pr, SEEK_SET); - } else - pw += strlen(ln); - } else { - fwr = 1; - } - // Set old offset - oldofs = pr; - } - - // Truncate file to new length - if (ftruncate(itab, pw) == -1) - ErrorInfo("RpdUpdateAuthTab: opt=%d: ftruncate error (errno: %d)", - opt, GetErrno()); - - // Return new file size - retval = pw; - - } else if (opt == 1) { - - // - // Add 'line' at the end - // (check size and cleanup/truncate if needed) - - // Check size ... - if ((int)(fsize+strlen(line)) > gMAXTABSIZE) { - - // If it is going to be too big, cleanup or truncate first - fsize = RpdUpdateAuthTab(0,(const char *)0,0,itab); - - // If still too big: delete everything - if ((int)(fsize+strlen(line)) > gMAXTABSIZE) - fsize = RpdUpdateAuthTab(-1,(const char *)0,0,itab); - } - // We are going to write at the end - retval = lseek(itab, 0, SEEK_END); - - // Save first RSA public key into file for later use by the - // same or other rootd; we will update the tab file - // only if this operation is successful - int ntry = 10; - int rs = 0; - while ((rs = RpdSavePubKey(gPubKey, retval, gUser)) == 2 && ntry--) { - // We are here if a file with the same name exists already - // and can not be deleted: we shift the offset with a - // dummy entry - char ltmp[256]; - SPrintf(ltmp, 256, - "0 0 %d %d %s error: pubkey file in use: shift offset\n", - gRSAKey, gRemPid, gOpenHost.c_str()); - - // adds line - while (write(itab, ltmp, strlen(ltmp)) < 0 && GetErrno() == EINTR) - ResetErrno(); - - // Set to the new end - retval = lseek(itab, 0, SEEK_END); - } - - if (rs > 0) { - // Something wrong - retval = -1; - if (gDebug > 0) - ErrorInfo("RpdUpdateAuthTab: pub key could not be saved (%d)",rs); - } else { - // Generate token - *token = RpdGetRandString(3, 8); // 8 crypt-like chars -#ifndef R__NOCRYPT - char *cryptToken = crypt(*token, *token); -#else - char *cryptToken = rpdcrypt(*token,gRndmSalt.c_str()); -#endif - SPrintf(fbuf, kMAXPATHLEN, "%s %s\n", line, cryptToken); - if (gDebug > 2) - ErrorInfo("RpdUpdateAuthTab: token: '%s'", cryptToken); - // Save it for later use in kSOCKD servers - gCryptToken = std::string(cryptToken); - - // adds line - while (write(itab, fbuf, strlen(fbuf)) < 0 && GetErrno() == EINTR) - ResetErrno(); - } - - } else { - - // - // Unknown option - ErrorInfo("RpdUpdateAuthTab: unrecognized option (opt= %d)", opt); - } - - goingout: - if (itab != ilck) { - // unlock the file - lseek(itab, 0, SEEK_SET); - if (lockf(itab, F_ULOCK, (off_t) 1) == -1) { - ErrorInfo("RpdUpdateAuthTab: error unlocking %s", - gRpdAuthTab.c_str()); - } - - // closing file ... - close(itab); - } - - return retval; -} - -//////////////////////////////////////////////////////////////////////////////// -/// De-activates entry related to token with crypt crypttoken. -/// Returns: 0 if successful -/// -4 if entry not found or inactive -/// -1 problems opening auth tab file -/// -2 problems locking auth tab file -/// -3 auth tab file does not exists - -int RpdCleanupAuthTab(const char *crypttoken) -{ - int retval = -4; - - if (gDebug > 2) - ErrorInfo("RpdCleanupAuthTab: Crypt-token: '%s'",crypttoken); - - // Open file for update - int itab = -1; - if ((itab = open(gRpdAuthTab.c_str(), O_RDWR)) == -1) { - if (GetErrno() == ENOENT) { - if (gDebug > 0) - ErrorInfo("RpdCleanupAuthTab: file %s does not exist", - gRpdAuthTab.c_str()); - return -3; - } else { - ErrorInfo("RpdCleanupAuthTab: error opening %s (errno: %d)", - gRpdAuthTab.c_str(), GetErrno()); - return -1; - } - } - - // lock tab file - if (lockf(itab, F_LOCK, (off_t) 1) == -1) { - ErrorInfo("RpdCleanupAuthTab: error locking %s (errno: %d)", - gRpdAuthTab.c_str(), GetErrno()); - close(itab); - return -2; - } - if (gDebug > 0) - ErrorInfo("RpdCleanupAuthTab: file LOCKED (ctkn: '%s')",crypttoken); - - - // Now access entry or scan over entries - int pr = 0, pw = 0; - int nw, lsec, act, remid, pkey; - char line[kMAXPATHLEN]; - - // Set indicators - if ((pr = lseek(itab, 0, SEEK_SET)) < 0) { - ErrorInfo("RpdCleanupAuthTab: error lseeking %s (errno: %d)", - gRpdAuthTab.c_str(), GetErrno()); - close(itab); - return -2; - } - pw = pr; - while (reads(itab,line, sizeof(line))) { - - pr += strlen(line); - if (gDebug > 2) - ErrorInfo("RpdCleanupAuthTab: pr:%d pw:%d (line:%s) (pId:%d)", - pr, pw, line, gParentId); - - char dum1[kMAXPATHLEN] = {0}, host[kMAXUSERLEN] = {0}, user[kMAXUSERLEN] = {0}, - ctkn[30] = {0}, dum2[30] = {0}; - nw = sscanf(line, "%d %d %d %d %127s %127s %29s %4095s %29s", - &lsec, &act, &pkey, &remid, host, user, ctkn, dum1, dum2); - - int deactivate = 0; - - if (act > 0) { - - if (lsec == 3 && nw == 9) { - if (!strncmp(dum2,crypttoken,strlen(crypttoken))) - deactivate = 1; - } else if (nw == 7) { - if (!strncmp(ctkn,crypttoken,strlen(crypttoken))) - deactivate = 1; - } - - // Deactivate active entries: remote client has gone ... - if (deactivate) { - - retval = 0; - - // Delete Public Key file - RpdDeleteKeyFile(pw); - - // Locate 'act' ... skeep initial spaces, if any - int slen = (int)strlen(line); - int ka = 0; - while (ka < slen && line[ka] == 32) - ka++; - // skeep method - while (ka < slen && line[ka] != 32) - ka++; - // skeep spaces before 'act' - while (ka < slen && line[ka] == 32) - ka++; - // This is 'act' - line[ka] = '0'; - // Make sure there is a '\n' before writing - int sl = strlen(line); - if (line[sl-1] != '\n') { - if (sl >= kMAXPATHLEN -1) - line[sl-1] = '\n'; - else { - line[sl] = '\n'; - line[sl+1] = '\0'; - } - } - // Write it now - lseek(itab, pw, SEEK_SET); - while (write(itab, line, strlen(line)) < 0 - && GetErrno() == EINTR) - ResetErrno(); - // We are done - lseek(itab, 0, SEEK_END); - } - } - pw = pr; - } - - // unlock the file - lseek(itab, 0, SEEK_SET); - if (lockf(itab, F_ULOCK, (off_t) 1) == -1) { - ErrorInfo("RpdCleanupAuthTab: error unlocking %s", gRpdAuthTab.c_str()); - } - // closing file ... - close(itab); - - return retval; -} - -//////////////////////////////////////////////////////////////////////////////// -/// In tab file, cleanup (set inactive) entry at offset -/// 'OffSet' from remote PiD 'RemId' at 'Host'. -/// If Host="all" or RemId=0 discard all entries. -/// Return number of entries not cleaned properly ... - -int RpdCleanupAuthTab(const char *Host, int RemId, int OffSet) -{ - int retval = 0; - - if (gDebug > 2) - ErrorInfo("RpdCleanupAuthTab: Host: '%s', RemId:%d, OffSet: %d", - Host, RemId, OffSet); - - // Open file for update - int itab = -1; - if ((itab = open(gRpdAuthTab.c_str(), O_RDWR)) == -1) { - if (GetErrno() == ENOENT) { - if (gDebug > 0) - ErrorInfo("RpdCleanupAuthTab: file %s does not exist", - gRpdAuthTab.c_str()); - return -3; - } else { - ErrorInfo("RpdCleanupAuthTab: error opening %s (errno: %d)", - gRpdAuthTab.c_str(), GetErrno()); - return -1; - } - } - - // lock tab file - if (lockf(itab, F_LOCK, (off_t) 1) == -1) { - ErrorInfo("RpdCleanupAuthTab: error locking %s (errno: %d)", - gRpdAuthTab.c_str(), GetErrno()); - close(itab); - // return retval; - return -2; - } - if (gDebug > 0) - ErrorInfo("RpdCleanupAuthTab: file LOCKED" - " (Host: '%s', RemId:%d, OffSet: %d)", - Host, RemId, OffSet); - - // Now access entry or scan over entries - int pr = 0, pw = 0; - int nw, lsec, act, remid, pkey; - char line[kMAXPATHLEN]; - - // Clean all flag - int all = (!strcmp(Host, "all") || RemId == 0); - - // Set indicator - if (all || OffSet < 0) - pr = lseek(itab, 0, SEEK_SET); - else - pr = lseek(itab, OffSet, SEEK_SET); - if (pr < 0) { - ErrorInfo("RpdCleanupAuthTab: error lseeking %s (errno: %d)", - gRpdAuthTab.c_str(), GetErrno()); - close(itab); - // return retval; - return -2; - } - pw = pr; - while (reads(itab,line, sizeof(line))) { - - pr += strlen(line); - if (gDebug > 2) - ErrorInfo("RpdCleanupAuthTab: pr:%d pw:%d (line:%s) (pId:%d)", - pr, pw, line, gParentId); - - char dumm[kMAXPATHLEN], host[kMAXUSERLEN], user[kMAXUSERLEN], shmbuf[30]; - nw = sscanf(line, "%d %d %d %d %127s %127s %29s %4095s", - &lsec, &act, &pkey, &remid, host, user, shmbuf, dumm); - - if (nw > 5) { - if (all || OffSet > -1 || - (strstr(line,Host) && (RemId == remid))) { - - // Delete Public Key file - RpdDeleteKeyFile(pw); - - // Deactivate active entries: remote client has gone ... - if (act > 0) { - - // Locate 'act' ... skeep initial spaces, if any - int slen = (int)strlen(line); - int ka = 0; - while (ka < slen && line[ka] == 32) - ka++; - // skeep method - while (ka < slen && line[ka] != 32) - ka++; - // skeep spaces before 'act' - while (ka < slen && line[ka] == 32) - ka++; - // This is 'act' - line[ka] = '0'; - // Make sure there is a '\n' before writing - int sl = strlen(line); - if (line[sl-1] != '\n') { - if (sl >= kMAXPATHLEN -1) - line[sl-1] = '\n'; - else { - line[sl] = '\n'; - line[sl+1] = '\0'; - } - } - // Write it now - lseek(itab, pw, SEEK_SET); - while (write(itab, line, strlen(line)) < 0 - && GetErrno() == EINTR) - ResetErrno(); - if (all || OffSet < 0) - lseek(itab, pr, SEEK_SET); - else - lseek(itab, 0, SEEK_END); - } - } - } - pw = pr; - } - - // unlock the file - lseek(itab, 0, SEEK_SET); - if (lockf(itab, F_ULOCK, (off_t) 1) == -1) { - ErrorInfo("RpdCleanupAuthTab: error unlocking %s", gRpdAuthTab.c_str()); - } - // closing file ... - close(itab); - - return retval; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Check authentication entry in tab file. - -int RpdCheckAuthTab(int Sec, const char *User, const char *Host, int RemId, - int *OffSet) -{ - int retval = 0; - if (gDebug > 2) - ErrorInfo("RpdCheckAuthTab: analyzing: %d %s %s %d %d", Sec, User, - Host, RemId, *OffSet); - - // Check OffSet first - char *tkn = 0, *user =0; - int shmid; - bool goodOfs = RpdCheckOffSet(Sec,User,Host,RemId, - OffSet,&tkn,&shmid,&user); - if (gDebug > 2) - ErrorInfo("RpdCheckAuthTab: goodOfs: %d", goodOfs); - - // Notify the result of the check - int tag = 0; - if (gClientProtocol >= 10) { - if (goodOfs) { - if (gClientProtocol > 11) { - // Generate tag - RpdInitRand(); - while ((tag = rpd_rand()) == 1) ; // .ne.1 for backward comptibility - - // We will receive the user token next - NetSend(tag, kROOTD_AUTH); - } else - // We will receive the user token next - NetSend(1, kROOTD_AUTH); - } else { - // No authentication available for re-use - NetSend(0, kROOTD_AUTH); - // Cleanup and return: we need a new one ... - if (tkn) delete[] tkn; - if (user) delete[] user; - // ... no need to continue receiving the old token - return retval; - } - } - - // Now Receive Token - int ofs = *OffSet; - char *token = 0; - if (gRSAKey > 0) { - if (RpdSecureRecv(&token) == -1) { - ErrorInfo("RpdCheckAuthTab: problems secure-" - "receiving token %s", - "- may result in authentication failure "); - } - - } else { - EMessageTypes kind; - int lenToken = 9; - token = new char[lenToken]; - NetRecv(token, lenToken, kind); - if (kind != kMESS_STRING) - ErrorInfo - ("RpdCheckAuthTab: got msg kind: %d instead of %d (kMESS_STRING)", - kind, kMESS_STRING); - // Invert Token - for (int i = 0; i < (int) strlen(token); i++) { - token[i] = ~token[i]; - } - } - if (gDebug > 2) - ErrorInfo - ("RpdCheckAuthTab: received from client: token: '%s' ", - token); - - // Check tag, if there - if (token && strlen(token) > 8) { - // Create hex from tag - char tagref[9] = {0}; - SPrintf(tagref,9,"%08x",tag); - if (strncmp(token+8,tagref,8)) { - ErrorInfo("RpdCheckAuthTab: token tag does not match - failure"); - goodOfs = 0; - } else - // Drop tag - token[8] = 0; - } - - // Now check Token validity - if (goodOfs && token && RpdCheckToken(token, tkn)) { - retval = 1; - // Comunicate new offset to remote client - *OffSet = ofs; - } - - if (tkn) delete[] tkn; - if (token) delete[] token; - if (user) delete[] user; - - return retval; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Check offset received from client entry in tab file. - -int RpdCheckOffSet(int Sec, const char *User, const char *Host, int RemId, - int *OffSet, char **Token, int *ShmId, char **GlbsUser) -{ - int retval = 0; - bool goodOfs = 0; - int ofs = *OffSet >= 0 ? *OffSet : 0; - - if (gDebug > 2) - ErrorInfo("RpdCheckOffSet: analyzing: %d %s %s %d %d", Sec, User, - Host, RemId, *OffSet); - - // Open file - int itab = open(gRpdAuthTab.c_str(), O_RDWR); - if (itab == -1) { - if (GetErrno() == ENOENT) - ErrorInfo("RpcCheckOffSet: file %s does not exist", - gRpdAuthTab.c_str()); - else - ErrorInfo("RpcCheckOffSet: error opening %s (errno: %d)", - gRpdAuthTab.c_str(), GetErrno()); - return retval; - } - // lock tab file - if (lockf(itab, F_LOCK, (off_t) 1) == -1) { - ErrorInfo("RpcCheckOffSet: error locking %s (errno: %d)", - gRpdAuthTab.c_str(), GetErrno()); - close(itab); - return retval; - } - if (gDebug > 0) - ErrorInfo("RpdCheckOffSet: file LOCKED"); - - // File is open: set position at wanted location - if (lseek(itab, ofs, SEEK_SET) < 0) { - ErrorInfo("RpcCheckOffSet: error lseeking %s (errno: %d)", - gRpdAuthTab.c_str(), GetErrno()); - close(itab); - return retval; - } - - // Now read the entry - char line[kMAXPATHLEN]; - if (reads(itab,line, sizeof(line)) < 0) { - ErrorInfo("RpcCheckOffSet: error reading %d bytes from %s (errno: %d)", - sizeof(line), gRpdAuthTab.c_str(), GetErrno()); - close(itab); - return retval; - } - - // and parse its content according to auth method - int lsec, act, remid, shmid = -1; - char host[kMAXPATHLEN], usr[kMAXPATHLEN], subj[kMAXPATHLEN], - dumm[kMAXPATHLEN], tkn[20]; - int nw = - sscanf(line, "%d %d %d %d %4095s %4095s %19s %4095s", - &lsec, &act, &gRSAKey, &remid, host, usr, tkn, dumm); - if (gDebug > 2) - ErrorInfo("RpdCheckOffSet: found line: %s", line); - - if (nw > 5 && act > 0) { - if (lsec == Sec) { - if (lsec == 3) { - sscanf(line, "%d %d %d %d %4095s %4095s %d %4095s %19s %4095s", - &lsec, &act, &gRSAKey, &remid, host, usr, &shmid, subj, tkn, dumm); - if ((remid == RemId) - && !strcmp(host, Host) && !strcmp(subj, User)) - goodOfs = 1; - } else { - if ((remid == RemId) && - !strcmp(host, Host) && !strcmp(usr, User)) - goodOfs = 1; - } - } - } - if (!goodOfs) { - // Tab may have been cleaned in the meantime ... try a scan - lseek(itab, 0, SEEK_SET); - ofs = 0; - while (reads(itab, line, sizeof(line))) { - - nw = sscanf(line, "%d %d %d %d %4095s %4095s %19s %4095s", - &lsec, &act, &gRSAKey, &remid, host, usr, tkn, dumm); - if (gDebug > 2) - ErrorInfo("RpdCheckOffSet: found line: %s", line); - - if (nw > 5 && act > 0) { - if (lsec == Sec) { - if (lsec == 3) { - sscanf(line, "%d %d %d %d %4095s %4095s %d %4095s %19s %4095s", - &lsec, &act, &gRSAKey, &remid, host, usr, &shmid, subj, tkn, dumm); - if ((remid == RemId) - && !strcmp(host, Host) && !strcmp(subj, User)) { - goodOfs = 1; - goto found; - } - } else { - if ((remid == RemId) && - !strcmp(host, Host) && !strcmp(usr, User)) { - goodOfs = 1; - goto found; - } - } - } - } - } - } - - found: - // unlock the file - lseek(itab, 0, SEEK_SET); - if (lockf(itab, F_ULOCK, (off_t) 1) == -1) { - ErrorInfo("RpcCheckOffSet: error unlocking %s", - gRpdAuthTab.c_str()); - } - // closing file ... - close(itab); - - // Read public key - std::string pukfile = gRpdKeyRoot; - pukfile.append(ItoA(*OffSet)); - if (gDebug > 2) - ErrorInfo("RpdCheckOffSet: RSAKey ofs file: %d %d '%s' ", - gRSAKey, ofs, pukfile.c_str()); - - struct passwd *pw = getpwnam(usr); - if (pw) { - uid_t fromUid = getuid(); - uid_t fromEUid = geteuid(); - // The check must be done with 'usr' UIDs to prevent - // unauthorized users from forcing the server to read - // manipulated key files. - if (fromUid == 0) - if (setresuid(pw->pw_uid, pw->pw_uid, fromEUid) == -1) - // Since we could not set the user IDs, we will - // not trust the client - goodOfs = 0; - - // Get the key now - if (goodOfs) - if (RpdGetRSAKeys(pukfile.c_str(), 1) < 1) - goodOfs = 0; - - // Reset original IDs - if (getuid() != fromUid) - if (setresuid(fromUid, fromEUid, pw->pw_uid) == -1) - goodOfs = 0; - - } else { - // Since we could not set the user IDs, we will - // not trust the client - goodOfs = 0; - if (gDebug > 0) - ErrorInfo("RpdCheckOffSet: error in getpwname(%s) (errno: %d)", - usr,GetErrno()); - } - - if (gDebug > 2) - ErrorInfo("RpdCheckOffSet: goodOfs: %d (active: %d)", - goodOfs, act); - - // Comunicate new offset to remote client - if (goodOfs) { - - // Rename the key file, if needed - if (*OffSet > 0 && *OffSet != ofs) { - if (RpdRenameKeyFile(*OffSet,ofs) > 0) { - goodOfs = 0; - // Error: set entry inactive - RpdCleanupAuthTab(Host,RemId,ofs); - } - } - - *OffSet = ofs; - // return token if requested - if (Token) { - const size_t tokenSize = strlen(tkn)+1; - *Token = new char[tokenSize]; - strlcpy(*Token,tkn,tokenSize); - } - if (Sec == 3) { - if (GlbsUser) { - const size_t glbsUserSize = strlen(usr)+1; - *GlbsUser = new char[glbsUserSize]; - strlcpy(*GlbsUser,usr,glbsUserSize); - } - if (ShmId) - *ShmId = shmid; - } - } - - return goodOfs; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Rename public file with new offset -/// Returns: 0 if OK -/// 1 if problems renaming - -int RpdRenameKeyFile(int oldofs, int newofs) -{ - int retval = 0; - - // Old name - std::string oldname = gRpdKeyRoot; - oldname.append(ItoA(oldofs)); - // New name - std::string newname = gRpdKeyRoot; - newname.append(ItoA(newofs)); - - if (rename(oldname.c_str(), newname.c_str()) == -1) { - if (gDebug > 0) - ErrorInfo("RpdRenameKeyFile: error renaming key file" - " %s to %s (errno: %d)", - oldname.c_str(),newname.c_str(),GetErrno()); - retval = 2; - } - - return retval; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Check token validity. - -bool RpdCheckToken(char *token, char *tknref) -{ - // Get rid of '\n' - char *s = strchr(token, '\n'); - if (s) - *s = 0; - s = strchr(tknref, '\n'); - if (s) - *s = 0; - -#ifndef R__NOCRYPT - char *tkn_crypt = crypt(token, tknref); - int tlen = 13; -#else - char *tkn_crypt = rpdcrypt(token,gRndmSalt.c_str()); - int tlen = 16; -#endif - - if (gDebug > 2) - ErrorInfo("RpdCheckToken: ref:'%s' crypt:'%s'", tknref, tkn_crypt); - - if (!strncmp(tkn_crypt, tknref, tlen)) - return 1; - else - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Check the requiring subject has already authenticated during this session -/// and its 'ticket' is still valid. - -int RpdReUseAuth(const char *sstr, int kind) -{ - int lenU, offset, opt; - gOffSet = -1; - gExistingAuth = 0; - int auth= 0; - - if (gDebug > 2) - ErrorInfo("RpdReUseAuth: analyzing: %s, %d", sstr, kind); - - char user[64]; - - // kClear - if (kind == kROOTD_USER) { - if (!(gReUseAllow & gAUTH_CLR_MSK)) { - return 0; // re-authentication required by administrator - } - gSec = 0; - // Decode subject string - sscanf(sstr, "%d %d %d %d %63s", &gRemPid, &offset, &opt, &lenU, user); - user[lenU] = '\0'; - if ((gReUseRequired = (opt & kAUTH_REUSE_MSK))) { - gOffSet = offset; - if (gRemPid > 0 && gOffSet > -1) { - auth = - RpdCheckAuthTab(gSec, user, gOpenHost.c_str(), gRemPid, &gOffSet); - } - if ((auth == 1) && (offset != gOffSet)) - auth = 2; - // Fill gUser and free allocated memory - strlcpy(gUser, user, sizeof(gUser)); - } - } - - // Flag if existing token has been re-used - if (auth > 0) - gExistingAuth = 1; - - // Return value - return auth; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Check if required auth method is allowed for 'Host'. -/// If 'yes', returns 0, if 'no', returns 1, the number of allowed -/// methods in NumAllow, and the codes of the allowed methods (in order -/// of preference) in AllowMeth. Memory for AllowMeth must be allocated -/// outside. Directives read from (in decreasing order of priority): -/// $ROOTDAEMONRC, $HOME/.rootdaemonrc (privately startd daemons only) -/// or $ROOTETCDIR/system.rootdaemonrc. - -int RpdCheckAuthAllow(int Sec, const char *Host) -{ - int retval = 1, found = 0; - - std::string theDaemonRc; - - // Check if a non-standard file has been requested - if (std::getenv("ROOTDAEMONRC")) - theDaemonRc = std::getenv("ROOTDAEMONRC"); - - if (theDaemonRc.length() <= 0) { - if (getuid()) { - // Check if user has a private daemon access file ... - struct passwd *pw = getpwuid(getuid()); - if (pw != 0) { - theDaemonRc = std::string(pw->pw_dir).append("/"); - theDaemonRc.append(gDaemonRc); - } else { - if (std::getenv("ROOTETCDIR")) { - theDaemonRc = std::string(std::getenv("ROOTETCDIR")).append("/system"); - theDaemonRc.append(gDaemonRc); - } else - theDaemonRc = std::string("/etc/root/system").append(gDaemonRc); - } - } else { - // If running as super-user, check system file only - if (std::getenv("ROOTETCDIR")) { - theDaemonRc = std::string(std::getenv("ROOTETCDIR")).append("/system"); - theDaemonRc.append(gDaemonRc); - } else - theDaemonRc = std::string("/etc/root/system").append(gDaemonRc); - } - } - if (gDebug > 2) - ErrorInfo("RpdCheckAuthAllow: Checking file: %s for meth:%d" - " host:%s (gNumAllow: %d)", - theDaemonRc.c_str(), Sec, Host, gNumAllow); - - // Check if info already loaded (not first call ...) - if (gMethInit == 1) { - - // Look for the method in the allowed list and flag this method - // as tried, if found ... - int newtry = 0, i; - for (i = 0; i < gNumAllow; i++) { - if (gTriedMeth[i] == 0 && gAllowMeth[i] == Sec) { - newtry = 1; - gTriedMeth[i] = 1; - gNumLeft--; - } - } - if (newtry == 0) { - ErrorInfo - ("RpdCheckAuthAllow: new auth method proposed by %s", - " client not in the list or already attempted"); - return retval; - } - retval = 0; - - } else { - - // Open file - FILE *ftab = fopen(theDaemonRc.c_str(), "r"); - if (ftab == 0) { - if (GetErrno() == ENOENT) - ErrorInfo("RpdCheckAuthAllow: file %s does not exist", - theDaemonRc.c_str()); - else - ErrorInfo("RpdCheckAuthAllow: error opening %s (errno: %d)", - theDaemonRc.c_str(), GetErrno()); - } - // Now read the entry - char line[kMAXPATHLEN], host[kMAXPATHLEN], rest[kMAXPATHLEN], - cmth[kMAXPATHLEN]; - int nmet = 0, mth[6] = { 0 }; - - int cont = 0, jm = -1; - while (ftab && fgets(line, sizeof(line), ftab)) { - int i; - if (line[0] == '#') - continue; // skip comment lines - if (line[strlen(line) - 1] == '\n') - line[strlen(line) - 1] = '\0'; // get rid of '\n', if any ... - // Analyze the line now ... - int nw = 0; - char *pstr = line; - // Check if a continuation line - if (cont == 1) { - cont = 0; - strlcpy(rest, pstr, kMAXPATHLEN); - } else { - jm = -1; - // Get 'host' first ... - nw = sscanf(pstr, "%4095s %4095s", host, rest); - if (nw < 2) - continue; // no method defined for this host - pstr = line + strlen(host) + 1; - - // Check if a service is specified - char *pcol = strstr(host, ":"); - if (pcol) { - if (!strstr(pcol+1, gServName[gService].c_str())) - continue; - else - host[(int)(pcol-host)] = '\0'; - } - if (!host[0]) - strlcpy(host, "default", kMAXPATHLEN); - - if (gDebug > 2) - ErrorInfo("RpdCheckAuthAllow: found host: %s ", host); - - if (strcmp(host, "default")) { - // now check validity of 'host' format - if (!RpdCheckHost(Host,host)) { - goto next; - } - } else { - // This is a default entry: ignore it if a host-specific entry was already - // found, analyse it otherwise ... - if (found == 1) - goto next; - } - - // Reset mth[kMAXSEC] - nmet = 0; - for (i = 0; i < kMAXSEC; i++) { - mth[i] = -1; - } - - } - - // We are at the end and there will be a continuation line ... - if (rest[0] == '\\') { - cont = 1; - continue; - } - - while (pstr != 0) { - int tmet = -1; - char *pd = 0, *pd2 = 0; - cmth[0] = '\0'; - rest[0] = '\0'; - nw = sscanf(pstr, "%4095s %4095s", cmth, rest); - if (!strcmp(cmth, "none")) { - nmet = 0; - goto nexti; - } - pd = strchr(cmth, ':'); - // Parse the method - char tmp[20]; - if (pd != 0) { - int mlen = pd - cmth; - strncpy(tmp, cmth, mlen); - tmp[mlen] = '\0'; - } else { - strlcpy(tmp, cmth, sizeof(tmp)); - } - - if (strlen(tmp) > 1) { - - for (tmet = 0; tmet < kMAXSEC; tmet++) { - if (!rpdstrcasecmp(gAuthMeth[tmet].c_str(), tmp)) - break; - } - if (tmet < kMAXSEC) { - if (gDebug > 2) - ErrorInfo("RpdCheckAuthAllow: tmet %d", tmet); - } else { - if (gDebug > 1) - ErrorInfo("RpdCheckAuthAllow: unknown methods" - " %s - ignore", tmp); - goto nexti; - } - - } else { - tmet = atoi(tmp); - } - jm = -1; - if (gDebug > 2) - ErrorInfo("RpdCheckAuthAllow: found method %d (have?:%d)", - tmet, (tmet >= 0 && tmet < kMAXSEC) ? gHaveMeth[tmet] : 0); - if (tmet >= 0 && tmet < kMAXSEC) { - if (gHaveMeth[tmet] == 1) { - int ii; - for (ii = 0; ii < nmet; ii++) { - if (mth[ii] == tmet) { - jm = ii; - } - } - } else - goto nexti; - } else - goto nexti; - if (jm == -1) { - // New method ... - mth[nmet] = tmet; - jm = nmet; - nmet++; - } - // Now parse users list, if any ... - while (pd != 0 && (int) (pd[1]) != 32) { - pd2 = strchr(pd + 1, ':'); - if (pd[1] == '-') { - pd += 2; - // Ignore - if (gUserIgnore[mth[jm]] == 0) { - gUserIgnLen[mth[jm]] = kMAXPATHLEN; - gUserIgnore[mth[jm]] = new char[gUserIgnLen[mth[jm]]]; - gUserIgnore[mth[jm]][0] = '\0'; - } - if (strlen(gUserIgnore[mth[jm]]) > - (gUserIgnLen[mth[jm]] - 10)) { - char *tmpUI = strdup(gUserIgnore[mth[jm]]); - free(gUserIgnore[mth[jm]]); - gUserIgnLen[mth[jm]] += kMAXPATHLEN; - gUserIgnore[mth[jm]] = new char[gUserIgnLen[mth[jm]]]; - strlcpy(gUserIgnore[mth[jm]], tmpUI, sizeof(gUserIgnLen[mth[jm]])); - free(tmpUI); - } - char usr[256]; - if (pd2 != 0) { - int ulen = pd2 - pd; - strncpy(usr, pd, ulen); - usr[ulen] = '\0'; - } else { - strlcpy(usr, pd, sizeof(usr)); - } - struct passwd *pw = getpwnam(usr); - if (pw != 0) - SPrintf(gUserIgnore[mth[jm]], gUserIgnLen[mth[jm]], "%s %d", - gUserIgnore[mth[jm]], (int)pw->pw_uid); - } else { - pd += 1; - if (pd[1] == '+') - pd += 1; - // Keep - if (gUserAllow[mth[jm]] == 0) { - gUserAlwLen[mth[jm]] = kMAXPATHLEN; - gUserAllow[mth[jm]] = new char[gUserAlwLen[mth[jm]]]; - gUserAllow[mth[jm]][0] = '\0'; - } - if (strlen(gUserAllow[mth[jm]]) > - (gUserAlwLen[mth[jm]] - 10)) { - char *tmpUI = strdup(gUserAllow[mth[jm]]); - free(gUserAllow[mth[jm]]); - gUserAlwLen[mth[jm]] += kMAXPATHLEN; - gUserAllow[mth[jm]] = new char[gUserAlwLen[mth[jm]]]; - strlcpy(gUserAllow[mth[jm]], tmpUI, sizeof(gUserAlwLen[mth[jm]])); - free(tmpUI); - } - char usr[256]; - if (pd2 != 0) { - int ulen = pd2 - pd; - strncpy(usr, pd, ulen); - usr[ulen] = '\0'; - } else { - strlcpy(usr, pd, sizeof(usr)); - } - struct passwd *pw = getpwnam(usr); - if (pw != 0) - SPrintf(gUserAllow[mth[jm]], gUserAlwLen[mth[jm]], "%s %d", - gUserAllow[mth[jm]], (int)pw->pw_uid); - } - pd = pd2; - } - // Get next item - nexti: - if (nw > 1 && (int) rest[0] != 92) { - pstr = strstr(pstr, rest); - } else { - if ((int) rest[0] == 92) - cont = 1; - pstr = 0; - } - } - if (gDebug > 2) { - ErrorInfo("RpdCheckAuthAllow: for host %s found %d methods", - host, nmet); - ErrorInfo("RpdCheckAuthAllow: %d %d %d %d %d %d", mth[0], - mth[1], mth[2], mth[3], mth[4], mth[5]); - } - // Found new entry matching: superseed previous result - found = 1; - retval = 1; - gNumAllow = gNumLeft = nmet; - for (i = 0; i < kMAXSEC; i++) { - gAllowMeth[i] = -1; - gTriedMeth[i] = 0; - if (i < gNumAllow) { - gAllowMeth[i] = mth[i]; - if (Sec == mth[i]) { - retval = 0; - gNumLeft--; - gTriedMeth[i] = 1; - } - } - } - next: - continue; - } - - // closing file ... - if (ftab) - fclose(ftab); - - // Host specific directives have been checked for ... - gMethInit = 1; - - // Use defaults if nothing found - if (!found) { - if (gDebug > 2) - ErrorInfo - ("RpdCheckAuthAllow: no specific or 'default' entry found: %s", - "using system defaults"); - int i; - for (i = 0; i < gNumAllow; i++) { - if (Sec == gAllowMeth[i]) { - retval = 0; - gNumLeft--; - gTriedMeth[i] = 1; - } - } - - } - - } - if (gDebug > 2) { - ErrorInfo - ("RpdCheckAuthAllow: returning: %d (gNumAllow: %d, gNumLeft:%d)", - retval, gNumAllow, gNumLeft); - int i, jm; - for (i = 0; i < kMAXSEC; i++) { - jm = gAllowMeth[i]; - if (gUserAlwLen[jm] > 0) - ErrorInfo("RpdCheckAuthAllow: users allowed for method %d: %s", - jm, gUserAllow[jm]); - } - for (i = 0; i < kMAXSEC; i++) { - jm = gAllowMeth[i]; - if (gUserIgnLen[jm] > 0) - ErrorInfo("RpdCheckAuthAllow: users ignored for method %d: %s", - jm, gUserIgnore[jm]); - } - } - - return retval; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Checks if 'host' is compatible with 'Host' taking into account -/// wild cards in the host name -/// Returns 1 if successful, 0 otherwise ... - -int RpdCheckHost(const char *Host, const char *host) -{ - int rc = 1; - - // Strings must be both defined - if (!Host || !host) - return 0; - - // If host is a just wild card accept it - if (!strcmp(host,"*")) - return 1; - - // Try now to understand whether it is an address or a name ... - int name = 0, i = 0; - for (i = 0; i < (int) strlen(host); i++) { - if ((host[i] < 48 || host[i] > 57) && - host[i] != '*' && host[i] != '.') { - name = 1; - break; - } - } - - // If ref host is an IP, get IP of Host - char *hh; - if (!name) { - hh = RpdGetIP(Host); - if (gDebug > 2) - ErrorInfo("RpdCheckHost: Checking Host IP: %s", hh); - } else { - const size_t hhSize = strlen(Host)+1; - hh = new char[hhSize]; - strlcpy(hh,Host,hhSize); - if (gDebug > 2) - ErrorInfo("RpdCheckHost: Checking Host name: %s", hh); - } - - // Check if starts with wild - // Starting with '.' defines a full (sub)domain - int sos = 0; - if (host[0] == '*' || host[0] == '.') - sos = 1; - - // Check if ends with wild - // Ending with '.' defines a name - int eos = 0, le = strlen(host); - if (host[le-1] == '*' || host[le-1] == '.') - eos = 1; - - int first= 1; - int ends= 0; - int starts= 0; - const size_t hSize = strlen(host)+1; - char *h = new char[hSize]; - strlcpy(h,host,hSize); - char *tk = strtok(h,"*"); - while (tk) { - - char *ps = strstr(hh,tk); - if (!ps) { - rc = 0; - break; - } - if (!sos && first && ps == hh) - starts = 1; - first = 0; - - if (ps == hh + strlen(hh) - strlen(tk)) - ends = 1; - - tk = strtok(0,"*"); - - } - delete[] h; - delete[] hh; - - if ((!sos || !eos) && !starts && !ends) - rc = 0; - - return rc; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Get IP address of 'host' as a string. String must be deleted by -/// the user. - -char *RpdGetIP(const char *host) -{ - struct hostent *h; - unsigned long ip; - unsigned char ip_fld[4]; - - // Check server name - if ((h = gethostbyname(host)) == 0) { - ErrorInfo("RpdGetIP: unknown host %s", host); - return 0; - } - // Decode ... - ip = ntohl(*(unsigned long *) h->h_addr_list[0]); - ip_fld[0] = (unsigned char) ((0xFF000000 & ip) >> 24); - ip_fld[1] = (unsigned char) ((0x00FF0000 & ip) >> 16); - ip_fld[2] = (unsigned char) ((0x0000FF00 & ip) >> 8); - ip_fld[3] = (unsigned char) ((0x000000FF & ip)); - - // Prepare output - char *output = new char[20]; - SPrintf(output, 20, "%d.%d.%d.%d", - ip_fld[0], ip_fld[1], ip_fld[2], ip_fld[3]); - - // return - return output; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Send list of authentication methods not yet tried. - -void RpdSendAuthList() -{ - if (gDebug > 2) - ErrorInfo("RpdSendAuthList: analyzing (gNumLeft: %d)", gNumLeft); - - // Send Number of methods left - NetSend(gNumLeft, kROOTD_NEGOTIA); - - if (gNumLeft > 0) { - int i = 0; - std::string alist; - char cm[5]; - for (i = 0; i < gNumAllow; i++) { - if (gDebug > 2) - ErrorInfo("RpdSendAuthList: gTriedMeth[%d]: %d", i, - gTriedMeth[i]); - if (gTriedMeth[i] == 0) { - SPrintf(cm, 5, " %d",gAllowMeth[i]); - alist.append(cm); - } - } - NetSend(alist.c_str(), alist.length() + 1, kMESS_STRING); - if (gDebug > 2) - ErrorInfo("RpdSendAuthList: sent list: %s", alist.c_str()); - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// Authenticate via Kerberos. - -int RpdKrb5Auth(const char *) -{ - ::Error("RpdKrb5Auth", "Kerberos5 no longer supported by ROOT"); - return 1; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Secure Remote Password protocol (no longer supported) - -int RpdSRPUser(const char *) -{ - ::Error("RpdSRPUser", "SRP no longer supported by ROOT"); - return 1; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Check if the requesting {host,user} can be granted immediate -/// login on the base of the information found in /etc/hosts.equiv -/// and/or $HOME/.rhosts. The two files must be trustable, i.e. owned -/// and modifiable only by 'root' and by 'user', respectively (0600). -/// Returns 1 in case access can be granted, 0 in any other case -/// (errout contains a code for error logging on the client side) -/// -/// NB: entries granting access in one of the two files cannot be -/// overriden in the other file; so, system admins cannot close -/// access from a host and user cannot stop access to their -/// account if the administrator has decided so; as an example, -/// if this entry is found in /etc/hosts.equiv -/// -/// remote.host.dom auser -/// -/// (allowing user named 'auser' from host 'remote.host.dom' to -/// login to any non-root local account without specifying a -/// password) the following entries in $home/.rhosts are ignored -/// -/// remote.host.dom -auser -/// -remote.host.dom -/// -/// and access to 'auser' is always granted. This is a "feature" -/// of ruserok. -/// - -int RpdCheckHostsEquiv(const char *host, const char *ruser, - const char *user, int &errout) -{ - int rc = 0; - - // Effective uid - int rootuser = 0; - if (!geteuid() && !getegid()) - rootuser = 1; - - // Check the files only if i) at least one exists; ii) those existing - // have the right permission settings - bool badfiles = 0; - int nfiles = 0; - - // Check system file /etc/hosts.equiv if non-root - char hostsequiv[20] = { "/etc/hosts.equiv" }; - if (!rootuser) { - - // Get info about the file ... - struct stat st; - if (stat(hostsequiv,&st) == -1) { - if (GetErrno() != ENOENT) { - ErrorInfo("RpdCheckHostsEquiv: cannot stat /etc/hosts.equiv" - " (errno: %d)",GetErrno()); - badfiles = 1; - } else - if (gDebug > 1) - ErrorInfo("RpdCheckHostsEquiv: %s does not exist", - hostsequiv); - } else { - - // Require 'root' ownership - if (st.st_uid || st.st_gid) { - if (gDebug > 0) - ErrorInfo("RpdCheckHostsEquiv: /etc/hosts.equiv not owned by" - " system (uid: %d, gid: %d)",st.st_uid,st.st_gid); - badfiles = 1; - } else { - - // Require WRITE permission only for owner - if ((st.st_mode & S_IWGRP) || (st.st_mode & S_IWOTH)) { - if (gDebug > 0) - ErrorInfo("RpdCheckHostsEquiv: group or others have write" - " permission on /etc/hosts.equiv: do not trust" - " it (g: %d, o: %d)", - (st.st_mode & S_IWGRP),(st.st_mode & S_IWOTH)); - badfiles = 1; - } else - // Good file - nfiles++; - } - } - } - - // Check local file - char rhosts[kMAXPATHLEN] = {0}; - if (!badfiles) { - - struct passwd *pw = getpwnam(user); - if (pw) { - int ldir = strlen(pw->pw_dir); - ldir = (ldir > kMAXPATHLEN - 9) ? (kMAXPATHLEN - 9) : ldir; - memcpy(rhosts,pw->pw_dir,ldir); - memcpy(rhosts+ldir,"/.rhosts",8); - rhosts[ldir+8] = 0; - if (gDebug > 2) - ErrorInfo("RpdCheckHostsEquiv: checking for user file %s ...",rhosts); - } else { - if (gDebug > 0) - ErrorInfo("RpdCheckHostsEquiv: cannot get user info with getpwnam" - " (errno: %d)",GetErrno()); - badfiles = 1; - } - - if (!badfiles) { - // Check the $HOME/.rhosts file ... ownership and protections - struct stat st; - if (stat(rhosts,&st) == -1) { - if (GetErrno() != ENOENT) { - ErrorInfo("RpdCheckHostsEquiv: cannot stat $HOME/.rhosts" - " (errno: %d)",GetErrno()); - badfiles = 1; - } else - ErrorInfo("RpdCheckHostsEquiv: %s/.rhosts does not exist", - pw->pw_dir); - } else { - - // Only use file when its access rights are 0600 - if (!S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || - (st.st_mode & 0777) != (S_IRUSR | S_IWUSR)) { - if (gDebug > 0) - ErrorInfo("RpdCheckHostsEquiv: unsecure permission setting" - " found for $HOME/.rhosts: 0%o (must be 0600)", - (st.st_mode & 0777)); - badfiles = 1; - } else - // Good file - nfiles++; - } - } - } - - // if files are not available or have wrong permissions or are - // not accessible, give up - if (!nfiles) { - if (gDebug > 0) - ErrorInfo("RpdCheckHostsEquiv: no files to check"); - errout = 1; - if (badfiles) { - if (gDebug > 0) - ErrorInfo("RpdCheckHostsEquiv: config files cannot be used" - " (check permissions)"); - errout = 2; - } - return rc; - } - - // Ok, now use ruserok to find out if {host,ruser,user} - // is trusted -#if defined(__sgi) || defined(_AIX) - if (ruserok((char*)host,rootuser,(char*)ruser,(char*)user) == 0) { -#else - if (ruserok(host,rootuser,ruser,user) == 0) { -#endif - if (gDebug > 0) - ErrorInfo("RpdCheckHostsEquiv: remote user %s authorized to" - " access %s's area",ruser,user); - rc = 1; - } else { - if (gDebug > 0) - ErrorInfo("RpdCheckHostsEquiv: no special permission from" - " %s or %s",hostsequiv,rhosts); - errout = 3; - } - - return rc; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Check received user's password against password in $HOME/.rootdpass. -/// The password is retrieved in RpdUser and temporarly saved in gPasswd. -/// Returns 1 in case of success authentication, 0 otherwise. - -int RpdCheckSpecialPass(const char *passwd) -{ - // Check inputs - if (!passwd) - return 0; - - // and the saved the password - if (strlen(gPasswd) <= 0) - return 0; - - // Ok, point to the saved passwd (retrieved in RpdUser) - char *rootdpass = gPasswd; - int n = 0; - - if (gClientProtocol > 8 && gSaltRequired > 0) { - n = strlen(rootdpass); - if (strncmp(passwd, rootdpass, n + 1) != 0) { - if (gDebug > 0) - ErrorInfo("RpdCheckSpecialPass: wrong password"); - rpdmemset((volatile void *)rootdpass,0,n); - return 0; - } - } else { -#ifndef R__NOCRYPT - char *pass_crypt = crypt(passwd, rootdpass); -#else - char *pass_crypt = (char *)passwd; -#endif - n = strlen(rootdpass); - if (strncmp(pass_crypt, rootdpass, n+1) != 0) { - if (gDebug > 0) - ErrorInfo("RpdCheckSpecialPass: wrong password"); - rpdmemset((volatile void *)rootdpass,0,n); - return 0; - } - } - - if (gDebug > 0) - ErrorInfo - ("RpdCheckSpecialPass: user %s authenticated via ~/.rootdpass", - gUser); - - rpdmemset((volatile void *)rootdpass,0,n); - return 1; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Check user's password. - -int RpdPass(const char *pass, int errheq) -{ - char passwd[128]; - char *passw; - char *pass_crypt; - struct passwd *pw; -#ifdef R__SHADOWPW - struct spwd *spw; -#endif - int afs_auth = 0; - - if (gDebug > 2) - ErrorInfo("RpdPass: Enter (pass length: %d)", (int)strlen(pass)); - - int auth = 0; - errheq = (errheq > -1 && errheq < 4) ? errheq : 0; - if (!*gUser) { - if (gClientProtocol > 11) - NetSend(gUsrPwdErr[0][errheq], kROOTD_ERR); - else - NetSend(kErrFatal, kROOTD_ERR); - if (gDebug > 0) - ErrorInfo("RpdPass: user needs to be specified first"); - return auth; - } - - if (!pass) { - if (gClientProtocol > 11) - NetSend(gUsrPwdErr[1][errheq], kROOTD_ERR); - else - NetSend(kErrNoPasswd, kROOTD_ERR); - if (gDebug > 0) - ErrorInfo("RpdPass: no password specified"); - return auth; - } - int n = strlen(pass); - // Passwd length should be in the correct range ... - if (!n) { - if (gClientProtocol > 11) - NetSend(gUsrPwdErr[1][errheq], kROOTD_ERR); - else - NetSend(kErrBadPasswd, kROOTD_ERR); - if (gDebug > 0) - ErrorInfo("RpdPass: null passwd not allowed"); - return auth; - } - if (n > (int) sizeof(passwd)) { - if (gClientProtocol > 11) - NetSend(gUsrPwdErr[1][errheq], kROOTD_ERR); - else - NetSend(kErrBadPasswd, kROOTD_ERR); - if (gDebug > 0) - ErrorInfo("RpdPass: passwd too long"); - return auth; - } - // Inversion is done in RpdUser, if needed - strlcpy(passwd, pass, sizeof(passwd)); - - // Special treatment for anonimous ... - if (gAnon) { - strlcpy(gPasswd, passwd, sizeof(gPasswd)); - goto authok; - } - // ... and SpecialPass ... - if (RpdCheckSpecialPass(passwd)) { - goto authok; - } - // Get local passwd info for gUser - if (!(pw = getpwnam(gUser))) { - ErrorInfo("RpdPass: getpwnam failed!"); - return auth; - } - -#ifdef R__SHADOWPW - // System V Rel 4 style shadow passwords - if ((spw = getspnam(gUser)) == 0) { - if (gDebug > 0) - ErrorInfo("RpdPass: Shadow passwd not available for user %s", - gUser); - passw = pw->pw_passwd; - } else - passw = spw->sp_pwdp; -#else - passw = pw->pw_passwd; -#endif -#ifndef R__NOCRYPT - if (gClientProtocol <= 8 || !gSaltRequired) { - char salt[20] = {0}; - int lenS = 2; - if (!strncmp(passw, "$1$", 3)) { - // Shadow passwd - char *pd = strstr(passw + 4, "$"); - lenS = (int) (pd - passw); - strncpy(salt, passw, lenS); - } else - strncpy(salt, passw, lenS); - salt[lenS] = 0; - pass_crypt = crypt(passwd, salt); // Comment this - } else { - pass_crypt = passwd; - } -#else - pass_crypt = passwd; -#endif - n = strlen(passw); - if (strncmp(pass_crypt, passw, n + 1) != 0) { - if (gClientProtocol > 11) - NetSend(gUsrPwdErr[1][errheq], kROOTD_ERR); - else - NetSend(kErrBadPasswd, kROOTD_ERR); - if (gDebug > 0) - ErrorInfo("RpdPass: invalid password for user %s", gUser); - return auth; - } - if (gDebug > 2) - ErrorInfo("RpdPass: valid password for user %s", gUser); - - authok: - auth = afs_auth ? 5 : 1; - gSec = 0; - - if (gClientProtocol > 8) { - // Set an entry in the auth tab file for later (re)use, if required ... - int offset = -1; - char *token = 0; - char line[kMAXPATHLEN]; - if ((gReUseAllow & gAUTH_CLR_MSK) && gReUseRequired) { - - SPrintf(line, kMAXPATHLEN, "0 1 %d %d %s %s", - gRSAKey, gRemPid, gOpenHost.c_str(), gUser); - if (!afs_auth) - offset = RpdUpdateAuthTab(1, line, &token); - if (gDebug > 2) - ErrorInfo("RpdPass: got offset %d", offset); - - // Comunicate login user name to client - SPrintf(line, kMAXPATHLEN, "%s %d", gUser, offset); - if (gDebug > 2) - ErrorInfo("RpdPass: sending back line %s", line); - NetSend(strlen(line), kROOTD_PASS); // Send message length first - NetSend(line, kMESS_STRING); - - if (offset > -1) { - if (gDebug > 2) - ErrorInfo("RpdPass: sending token %s (Crypt: %d)", token, - gCryptRequired); - if (gCryptRequired) { - // Send over the token - if (RpdSecureSend(token) == -1) { - if (gDebug > 0) - ErrorInfo("RpdPass: problems secure-sending token" - " - may result in corrupted token"); - } - } else { - // Send token inverted - for (int i = 0; i < (int) strlen(token); i++) { - token[i] = ~token[i]; - } - NetSend(token, kMESS_STRING); - } - delete[] token; - } - gOffSet = offset; - - } else { - // Comunicate login user name to client - SPrintf(line, kMAXPATHLEN, "%s -1", gUser); - if (gDebug > 2) - ErrorInfo("RpdPass: sending back line %s", line); - NetSend(strlen(line), kROOTD_PASS); // Send message length first - NetSend(line, kMESS_STRING); - } - } - - return auth; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Prepare for globus authentication: check hostcer.conf and get -/// the credential handle. This is run once at daemon start-up - -int RpdGlobusInit() -{ - ::Error("RpdGlobusInit", "Globus is no longer supported by ROOT"); - return 1; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Authenticate via Globus. - -int RpdGlobusAuth(const char *) -{ - ::Error("RpdGlobusInit", "Globus is no longer supported by ROOT"); - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -/// RFIO protocol (no longer supported by ROOT) - -int RpdRfioAuth(const char *) -{ - ::Error("RpdRfioAuth", "RfioAuth no longer supported by ROOT"); - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Terminate correctly by cleaning up the auth table and closing the file. -/// Called upon receipt of a kROOTD_CLEANUP and on SIGPIPE. - -void RpdAuthCleanup(const char *sstr, int opt) -{ - int rpid = 0, sec = -1, offs = -1, nw = 0; - char usr[64] = {0}; - if (sstr) - nw = sscanf(sstr, "%d %d %d %63s", &rpid, &sec, &offs, usr); - - // Turn back to superuser for cleaning, if the case - if (getuid() == 0) { - if (setresgid(0, 0, 0) == -1) - if (gDebug > 0) - ErrorInfo("RpdAuthCleanup: can't setgid to superuser"); - if (setresuid(0, 0, 0) == -1) - if (gDebug > 0) - ErrorInfo("RpdAuthCleanup: can't setuid to superuser"); - } - if (opt == 0) { - RpdCleanupAuthTab("all", 0, -1); // Cleanup everything (SIGPIPE) - ErrorInfo("RpdAuthCleanup: cleanup ('all',0) done"); - } else if (opt == 1) { - if (nw == 1) { - // host specific cleanup - RpdCleanupAuthTab(gOpenHost.c_str(), rpid, -1); - ErrorInfo("RpdAuthCleanup: cleanup ('%s',%d) done", - gOpenHost.c_str(), rpid); - } else if (nw == 4) { - // (host,usr,method) specific cleanup - if (RpdCheckOffSet(sec,usr,gOpenHost.c_str(),rpid,&offs,0,0,0)) { - RpdCleanupAuthTab(gOpenHost.c_str(), rpid, offs); - ErrorInfo("RpdAuthCleanup: cleanup (%s,%d,%d,%d,%s) done", - gOpenHost.c_str(), rpid, sec, offs, usr); - } else { - ErrorInfo("RpdAuthCleanup: cleanup not done: %s", - "wrong offset or already cleaned up"); - } - } - } -} - -//////////////////////////////////////////////////////////////////////////////// - -void RpdInitAuth() -{ - // Size check done in RpdUpdateAuthTab(1,...) - - // Reset - int i; - gNumAllow = gNumLeft = 0; - for (i = 0; i < kMAXSEC; i++) { - gAllowMeth[i] = -1; - gHaveMeth[i] = 1; - } - - // List of default authentication methods - RpdDefaultAuthAllow(); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Check configuration options and running daemons to build a default list -/// of secure methods. - -void RpdDefaultAuthAllow() -{ - if (gDebug > 2) - ErrorInfo("RpdDefaultAuthAllow: Enter"); - - // UsrPwdClear - gAllowMeth[gNumAllow] = 0; - gNumAllow++; - gNumLeft++; - - // No SRP method - gHaveMeth[1] = 0; - - // No Kerberos method - gHaveMeth[2] = 0; - - // No Globus method - gHaveMeth[3] = 0; - - if (gDebug > 2) { - int i; - std::string temp; - char cm[5]; - if (gNumAllow == 0) - temp.append("none"); - for (i = 0; i < gNumAllow; i++) { - SPrintf(cm, 5, " %3d",gAllowMeth[i]); - temp.append(cm); - } - ErrorInfo - ("RpdDefaultAuthAllow: default list of secure methods available: %s", - temp.c_str()); - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// Check the running of process 'daemon'. -/// Info got from 'ps ax'. - -int RpdCheckDaemon(const char *daemon) -{ - char cmd[kMAXPATHLEN] = { 0 }; - int ch, i = 0, cnt = 0; - - if (gDebug > 2) - ErrorInfo("RpdCheckDaemon: Enter ... %s", daemon); - - // Return if empty - if (daemon == 0 || !daemon[0]) - return cnt; - - // Build command - SPrintf(cmd, kMAXPATHLEN, "ps ax | grep %s 2>/dev/null", daemon); - - // Run it ... - FILE *fp = popen(cmd, "r"); - if (fp != 0) { - for (ch = fgetc(fp); ch != EOF; ch = fgetc(fp)) { - if (ch != 10) { - cmd[i++] = ch; - } else { - cmd[i] = '\0'; - if (strstr(cmd, "grep") == 0 && strstr(cmd, "rootd") == 0) { - cnt++; - } - i = 0; - } - } - if (i > 0) { - cmd[i] = '\0'; - cnt++; - } - pclose(fp); - if (gDebug > 2) - ErrorInfo("RpdCheckDaemon: found %d instances of daemon %s", - cnt, daemon); - - } else { - ErrorInfo("RpdCheckDaemon: problems executing cmd ..."); - } - return cnt; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Check user id. If user id is not equal to rootd's effective uid, user -/// will not be allowed access, unless effective uid = 0 (i.e. root). - -int RpdUser(const char *sstr) -{ - const int kMaxBuf = 256; - char recvbuf[kMaxBuf]; - EMessageTypes kind; - struct passwd *pw; - if (gDebug > 2) - ErrorInfo("RpdUser: Enter ... %s", sstr); - - int auth = 0; - - // Nothing can be done if empty message - if (!*sstr) { - NetSend(kErrBadUser, kROOTD_ERR); - ErrorInfo("RpdUser: received empty string"); - return auth; - } - // Parse input message - char user[kMAXUSERLEN] = {0}; - char ruser[kMAXUSERLEN] = {0}; - if (gClientProtocol > 8) { - int ulen, ofs, opt, rulen; - // Decode subject string - int nw = sscanf(sstr, "%d %d %d %d %63s %d %63s", - &gRemPid, &ofs, &opt, &ulen, user, &rulen, ruser); - ulen = (ulen >= kMAXUSERLEN) ? kMAXUSERLEN-1 : ulen; - rulen = (rulen >= kMAXUSERLEN) ? kMAXUSERLEN-1 : rulen; - user[ulen] = '\0'; - if (nw > 5) - ruser[rulen] = '\0'; - gReUseRequired = (opt & kAUTH_REUSE_MSK); - gCryptRequired = (opt & kAUTH_CRYPT_MSK); - gSaltRequired = (opt & kAUTH_SSALT_MSK); - gOffSet = ofs; -#ifdef R__SSL - if (gRSASSLKey) { - // Determine type of RSA key required - gRSAKey = (opt & kAUTH_RSATY_MSK) ? 2 : 1; - } else - gRSAKey = 1; -#else - gRSAKey = 1; -#endif - } else { - SPrintf(user,kMAXUSERLEN,"%s",sstr); - } - if (gDebug > 2) - ErrorInfo("RpdUser: gReUseRequired: %d gCryptRequired: %d gRSAKey: %d", - gReUseRequired, gCryptRequired, gRSAKey); - - ERootdErrors err = kErrNoUser; - if (gService == kROOTD) { - // Default anonymous account ... - if (!strcmp(user, "anonymous")) { - user[0] = '\0'; - strlcpy(user, "rootd", sizeof(user)); - } - } - - if ((pw = getpwnam(user)) == 0) { - NetSend(err, kROOTD_ERR); - ErrorInfo("RpdUser: user %s unknown", user); - return auth; - } - - // If server is not started as root and user is not same as the - // one who started rootd then authetication is not ok. - uid_t uid = getuid(); - if (uid && uid != pw->pw_uid) { - NetSend(kErrBadUser, kROOTD_ERR); - ErrorInfo("RpdUser: user not same as effective user of rootd"); - return auth; - } - - // Check if the administrator allows authentication - char cuid[20]; - SPrintf(cuid, 20, "%d", (int)pw->pw_uid); - if (gUserIgnLen[0] > 0 && strstr(gUserIgnore[0], cuid) != 0) { - NetSend(kErrNotAllowed, kROOTD_ERR); - ErrorInfo - ("RpdUser: user (%d,%s) not authorized to use UsrPwd method", - uid, pw->pw_name); - return auth; - } - if (gUserAlwLen[0] > 0 && strstr(gUserAllow[0], cuid) == 0) { - NetSend(kErrNotAllowed, kROOTD_ERR); - ErrorInfo - ("RpdUser: user (%d,%s) not authorized to use UsrPwd method", - uid, pw->pw_name); - return auth; - } - - // Check /etc/hosts.equiv and/or $HOME/.rhosts - int errheq = 0; - if (gCheckHostsEquiv && strlen(ruser)) { - if (RpdCheckHostsEquiv(gOpenHost.c_str(),ruser,user,errheq)) { - auth = 3; - strlcpy(gUser, user, sizeof(gUser)); - return auth; - } - } - - // Check if of type anonymous ... - if (!strcmp(pw->pw_shell, "/bin/false")) { - err = kErrNoAnon; - gAnon = 1; - gReUseRequired = 0; - } - - // Check if authorized - // If not anonymous, try to get passwd - // (if our system uses shadow passwds and we are not superuser - // we cannot authenticate users ...) - // char *passw = 0; - gPasswd[0] = 0; - char *passw = gPasswd; - int errrdp = 0; - if (gAnon == 0) { - - // Check ROOT specific passwd first - int rcsp = RpdRetrieveSpecialPass(user,gRootdPass.c_str(), - gPasswd,sizeof(gPasswd)); - if (rcsp < 0) - errrdp = (rcsp == -2) ? 3 : 0; - - if (!passw[0] || !strcmp(passw, "x")) { - -#ifdef R__SHADOWPW - struct spwd *spw = 0; - // System V Rel 4 style shadow passwords - if ((spw = getspnam(user)) == 0) { - if (gDebug > 0) { - ErrorInfo("RpdUser: Shadow passwd not accessible for user %s",user); - ErrorInfo("RpdUser: trying normal system passwd"); - } - } else - passw = spw->sp_pwdp; -#else - passw = pw->pw_passwd; -#endif - // Check if successful - if (!passw[0] || !strcmp(passw, "x")) { - if (gClientProtocol > 11) - NetSend(gUsrPwdErr[errrdp][errheq], kROOTD_ERR); - else - NetSend(kErrNotAllowed, kROOTD_ERR); - ErrorInfo("RpdUser: passwd hash not available for user %s", user); - ErrorInfo - ("RpdUser: user %s cannot be authenticated with this method", - user); - return auth; - } - } - } - // Ok: Save username and go to next steps - strlcpy(gUser, user, sizeof(gUser)); - - // Salt vars - char salt[30] = { 0 }; - char ctag[11] = { 0 }; - int rtag = 0; - int lenS = 0; - - if (gClientProtocol > 8) { - - // Prepare status flag to send back - if (gAnon == 1) { - // Anonymous user: we will receive a text pass in the form - // user@remote.host.dom - NetSend(-1, kROOTD_AUTH); - - } else { - - if (gCryptRequired) { - // Named user: first we receive a session public key - // Ask for the RSA key - NetSend(gRSAKey, kROOTD_RSAKEY); - - // Receive the key securely - if (RpdRecvClientRSAKey()) { - ErrorInfo("RpdUser: could not import a valid key -" - " switch off reuse for this session"); - gReUseRequired = 0; - } - - // We get a random tag - if (gClientProtocol > 11) { - RpdInitRand(); - rtag = rpd_rand(); - SPrintf(ctag, 11, "#%08x#",rtag); - } - - if (gSaltRequired) { - // The crypt man page says that alternative salts can be in the form '$1$...$'; - // but on Ubuntu 10.04 the salt are in the form '$j$...$' where j is 6 or other. - if (passw[0] == '$' && passw[2] == '$') { - // Shadow passwd - char *pd = strstr(passw + 4, "$"); - lenS = (int) (pd - passw); - strncpy(salt, passw, lenS); - salt[lenS] = 0; - } else { - lenS = 2; - strncpy(salt, passw, lenS); - salt[lenS] = 0; - } - - if (gDebug > 2) - ErrorInfo("RpdUser: salt: '%s' ",salt); - - // We add the random tag here - if (gClientProtocol > 11) { - strncat(salt, ctag, sizeof(salt) - sizeof(ctag) - 1); - salt[sizeof(salt) - 1] = '\0'; - } - - // Send it over encrypted - if (RpdSecureSend(salt) == -1) { - ErrorInfo("RpdUser: problems secure-sending salt -" - " may result in corrupted salt"); - } - } else { - if (gClientProtocol > 11) { - // We send the random tag here - if (RpdSecureSend(ctag) == -1) { - ErrorInfo("RpdUser: problems secure-sending rndmtag -" - " may result in corrupted rndmtag"); - } - } else - NetSend(0, kMESS_ANY); - } - } else { - // We continue the authentication process in clear - NetSend(0, kROOTD_AUTH); - } - } - - } else { - // If we are talking to a old client protocol - NetSend(0, kROOTD_AUTH); - } - - // Get the password hash or anonymous string - if (NetRecv(recvbuf, kMaxBuf, kind) < 0) { - NetSend(kErrFatal, kROOTD_ERR); - ErrorInfo("RpdUser: error receiving message"); - return auth; - } - if (kind != kROOTD_PASS) { - NetSend(kErrFatal, kROOTD_ERR); - ErrorInfo("RpdUser: received wrong message type: %d (expecting: %d)", - kind, (int) kROOTD_PASS); - return auth; - } - if (!strncmp(recvbuf,"-1",2)) { - if (gDebug > 0) - ErrorInfo("RpdUser: client did not send a password - return"); - return auth; - } - // Get passwd - char *passwd = 0; - int lpwd = 0; - if (gAnon == 0 && gClientProtocol > 8 && gCryptRequired) { - - // Receive encrypted pass or its hash - if (RpdSecureRecv(&passwd) == -1) { - ErrorInfo - ("RpdUser: problems secure-receiving pass hash - %s", - "may result in authentication failure"); - } - // Length of the password buffer - lpwd = strlen(passwd); - - // Check the random tag, if any - if (strlen(ctag)) { - - // Check first that there is enough space for the tag - int plen = lpwd; - if (plen > 9 && - passwd[plen-1] == '#' && passwd[plen-10] == '#') { - if (strncmp(ctag,&passwd[plen-10],10)) { - // The tag does not match; failure - if (gClientProtocol > 11) - NetSend(gUsrPwdErr[2][errheq], kROOTD_ERR); - else - NetSend(kErrBadPasswd, kROOTD_ERR); - ErrorInfo("RpdUser: rndm tag mis-match" - " (%s vs %s) - Failure",&passwd[plen-10],ctag); - delete[] passwd; - return auth; - } - - // Tag ok: drop it - plen -= 10; - passwd[plen] = 0; - - } else { - // The tag is not there or incomplete; failure - if (gClientProtocol > 11) - NetSend(gUsrPwdErr[2][errheq], kROOTD_ERR); - else - NetSend(kErrBadPasswd, kROOTD_ERR); - ErrorInfo("RpdUser: rndm tag missing or incomplete" - " (pw length: %d) - Failure", plen); - delete[] passwd; - return auth; - } - } - - // If we required an hash check that we got it - // (the client sends the passwd if the crypt version is different) - if (gSaltRequired && lenS) { - if (strncmp(passwd,salt,lenS)) - gSaltRequired = 0; - } - - } else { - - // Receive clear or anonymous pass - passwd = new char[strlen(recvbuf) + 1]; - - // Re-invert pass - int i, n = strlen(recvbuf); - for (i = 0; i < n; i++) - passwd[i] = ~recvbuf[i]; - passwd[i] = '\0'; - - if (gDebug > 2 && gAnon) - ErrorInfo("RpdUser: received anonymous pass: '%s'", passwd); - } - - // Check the passwd and login if ok ... - auth = RpdPass(passwd,errheq); - - // Erase memory used for password - passwd = (char *)rpdmemset((volatile void *)passwd,0,lpwd); - delete[] passwd; - - return auth; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Try a guess of the client protocol from what they sent over -/// the net ... - -int RpdGuessClientProt(const char *buf, EMessageTypes kind) -{ - if (gDebug > 2) - ErrorInfo("RpdGuessClientProt: Enter: buf: '%s', kind: %d", buf, - (int) kind); - - // Assume same version as us. - int proto = 9; - - // Clear authentication - if (kind == kROOTD_USER) { - char usr[64], rest[256]; - int ns = sscanf(buf, "%63s %255s", usr, rest); - if (ns == 1) - proto = 8; - } - - if (gDebug > 2) - ErrorInfo("RpdGuessClientProt: guess for gClientProtocol is %d", - proto); - - // Return the guess - return proto; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Allocates and Fills a NULL terminated buffer of length Len+1 with -/// Len random characters. -/// Return pointer to the buffer (to be deleted by the caller) -/// Opt = 0 any non dangerous char -/// 1 letters and numbers (upper and lower case) -/// 2 hex characters (upper and lower case) -/// 3 crypt like [a-zA-Z0-9./] - -char *RpdGetRandString(int Opt, int Len) -{ - unsigned int iimx[4][4] = { - { 0x0, 0xffffff08, 0xafffffff, 0x2ffffffe }, // Opt = 0 - { 0x0, 0x3ff0000, 0x7fffffe, 0x7fffffe }, // Opt = 1 - { 0x0, 0x3ff0000, 0x7e, 0x7e }, // Opt = 2 - { 0x0, 0x3ffc000, 0x7fffffe, 0x7fffffe } // Opt = 3 - }; - - const char *cOpt[4] = { "Any", "LetNum", "Hex", "Crypt" }; - - // Default option 0 - if (Opt < 0 || Opt > 3) { - Opt = 0; - if (gDebug > 2) - ErrorInfo("RpdGetRandString: Unknown option: %d : assume 0", Opt); - } - if (gDebug > 2) - ErrorInfo("RpdGetRandString: Enter ... Len: %d %s", Len, cOpt[Opt]); - - // Allocate buffer - char *buf = new char[Len + 1]; - - // Init Random machinery ... - if (!gRandInit) - RpdInitRand(); - - // randomize - int k = 0; - int i, j, l, m, frnd; - while (k < Len) { - frnd = rpd_rand(); - for (m = 7; m < 32; m += 7) { - i = 0x7F & (frnd >> m); - j = i / 32; - l = i - j * 32; - if ((iimx[Opt][j] & (1 << l))) { - buf[k] = i; - k++; - } - if (k == Len) - break; - } - } - - // NULL terminated - buf[Len] = 0; - if (gDebug > 2) - ErrorInfo("RpdGetRandString: got '%s' ", buf); - - return buf; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Get public key from file pubkey (Opt == 1) or string pubkey (Opt == 0). - -int RpdGetRSAKeys(const char *pubkey, int Opt) -{ - char str[kMAXPATHLEN] = { 0 }; - int keytype = 0; - - if (gDebug > 2) - ErrorInfo("RpdGetRSAKeys: enter: string len: %d, opt %d ", - gPubKeyLen, Opt); - - if (!pubkey) - return keytype; - - char *theKey = 0; - FILE *fKey = 0; - // Parse input type - if (Opt == 1) { - - // Ok, now open it - fKey = fopen(pubkey, "r"); - if (!fKey) { - if (GetErrno() == EACCES) { - struct passwd *pw = getpwuid(getuid()); - char *usr = 0; - if (pw) - usr = pw->pw_name; - ErrorInfo("RpdGetRSAKeys: access to key file %s denied" - " to user: %s", pubkey, (usr ? usr : (char *)"????")); - } else - ErrorInfo("RpdGetRSAKeys: cannot open key file" - " %s (errno: %d)", pubkey, GetErrno()); - return 0; - } - // Check first the permissions: should be 0600 - struct stat st; - if (fstat(fileno(fKey), &st) == -1) { - ErrorInfo("RpdGetRSAKeys: cannot stat descriptor %d" - " %s (errno: %d)", fileno(fKey), GetErrno()); - fclose(fKey); - return 0; - } - if (!S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || - (st.st_mode & 0777) != (S_IRUSR | S_IWUSR)) { - ErrorInfo("RpdGetRSAKeys: key file %s: wrong permissions" - " 0%o (should be 0600)", pubkey, (st.st_mode & 0777)); - fclose(fKey); - return 0; - } - gPubKeyLen = fread((void *)str,1,sizeof(str),fKey); - if (gDebug > 2) - ErrorInfo("RpdGetRSAKeys: length of the read key: %d",gPubKeyLen); - - // This the key - theKey = str; - } else { - // the key is the argument - theKey = (char *)pubkey; - } - - if (gPubKeyLen > 0) { - - // Skip spaces at beginning, if any - int k = 0; - while (theKey[k] == 32) k++; - - keytype = gRSAKey; - - // The format of keytype 1 is ### - char *pd1 = 0, *pd2 = 0, *pd3 = 0; - pd1 = strstr(theKey, "#"); - if (pd1) pd2 = strstr(pd1 + 1, "#"); - if (pd2) pd3 = strstr(pd2 + 1, "#"); - if (keytype == 1) { - if (!pd1 || !pd2 || !pd3) { - if (gDebug > 0) - ErrorInfo("RpdGetRSAKeys: bad format for keytype %d" - " - exit", keytype); - keytype = 0; - } - } - if (keytype == 1) { - - if (gDebug > 2) - ErrorInfo("RpdGetRSAKeys: keytype %d ", keytype); - - // Get ... - int l1 = (int) (pd2 - pd1 - 1); - char *n_exp_RSA = new char[l1 + 1]; - strncpy(n_exp_RSA, pd1 + 1, l1); - n_exp_RSA[l1] = 0; - if (gDebug > 2) - ErrorInfo("RpdGetRSAKeys: got %d bytes for n_exp_RSA", - strlen(n_exp_RSA)); - // Now - int l2 = (int) (pd3 - pd2 - 1); - char *d_exp_RSA = new char[l2 + 1]; - strncpy(d_exp_RSA, pd2 + 1, l2); - d_exp_RSA[l2] = 0; - if (gDebug > 2) - ErrorInfo("RpdGetRSAKeys: got %d bytes for d_exp_RSA", - strlen(d_exp_RSA)); - - rsa_num_sget(&gRSA_n, n_exp_RSA); - rsa_num_sget(&gRSA_d, d_exp_RSA); - - delete[] n_exp_RSA; - delete[] d_exp_RSA; - - } else if (keytype == 2){ - -#ifdef R__SSL - // try SSL - if (gDebug > 2) - ErrorInfo("RpdGetRSAKeys: keytype %d ", keytype); - - // Now set the key locally in BF form - BF_set_key(&gBFKey, gPubKeyLen, (const unsigned char *)theKey); -#else - if (gDebug > 0) { - ErrorInfo("RpdGetRSAKeys: not compiled with SSL support:" - " you should not have got here!"); - } -#endif - } - } - - if (fKey) - fclose(fKey); - - return keytype; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Save RSA public key into file for later use by other rootd. -/// Return: 0 if ok -/// 1 if not ok -/// 2 if not ok because file already exists and cannot be -/// overwritten - -int RpdSavePubKey(const char *PubKey, int OffSet, char *user) -{ - int retval = 0; - - if (gRSAKey == 0 || OffSet < 0) - return 1; - - std::string pukfile = gRpdKeyRoot; - pukfile.append(ItoA(OffSet)); - - // Unlink the file first - if (unlink(pukfile.c_str()) == -1) { - if (GetErrno() != ENOENT) - // File exists and cannot overwritten by this process - return 2; - } - - // Create file - int ipuk = -1; - ipuk = open(pukfile.c_str(), O_WRONLY | O_CREAT, 0600); - if (ipuk == -1) { - ErrorInfo("RpdSavePubKey: cannot open file %s (errno: %d)", - pukfile.c_str(),GetErrno()); - if (GetErrno() == ENOENT) - return 2; - else - return 1; - } - - // If root process set ownership of the pub key to the user - if (getuid() == 0) { - struct passwd *pw = getpwnam(user); - if (pw) { - if (fchown(ipuk,pw->pw_uid,pw->pw_gid) == -1) { - ErrorInfo("RpdSavePubKey: cannot change ownership" - " of %s (errno: %d)",pukfile.c_str(),GetErrno()); - retval = 1; - } - } else { - ErrorInfo("RpdSavePubKey: getpwnam failure (errno: %d)",GetErrno()); - retval = 1; - } - } - - // Write the key if no error occurred - if (retval == 0) { - while (write(ipuk, PubKey, gPubKeyLen) < 0 && GetErrno() == EINTR) - ResetErrno(); - } - - // close the file - close(ipuk); - - // Over - return retval; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Encode null terminated str using the session private key indcated by Key -/// and sends it over the network. -/// Returns number of bytes sent.or -1 in case of error. - -int RpdSecureSend(char *str) -{ - char buftmp[kMAXSECBUF]; - char buflen[20]; - - int ttmp = 0; - int nsen = -1; - - if (gRSAKey == 1) { - strncpy(buftmp, str, sizeof(buftmp) - 1); - buftmp[kMAXSECBUF - 1] = '\0'; - ttmp = rsa_encode(buftmp, strlen(buftmp) + 1, gRSA_n, gRSA_d); - } else if (gRSAKey == 2) { -#ifdef R__SSL - ttmp = strlen(str); - if ((ttmp % 8) > 0) // It should be a multiple of 8! - ttmp = ((ttmp + 8)/8) * 8; - unsigned char iv[8]; - memset((void *)&iv[0],0,8); - BF_cbc_encrypt((const unsigned char *)str, (unsigned char *)buftmp, - strlen(str), &gBFKey, iv, BF_ENCRYPT); -#else - ErrorInfo("RpdSecureSend: Not compiled with SSL support:" - " you should not have got here! - return"); -#endif - } else { - ErrorInfo("RpdSecureSend: Unknown key option (%d) - return", - gRSAKey); - } - - // Send the buffer now - SPrintf(buflen, 20, "%d", ttmp); - NetSend(buflen, kROOTD_ENCRYPT); - nsen = NetSendRaw(buftmp, ttmp); - if (gDebug > 4) - ErrorInfo("RpdSecureSend: sent %d bytes (expected: %d) - keytype: %d", - nsen, ttmp, gRSAKey); - - return nsen; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Receive buffer and decode it in str using key indicated by Key type. -/// Return number of received bytes or -1 in case of error. - -int RpdSecureRecv(char **str) -{ - char buftmp[kMAXSECBUF]; - char buflen[20]; - - int nrec = -1; - // We must get a pointer ... - if (!str) - return nrec; - - if (gDebug > 2) - ErrorInfo("RpdSecureRecv: enter ... (key is %d)", gRSAKey); - - EMessageTypes kind; - NetRecv(buflen, 20, kind); - int len = atoi(buflen); - if (gDebug > 4) - ErrorInfo("RpdSecureRecv: got len '%s' %d ", buflen, len); - if (!strncmp(buflen, "-1", 2)) - return nrec; - - // receive the buffer - nrec = NetRecvRaw(buftmp,len); - - // decode it - if (gRSAKey == 1) { - rsa_decode(buftmp, len, gRSA_n, gRSA_d); - if (gDebug > 2) - ErrorInfo("RpdSecureRecv: Local: decoded string is %d bytes long", - strlen(buftmp)); - - // Prepare output - const size_t strSize = strlen(buftmp) + 1; - *str = new char[strSize]; - strlcpy(*str, buftmp, strSize); - } else if (gRSAKey == 2) { -#ifdef R__SSL - unsigned char iv[8]; - memset((void *)&iv[0],0,8); - *str = new char[nrec + 1]; - BF_cbc_encrypt((const unsigned char *)buftmp, (unsigned char *)(*str), - nrec, &gBFKey, iv, BF_DECRYPT); - (*str)[nrec] = '\0'; -#else - ErrorInfo("RpdSecureRecv: Not compiled with SSL support:" - " you should not have got here! - return"); -#endif - } else { - ErrorInfo("RpdSecureRecv: Unknown key option (%d) - return", - gRSAKey); - } - - return nrec; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Generate a valid pair of private/public RSA keys to protect for -/// authentication password and token exchange -/// Returns 1 if a good key pair is not found after kMAXRSATRIES attempts -/// Returns 0 if a good key pair is found -/// If setrndinit = 1, no futher init of the random engine - -int RpdGenRSAKeys(int setrndinit) -{ - if (gDebug > 2) - ErrorInfo("RpdGenRSAKeys: enter"); - - // Init Random machinery ... - if (!gRandInit) - RpdInitRand(); - gRandInit = setrndinit; - -#ifdef R__NOCRYPT - // Generate a random salt - char *rsalt = RpdGetRandString(3,8); - if (rsalt) { - gRndmSalt = std::string(rsalt); - delete[] rsalt; - } else { - if (gDebug > 0) - ErrorInfo("RpdGenRSAKeys: could not generate random salt"); - } -#endif - -#ifdef R__SSL - // Generate also the SSL key - if (gDebug > 2) - ErrorInfo("RpdGenRSAKeys: Generate RSA SSL keys"); - - // Init SSL ... - SSL_library_init(); - - // ... and its error strings - SSL_load_error_strings(); - - // Load Ciphers - OpenSSL_add_all_ciphers(); - - // Number of bits for key - Int_t nbits = 1024; - - // Public exponent - Int_t pubex = 17; - - // Init random engine - char *rbuf = RpdGetRandString(0,40); - RAND_seed(rbuf,strlen(rbuf)); - - // Generate Key - gRSASSLKey = RSA_generate_key(nbits,pubex,0,0); - - // Bio for exporting the pub key - BIO *bkey = BIO_new(BIO_s_mem()); - - // Write public key to BIO - PEM_write_bio_RSAPublicKey(bkey,gRSASSLKey); - - // Read key from BIO to buf - Int_t sbuf = 2*RSA_size(gRSASSLKey); - char *kbuf = new char[sbuf]; - BIO_read(bkey,(void *)kbuf,sbuf); - BIO_free(bkey); - - // Prepare export - gRSAPubExport[1].len = sbuf; - gRSAPubExport[1].keys = new char[gRSAPubExport[1].len + 2]; - strncpy(gRSAPubExport[1].keys,kbuf,gRSAPubExport[1].len); - gRSAPubExport[1].keys[gRSAPubExport[1].len-1] = '\0'; - delete[] kbuf; - if (gDebug > 2) - ErrorInfo("RpdGenRSAKeys: SSL: export pub:\n%.*s", - gRSAPubExport[1].len,gRSAPubExport[1].keys); - - // We have at least one key - gRSAInit = 1; - -#endif - - // Sometimes some bunch is not decrypted correctly - // That's why we make retries to make sure that encryption/decryption - // works as expected - bool notOK = 1; - rsa_NUMBER p1, p2, rsa_n, rsa_e, rsa_d; - int l_n = 0, l_d = 0; -#if R__RSADEB - Int_t l_e = 0; - char buf[rsa_STRLEN]; -#endif - char buf_n[rsa_STRLEN], buf_e[rsa_STRLEN], buf_d[rsa_STRLEN]; - - int nAttempts = 0; - int thePrimeLen = kPRIMELENGTH; - int thePrimeExp = kPRIMEEXP + 5; // Prime probability = 1-0.5^thePrimeExp - while (notOK && nAttempts < kMAXRSATRIES) { - - nAttempts++; - if (gDebug > 2 && nAttempts > 1) { - ErrorInfo("RpdGenRSAKeys: retry no. %d",nAttempts); - srand(rpd_rand()); - } - - // Valid pair of primes - p1 = rsa_genprim(thePrimeLen, thePrimeExp); - p2 = rsa_genprim(thePrimeLen+1, thePrimeExp); - - // Retry if equal - int nPrimes = 0; - while (rsa_cmp(&p1, &p2) == 0 && nPrimes < kMAXRSATRIES) { - nPrimes++; - if (gDebug > 2) - ErrorInfo("RpdGenRSAKeys: equal primes: regenerate (%d times)",nPrimes); - srand(rpd_rand()); - p1 = rsa_genprim(thePrimeLen, thePrimeExp); - p2 = rsa_genprim(thePrimeLen+1, thePrimeExp); - } - -#if R__RSADEB - if (gDebug > 2) { - rsa_num_sput(&p1, buf, rsa_STRLEN); - ErrorInfo("RpdGenRSAKeys: local: p1: '%s' ", buf); - rsa_num_sput(&p2, buf, rsa_STRLEN); - ErrorInfo("RpdGenRSAKeys: local: p2: '%s' ", buf); - } -#endif - - // Generate keys - if (rsa_genrsa(p1, p2, &rsa_n, &rsa_e, &rsa_d)) { - if (gDebug > 0) - ErrorInfo("RpdGenRSAKeys: genrsa: attempt %d to generate" - " keys failed",nAttempts); - continue; - } - - // Determine their lengths - rsa_num_sput(&rsa_n, buf_n, rsa_STRLEN); - l_n = strlen(buf_n); - rsa_num_sput(&rsa_e, buf_e, rsa_STRLEN); -#if R__RSADEB - l_e = strlen(buf_e); -#endif - rsa_num_sput(&rsa_d, buf_d, rsa_STRLEN); - l_d = strlen(buf_d); - -#if R__RSADEB - if (gDebug > 2) { - ErrorInfo("RpdGenRSAKeys: local: n: '%s' length: %d", buf_n, l_n); - ErrorInfo("RpdGenRSAKeys: local: e: '%s' length: %d", buf_e, l_e); - ErrorInfo("RpdGenRSAKeys: local: d: '%s' length: %d", buf_d, l_d); - } -#endif - if (rsa_cmp(&rsa_n, &rsa_e) <= 0) - continue; - if (rsa_cmp(&rsa_n, &rsa_d) <= 0) - continue; - - // Now we try the keys - char test[2 * rsa_STRLEN] = "ThisIsTheStringTest01203456-+/"; - Int_t lTes = 31; - char *dumT = RpdGetRandString(0, lTes - 1); - strncpy(test, dumT, lTes); - delete[]dumT; - char buf[2 * rsa_STRLEN]; - if (gDebug > 3) - ErrorInfo("RpdGenRSAKeys: local: test string: '%s' ", test); - - // Private/Public - strncpy(buf, test, lTes); - buf[lTes] = 0; - - // Try encryption with private key - int lout = rsa_encode(buf, lTes, rsa_n, rsa_e); - if (gDebug > 3) - ErrorInfo("GenRSAKeys: local: length of crypted string: %d bytes", lout); - - // Try decryption with public key - rsa_decode(buf, lout, rsa_n, rsa_d); - buf[lTes] = 0; - if (gDebug > 3) - ErrorInfo("RpdGenRSAKeys: local: after private/public : '%s' ", buf); - - if (strncmp(test, buf, lTes)) - continue; - - // Public/Private - strncpy(buf, test, lTes); - buf[lTes] = 0; - - // Try encryption with public key - lout = rsa_encode(buf, lTes, rsa_n, rsa_d); - if (gDebug > 3) - ErrorInfo("RpdGenRSAKeys: local: length of crypted string: %d bytes ", - lout); - - // Try decryption with private key - rsa_decode(buf, lout, rsa_n, rsa_e); - buf[lTes] = 0; - if (gDebug > 3) - ErrorInfo("RpdGenRSAKeys: local: after public/private : '%s' ", buf); - - if (strncmp(test, buf, lTes)) - continue; - - notOK = 0; - } - - if (notOK) { - ErrorInfo("RpdGenRSAKeys: unable to generate good RSA key pair" - " (%d attempts)- return",kMAXRSATRIES); - return 1; - } - - // Save Private key - rsa_assign(&gRSAPriKey.n, &rsa_n); - rsa_assign(&gRSAPriKey.e, &rsa_e); - - // Save Public key - rsa_assign(&gRSAPubKey.n, &rsa_n); - rsa_assign(&gRSAPubKey.e, &rsa_d); - -#if R__RSADEB - if (gDebug > 2) { - // Determine their lengths - ErrorInfo("RpdGenRSAKeys: local: generated keys are:"); - ErrorInfo("RpdGenRSAKeys: local: n: '%s' length: %d", buf_n, l_n); - ErrorInfo("RpdGenRSAKeys: local: e: '%s' length: %d", buf_e, l_e); - ErrorInfo("RpdGenRSAKeys: local: d: '%s' length: %d", buf_d, l_d); - } -#endif - // Export form - gRSAPubExport[0].len = l_n + l_d + 4; - if (gRSAPubExport[0].keys) - delete[] gRSAPubExport[0].keys; - gRSAPubExport[0].keys = new char[gRSAPubExport[0].len]; - - gRSAPubExport[0].keys[0] = '#'; - memcpy(gRSAPubExport[0].keys + 1, buf_n, l_n); - gRSAPubExport[0].keys[l_n + 1] = '#'; - memcpy(gRSAPubExport[0].keys + l_n + 2, buf_d, l_d); - gRSAPubExport[0].keys[l_n + l_d + 2] = '#'; - gRSAPubExport[0].keys[l_n + l_d + 3] = 0; -#if R__RSADEB - if (gDebug > 2) - ErrorInfo("RpdGenRSAKeys: local: export pub: '%s'", - gRSAPubExport[0].keys); -#else - if (gDebug > 2) - ErrorInfo("RpdGenRSAKeys: local: export pub length: %d bytes", - gRSAPubExport[0].len); -#endif - - gRSAInit = 1; - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Generates local public/private RSA key pair -/// Send request for Client Public Key and Local public key -/// Receive encoded Client Key -/// Decode Client public key -/// NB: key is not saved to file here - -int RpdRecvClientRSAKey() -{ - if (gRSAInit == 0) { - // Generate Local RSA keys for the session - if (RpdGenRSAKeys(1)) { - ErrorInfo("RpdRecvClientRSAKey: unable to generate local keys"); - return 1; - } - } - - // Send server public key - int key = gRSAKey - 1; - NetSend(gRSAPubExport[key].keys, gRSAPubExport[key].len, kROOTD_RSAKEY); - - // Receive length of message with encode client public key - EMessageTypes kind; - char buflen[40]; - NetRecv(buflen, 20, kind); - gPubKeyLen = atoi(buflen); - if (gDebug > 3) - ErrorInfo("RpdRecvClientRSAKey: got len '%s' %d ", buflen, gPubKeyLen); - - int nrec = 0; - - if (gRSAKey == 1) { - - // Receive and decode encoded public key - nrec = NetRecvRaw(gPubKey, gPubKeyLen); - - rsa_decode(gPubKey, gPubKeyLen, gRSAPriKey.n, gRSAPriKey.e); - if (gDebug > 2) - ErrorInfo("RpdRecvClientRSAKey: Local: decoded string is %d bytes long ", - strlen(gPubKey)); - gPubKeyLen = strlen(gPubKey); - - } else if (gRSAKey == 2) { -#ifdef R__SSL - int ndec = 0; - int lcmax = RSA_size(gRSASSLKey); - char btmp[kMAXSECBUF]; - int nr = gPubKeyLen; - int kd = 0; - while (nr > 0) { - // Receive and decode encoded public key - nrec += NetRecvRaw(btmp, lcmax); - if ((ndec = RSA_private_decrypt(lcmax,(unsigned char *)btmp, - (unsigned char *)&gPubKey[kd], - gRSASSLKey, - RSA_PKCS1_PADDING)) < 0) { - char errstr[120]; - ERR_error_string(ERR_get_error(), errstr); - ErrorInfo("RpdRecvClientRSAKey: SSL: error: '%s' ",errstr); - } - nr -= lcmax; - kd += ndec; - } - gPubKeyLen = kd; -#else - if (gDebug > 0) - ErrorInfo("RpdRecvClientRSAKey: not compiled with SSL support" - ": you should not have got here!"); - return 1; -#endif - } else { - if (gDebug > 0) - ErrorInfo("RpdRecvClientRSAKey: unknown key type (%d)", gRSAKey); - } - - - // Import Key and Determine key type - if (RpdGetRSAKeys(gPubKey, 0) != gRSAKey) { - ErrorInfo("RpdRecvClientRSAKey:" - " could not import a valid key (type %d)",gRSAKey); - char *elogfile = new char[gRpdKeyRoot.length() + 11]; - SPrintf(elogfile, gRpdKeyRoot.length() + 11, "%.*serr.XXXXXX", (int)gRpdKeyRoot.length(), gRpdKeyRoot.c_str()); - mode_t oldumask = umask(0700); - int ielog = mkstemp(elogfile); - umask(oldumask); - if (ielog != -1) { - char line[kMAXPATHLEN] = {0}; - // - SPrintf(line,kMAXPATHLEN, - " + RpdRecvClientRSAKey: error importing key\n + type: %d\n" - " + length: %d\n + key: %s\n + (%d bytes were received)", - gRSAKey, gPubKeyLen, gPubKey, nrec); - while (write(ielog, line, strlen(line)) < 0 && GetErrno() == EINTR) - ResetErrno(); - close (ielog); - } - delete [] elogfile; - return 2; - } - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Init random machine. - -void RpdInitRand() -{ - const char *randdev = "/dev/urandom"; - - int fd; - unsigned int seed; - if ((fd = open(randdev, O_RDONLY)) != -1) { - if (gDebug > 2) - ErrorInfo("RpdInitRand: taking seed from %s", randdev); - if (read(fd, &seed, sizeof(seed))) {;} - close(fd); - } else { - if (gDebug > 2) - ErrorInfo("RpdInitRand: %s not available: using time()", randdev); - seed = time(0); //better use times() + win32 equivalent - } - srand(seed); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Handle user authentication. - -int RpdAuthenticate() -{ - char buf[kMAXRECVBUF]; - EMessageTypes kind; - -//#define R__DEBUG -#ifdef R__DEBUG - int debug = 1; - while (debug) - ; -#endif - - // Reset gAuth (if we have been called this means that we need - // to check at least that a valid authentication exists ...) - int auth = 0; - - while (!auth) { - - // Receive next - if (!gClientOld) { - if (NetRecv(buf, kMAXRECVBUF, kind) < 0) { - Error(gErr, -1, "RpdAuthenticate: error receiving message"); - return auth; - } - } else { - strlcpy(buf,gBufOld, sizeof(buf)); - kind = gKindOld; - gBufOld[0] = '\0'; - gClientOld = 0; - } - - // If this is a rootd contacted via a TNetXNGFile we need to - // receive again the buffer - if (gService == kROOTD && kind == kROOTD_PROTOCOL) { - if (NetRecv(buf, kMAXRECVBUF, kind) < 0) { - Error(gErr, -1, "RpdAuthenticate: error receiving message"); - return auth; - } - } - - // Decode the method ... - gAuthProtocol = RpdGetAuthMethod(kind); - - if (gDebug > 2) { - if (kind != kROOTD_PASS) { - ErrorInfo("RpdAuthenticate got: %d -- %s", kind, buf); - } else { - ErrorInfo("RpdAuthenticate got: %d ", kind); - } - } - - // Guess the client procotol if not received via Rootd - if (gClientProtocol == 0) - gClientProtocol = RpdGuessClientProt(buf, kind); - - // If the client supports it check if we accept the method proposed; - // if not send back the list of accepted methods, if any ... - if (gAuthProtocol != -1 && gClientProtocol > 8) { - - // Check if accepted ... - if (RpdCheckAuthAllow(gAuthProtocol, gOpenHost.c_str())) { - if (gNumAllow>0) { - if (gAuthListSent == 0) { - if (gDebug > 0) - ErrorInfo("Authenticate: %s method not" - " accepted from host: %s", - gAuthMeth[gAuthProtocol].c_str(), - gOpenHost.c_str()); - NetSend(kErrNotAllowed, kROOTD_ERR); - RpdSendAuthList(); - gAuthListSent = 1; - goto next; - } else { - Error(gErr,kErrNotAllowed,"Authenticate: method not" - " in the list sent to the client"); - return auth; - } - } else { - Error(gErr,kErrConnectionRefused,"Authenticate:" - " connection refused from host %s", gOpenHost.c_str()); - return auth; - } - } - - // Then check if a previous authentication exists and is valid - if ((auth = RpdReUseAuth(buf, kind))) - goto next; - } - - // Reset global variable - auth = 0; - - switch (kind) { - case kROOTD_USER: - auth = RpdUser(buf); - break; - case kROOTD_PASS: - auth = RpdPass(buf); - break; - case kROOTD_CLEANUP: - RpdAuthCleanup(buf,1); - ErrorInfo("RpdAuthenticate: authentication stuff cleaned - exit"); - // Fallthrough next case now to free the keys - case kROOTD_BYE: - RpdFreeKeys(); - return auth; - default: - Error(gErr,-1,"RpdAuthenticate: received bad opcode %d", kind); - return auth; - } - - if (gClientProtocol > 8) { - - // If failure prepare or continue negotiation - int doneg = (gAuthProtocol != -1 || kind == kROOTD_PASS); - if (gDebug > 2 && doneg) - ErrorInfo("RpdAuthenticate: kind:%d meth:%d auth:%d gNumLeft:%d", - kind, gAuthProtocol, auth, gNumLeft); - - // If authentication failure, check if other methods could be tried ... - if (auth == 0 && doneg) { - if (gNumLeft > 0) { - if (gAuthListSent == 0) { - RpdSendAuthList(); - gAuthListSent = 1; - } else - NetSend(-1, kROOTD_NEGOTIA); - } else { - NetSend(0, kROOTD_NEGOTIA); - Error(gErr, -1, "RpdAuthenticate: authentication failed"); - return auth; - } - } - } -next: - continue; - } - - return auth; -} -//////////////////////////////////////////////////////////////////////////////// -/// Free space allocated for encryption keys - -void RpdFreeKeys() -{ - if (gRSAPubExport[0].keys) delete[] gRSAPubExport[0].keys; - if (gRSAPubExport[1].keys) delete[] gRSAPubExport[1].keys; -#ifdef R__SSL - RSA_free(gRSASSLKey); -#endif -} - -//////////////////////////////////////////////////////////////////////////////// -/// Receives client protocol and returns daemon protocol. -/// Returns: 0 if ok -/// -1 if any error occurred -/// -2 if special action (e.g. cleanup): no need to continue - -int RpdProtocol(int ServType) -{ - int rc = 0; - -//#define R__DEBUG -#ifdef R__DEBUG - int debug = 1; - while (debug) - ; -#endif - - if (gDebug > 2) - ErrorInfo("RpdProtocol: Enter: server type = %d", ServType); - - int readbuf = 1; - EMessageTypes kind; - char proto[kMAXRECVBUF]; - - // For backward compatibility, for rootd we need to understand - // whether we are talking to a OLD client: protocol information is - // available only later on ... - int lbuf[2]; - if (NetRecvRaw(lbuf, sizeof(lbuf)) < 0) { - NetSend(kErrFatal, kROOTD_ERR); - ErrorInfo("RpdProtocol: error receiving message"); - return -1; - } - - // if kind is {kROOTD_PROTOCOL, kROOTD_CLEANUP} - // receive the rest - kind = (EMessageTypes) ntohl(lbuf[1]); - int len = ntohl(lbuf[0]); - if (gDebug > 1) - ErrorInfo("RpdProtocol: kind: %d %d",kind,len); - if (kind == kROOTD_PROTOCOL || kind == kROOTD_CLEANUP) { - // Receive the rest - char *buf = 0; - len -= sizeof(int); - if (gDebug > 1) - ErrorInfo("RpdProtocol: len: %d",len); - if (len) { - buf = new char[len]; - if (NetRecvRaw(buf, len) < 0) { - NetSend(kErrFatal, kROOTD_ERR); - ErrorInfo("RpdProtocol: error receiving message"); - delete[] buf; - return -1; - } - strlcpy(proto, buf, sizeof(proto)); - } else { - // Empty buffer - proto[0] = '\0'; - } - if (gDebug > 1) - ErrorInfo("RpdProtocol: proto buff: %s", buf ? buf : "---"); - // Copy buffer for later use - readbuf = 0; - if (buf) delete[] buf; - } else if (ServType == kROOTD && kind == 0 && len == 0) { - // TNetFile via TNetXNGFile: receive client protocol - // read first next 12 bytes and discard them - int llen = 12; - char *buf = new char[llen]; - if (NetRecvRaw(buf, llen) < 0) { - NetSend(kErrFatal, kROOTD_ERR); - ErrorInfo("RpdProtocol: error receiving message"); - if (buf) delete[] buf; - return -1; - } - if (buf) delete[] buf; - // Send back the 'type' - int type = htonl(8); - if (NetSendRaw(&type,sizeof(type)) < 0) { - NetSend(kErrFatal, kROOTD_ERR); - ErrorInfo("RpdProtocol: error sending type to TNetXNGFile"); - return -1; - } - // Now read the client protocol - llen = 4; - buf = new char[llen]; - if (NetRecvRaw(buf,llen) < 0) { - NetSend(kErrFatal, kROOTD_ERR); - ErrorInfo("RpdProtocol: error receiving message"); - delete[] buf; - return -1; - } - strlcpy(proto,buf, sizeof(proto)); - kind = kROOTD_PROTOCOL; - readbuf = 0; - delete[] buf; - } else { - // Need to open parallel sockets first - int size = ntohl(lbuf[1]); - // Read port - int port; - if (NetRecvRaw(&port, sizeof(int)) < 0) { - NetSend(kErrFatal, kROOTD_ERR); - ErrorInfo("RpdProtocol: error receiving message"); - return -1; - } - port = ntohl(port); - if (gDebug > 0) - ErrorInfo("RpdProtocol: port = %d, size = %d", port, size); - if (size > 1) - NetParOpen(port, size); - } - - int done = 0; - gClientOld = 0; - while (!done) { - - // Receive next - if (readbuf) { - if (NetRecv(proto, kMAXRECVBUF, kind) < 0) { - ErrorInfo("RpdProtocol: error receiving message"); - return -1; - } - } - readbuf = 1; - - switch(kind) { - - case kROOTD_CLEANUP: - RpdAuthCleanup(proto,1); - ErrorInfo("RpdProtocol: authentication stuff cleaned"); - done = 1; - rc = -2; - break; - case kROOTD_BYE: - RpdFreeKeys(); - NetClose(); - done = 1; - rc = -2; - break; - case kROOTD_PROTOCOL: - - if (strlen(proto) > 0) { - gClientProtocol = atoi(proto); - } else { - if (ServType == kROOTD) { - // This is an old (TNetFile,TFTP) client: - // send our protocol first ... - if (NetSend(gServerProtocol, kROOTD_PROTOCOL) < 0) { - ErrorInfo("RpdProtocol: error sending kROOTD_PROTOCOL"); - rc = -1; - } - // ... and receive protocol via kROOTD_PROTOCOL2 - if (NetRecv(proto, kMAXRECVBUF, kind) < 0) { - ErrorInfo("RpdProtocol: error receiving message"); - rc = -1; - } - if (kind != kROOTD_PROTOCOL2) { - strlcpy(gBufOld, proto, sizeof(gBufOld)); - gKindOld = kind; - gClientOld = 1; - gClientProtocol = 0; - } else - gClientProtocol = atoi(proto); - } else - gClientProtocol = 0; - } - if (!gClientOld) { - // send our protocol - // if we do not require authentication say it here - Int_t protoanswer = gServerProtocol; - if (!gRequireAuth && gClientProtocol > 10) - protoanswer += 1000; - // Notify - if (gDebug > 0) { - ErrorInfo("RpdProtocol: gClientProtocol = %d", - gClientProtocol); - ErrorInfo("RpdProtocol: Sending gServerProtocol = %d", - protoanswer); - } - if (NetSend(protoanswer, kROOTD_PROTOCOL) < 0) { - ErrorInfo("RpdProtocol: error sending kROOTD_PROTOCOL"); - rc = -1; - } - } - done = 1; - break; - default: - ErrorInfo("RpdProtocol: received bad option (%d)",kind); - rc = -1; - done = 1; - break; - } // Switch - - } // done - - return rc; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Authentication was successful, set user environment. - -int RpdLogin(int ServType, int auth) -{ -// if (gDebug > 2) - ErrorInfo("RpdLogin: enter: Server: %d, gUser: %s, auth: %d", - ServType, gUser, auth); - - // Login only if requested - if (gDoLogin == 0) - return -2; - - struct passwd *pw = getpwnam(gUser); - - if (!pw) { - ErrorInfo("RpdLogin: user %s does not exist locally\n", gUser); - return -1; - } - - if (getuid() == 0) { - // Anonymous users are confined to their corner - if (gAnon) { - // We need to do it before chroot, otherwise it does not work - if (chdir(pw->pw_dir) == -1) { - ErrorInfo("RpdLogin: can't change directory to %s (errno: %d)", - pw->pw_dir, errno); - return -1; - } - if (chroot(pw->pw_dir) == -1) { - ErrorInfo("RpdLogin: can't chroot to %s", pw->pw_dir); - return -1; - } - } - - // set access control list from /etc/initgroup - initgroups(gUser, pw->pw_gid); - - // set uid and gid - if (setresgid(pw->pw_gid, pw->pw_gid, 0) == -1) { - ErrorInfo("RpdLogin: can't setgid for user %s", gUser); - return -1; - } - if (setresuid(pw->pw_uid, pw->pw_uid, 0) == -1) { - ErrorInfo("RpdLogin: can't setuid for user %s", gUser); - return -1; - } - } - - if (ServType == 2) { - // set HOME env - char *home = new char[8+strlen(pw->pw_dir)]; - SPrintf(home, 8+strlen(pw->pw_dir), "HOME=%s", pw->pw_dir); - putenv(home); - } - - // Change user's HOME, if required (for anon it is already done) - if (gDoLogin == 2 && !gAnon) { - if (chdir(pw->pw_dir) == -1) { - ErrorInfo("RpdLogin: can't change directory to %s (errno: %d)", - pw->pw_dir, errno); - return -1; - } - } - - umask(022); - - // Notify authentication to client ... - NetSend(auth, kROOTD_AUTH); - // Send also new offset if it changed ... - if (auth == 2) NetSend(gOffSet, kROOTD_AUTH); - - if (gDebug > 0) - ErrorInfo("RpdLogin: user %s logged in", gUser); - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Perform the action needed to commence the new session: -/// Version called by TServerSocket. -/// - set debug flag -/// - check authentication table -/// - Inquire protocol -/// - authenticate the client -/// Returns logged-in user, the remote client procotol cproto, -/// the authentication protocol (ROOT internal) number is returned -/// in meth, type indicates the kind of authentication: -/// 0 = new authentication -/// 1 = existing authentication -/// 2 = existing authentication with updated offset -/// and the crypted-token in ctoken (used later for cleaning). -/// Called just after opening the connection - -int RpdInitSession(int servtype, std::string &user, - int &cproto, int &meth, int &type, std::string &ctoken) -{ - std::string pwd; - int auth = RpdInitSession(servtype,user,cproto,meth,pwd); - if (auth == 1) - if (gExistingAuth) - type = 1; - else - type = 0; - else if (auth == 2) - type = 2; - ctoken = gCryptToken; - - return auth; -} -//////////////////////////////////////////////////////////////////////////////// -/// Perform the action needed to commence the new session: -/// - set debug flag -/// - check authentication table -/// - Inquire protocol -/// - authenticate the client -/// - login the client -/// Returns 0 in presence of a server. -/// Returns logged-in user, the remote client procotol cproto, the -/// client kind of user anon and, if anonymous user, the client passwd. -/// If TServerSocket (servtype==kSOCKD), the protocol number is returned -/// in anon. -/// Called just after opening the connection - -int RpdInitSession(int servtype, std::string &user, - int &cproto, int &anon, std::string &passwd) -{ - if (gDebug > 2) - ErrorInfo("RpdInitSession: %s", gServName[servtype].c_str()); - - int retval = 0; - - // CleanUp authentication table, if needed or required ... - RpdInitAuth(); - - // Get Host name - NetGetRemoteHost(gOpenHost); - - // Get protocol first - // Failure typically indicate special actions like cleanup - // which do not need additional work - // The calling program will then decide what to do - int rcp = RpdProtocol(servtype); - if (rcp != 0) { - if (rcp == -1) - ErrorInfo("RpdInitSession: error getting remote protocol"); - else if (rcp != -2) - ErrorInfo("RpdInitSession: unknown error from RpdProtocol"); - return rcp; - } - - // Check if authentication is required - // Old clients do not support no authentication mode - bool runAuth = (gClientProtocol < 11 || gRequireAuth) ? 1 : 0; - - // user authentication (does not return in case of failure) - int auth = 0; - if (runAuth) { - auth = RpdAuthenticate(); - if (auth == 0) { - ErrorInfo("RpdInitSession: unsuccessful authentication attempt"); - return -1; - } - } else { - auth = RpdNoAuth(servtype); - } - - // Login the user (if in rootd environment) - if (gDoLogin > 0) { - if (RpdLogin(servtype,auth) != 0) { - ErrorInfo("RpdInitSession: unsuccessful login attempt"); - // Notify failure to client ... - NetSend(0, kROOTD_AUTH); - return -1; - } - } else { - // Notify authentication to client ... - NetSend(auth, kROOTD_AUTH); - // Send also new offset if it changed ... - if (auth == 2) - NetSend(gOffSet, kROOTD_AUTH); - if (gDebug > 0) - ErrorInfo("RpdInitSession: User '%s' authenticated", gUser); - retval = auth; - } - - // Output vars - user = std::string(gUser); - cproto = gClientProtocol; - if (servtype == kSOCKD) - anon = gSec; - else - anon = gAnon; - if (gAnon) - passwd = std::string(gPasswd); - - return retval; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Perform the action needed to commence the new session: -/// - set debug flag -/// - check authentication table -/// - Inquire protocol -/// - authenticate the client -/// - login the client -/// Returns 0 in presence of a master server. -/// Returns logged-in user and remote process id in rid -/// Called just after opening the connection - -int RpdInitSession(int servtype, std::string &user, int &rid) -{ - int dum1 = 0, dum2 = 0; - std::string dum3; - rid = gRemPid; - return RpdInitSession(servtype,user,dum1,dum2,dum3); - -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Perform entrance formalities in case of no authentication -/// mode, i.e. get target user and check if authorized -/// Don't return if something goes wrong - -int RpdNoAuth(int servtype) -{ - if (gDebug > 1) - ErrorInfo("RpdNoAuth: no authentication required"); - - // Special value for this case - int auth = 0; - - // Receive target username - if (servtype == kROOTD) { - - char buf[kMAXPATHLEN]; - EMessageTypes kind; - if (NetRecv(buf, kMAXPATHLEN, kind) < 0) { - NetSend(kErrBadMess, kROOTD_ERR); - ErrorInfo("RpdNoAuth: error receiving target user"); - goto quit; - } - - if (kind == kROOTD_BYE) - goto quit; - - if (kind != kROOTD_USER) { - NetSend(kErrBadOp, kROOTD_ERR); - ErrorInfo("RpdNoAuth: protocol error:" - " received msg type: %d, expecting: %d", kind, kROOTD_USER); - goto quit; - } - - // Decode buffer - char ruser[kMAXUSERLEN], user[kMAXUSERLEN]; - int nw = sscanf(buf,"%64s %64s",ruser,user); - if (nw <= 0 || !strcmp(ruser,"-1")) { - NetSend(kErrBadMess, kROOTD_ERR); - ErrorInfo("RpdNoAuth: received uncorrect information: %s", buf); - goto quit; - } - // If target user not send, assume user == ruser - if (nw == 1) - snprintf(user,kMAXUSERLEN,"%s",ruser); - - struct passwd *pw = 0; - if ((pw = getpwnam(user)) == 0) { - NetSend(kErrNoUser, kROOTD_ERR); - ErrorInfo("RpdNoAuth: user %s unknown", user); - goto quit; - } - - // If server is not started as root, require user to be the same - // as the one who started rootd - uid_t uid = getuid(); - if (uid && uid != pw->pw_uid) { - NetSend(kErrBadUser, kROOTD_ERR); - ErrorInfo("RpdNoAuth: user not same as effective user of rootd"); - goto quit; - } - - if (gDebug > 2) - ErrorInfo("RpdNoAuth: remote user: %s, target user: %s",ruser,user); - - SPrintf(gUser, 63, "%s", user); - } - - auth = 4; - - quit: - return auth; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Change current user id to uid (and gid). - -int RpdSetUid(int uid) -{ - if (gDebug > 2) - ErrorInfo("RpdSetUid: enter ...uid: %d", uid); - - struct passwd *pw = getpwuid(uid); - - if (!pw) { - ErrorInfo("RpdSetUid: uid %d does not exist locally", uid); - return -1; - } else if (chdir(pw->pw_dir) == -1) { - ErrorInfo("RpdSetUid: can't change directory to %s", pw->pw_dir); - return -1; - } - - if (getuid() == 0) { - - // set access control list from /etc/initgroup - initgroups(pw->pw_name, pw->pw_gid); - - // set uid and gid - if (setresgid(pw->pw_gid, pw->pw_gid, 0) == -1) { - ErrorInfo("RpdSetUid: can't setgid for uid %d", uid); - return -1; - } - if (setresuid(pw->pw_uid, pw->pw_uid, 0) == -1) { - ErrorInfo("RpdSetUid: can't setuid for uid %d", uid); - return -1; - } - } - - if (gDebug > 0) - ErrorInfo("RpdSetUid: uid set (%d,%s)", uid, pw->pw_name); - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Change defaults job control options. - -void RpdInit(EService serv, int pid, int sproto, unsigned int options, - int rumsk, int, const char *tmpd, const char * /* asrpp */, int login) -{ - gService = serv; - gParentId = pid; - gServerProtocol = sproto; - gReUseAllow = rumsk; - gDoLogin = login; - - // Parse options - gCheckHostsEquiv= (bool)((options & kDMN_HOSTEQ) != 0); - gRequireAuth = (bool)((options & kDMN_RQAUTH) != 0); - gSysLog = (bool)((options & kDMN_SYSLOG) != 0); - - if (tmpd && strlen(tmpd)) { - gTmpDir = tmpd; - gRpdAuthTab = gTmpDir + gAuthTab; - gRpdKeyRoot = gTmpDir + gKeyRoot; - } - // Auth Tab and public key files are exclusive to this family - gRpdAuthTab.append("."); - gRpdAuthTab.append(ItoA(getuid())); - gRpdKeyRoot.append(ItoA(getuid())); - gRpdKeyRoot.append("_"); - - if (gDebug > 0) { - ErrorInfo("RpdInit: gService= %s, gSysLog= %d", - gServName[gService].c_str(), gSysLog); - ErrorInfo("RpdInit: gParentId= %d", gParentId); - ErrorInfo("RpdInit: gRequireAuth= %d, gCheckHostEquiv= %d", - gRequireAuth, gCheckHostsEquiv); - ErrorInfo("RpdInit: gReUseAllow= 0x%x", gReUseAllow); - ErrorInfo("RpdInit: gServerProtocol= %d", gServerProtocol); - ErrorInfo("RpdInit: gDoLogin= %d", gDoLogin); - if (tmpd) - ErrorInfo("RpdInit: gTmpDir= %s", gTmpDir.c_str()); - } -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Acts like snprintf with some printout in case of error if required -/// Returns number of characters printed (excluding the trailing `\0'). -/// Returns 0 is buf or size are not defined or inconsistent. -/// Returns -1 if the buffer is truncated. - -int SPrintf(char *buf, size_t size, const char *va_(fmt), ...) -{ - // Check buf - if (!buf) { - if (gDebug > 0) - ErrorInfo("SPrintf: buffer not allocated: do nothing"); - return 0; - } - - // Check size - if (size < 1) { - if (gDebug > 0) - ErrorInfo("SPrintf: cannot determine buffer size (%d): do nothing",size); - return 0; - } - - // Now fill buf - va_list ap; - va_start(ap,va_(fmt)); - int np = vsnprintf(buf, size, fmt, ap); - va_end(ap); - - if (np == -1 && gDebug > 0) - ErrorInfo("SPrintf: buffer truncated (%s)",buf); - - return np; -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Return pointer to a static string containing the string -/// version of integer 'i', up to a max of kMAXCHR (=30) -/// characters; returns "-1" if more chars are needed. - -char *ItoA(int i) -{ - const int kMAXCHR = 30; - static char str[kMAXCHR]; - - // This is the number of characters we need - int nchr = (int)log10(double(i)) + 1; - if (nchr > kMAXCHR) - strlcpy(str,"-1", sizeof(str)); - else - snprintf(str,30,"%d",i); - - return str; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Set global pointers to error handler functions - -void RpdSetErrorHandler(ErrorHandler_t err, ErrorHandler_t sys, ErrorHandler_t fatal) -{ - gErr = err; - gErrSys = sys; - gErrFatal = fatal; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Retrieve specific ROOT password from $HOME/fpw, if any. -/// To avoid problems with NFS-root-squashing, if 'root' changes temporarly the -/// uid/gid to those of the target user (usr). -/// If OK, returns pass length and fill 'pass' with the password, null-terminated. -/// ('pass' is allocated externally to contain max lpwmax bytes). -/// If the file does not exists, return 0 and an empty pass. -/// If any problems with the file occurs, return a negative -/// code, -2 indicating wrong file permissions. -/// If any problem with changing ugid's occurs, prints a warning trying anyhow -/// to read the password hash. - -int RpdRetrieveSpecialPass(const char *usr, const char *fpw, char *pass, int lpwmax) -{ - int rc = -1; - int len = 0, n = 0, fid = -1; - - // Check inputs - if (!usr || !pass) { - if (gDebug > 0) - ErrorInfo("RpdRetrieveSpecialPass: invalid arguments:" - " us:%p, sp:%p", usr, pass); - return rc; - } - - struct passwd *pw = getpwnam(usr); - if (!pw) { - if (gDebug > 0) - ErrorInfo("RpdRetrieveSpecialPass: user '%s' does not exist", usr); - return rc; - } - - // target and actual uid - int uid = pw->pw_uid; - int ouid = getuid(); - - // Temporary change to target user ID to avoid NFS squashing problems - if (ouid == 0) { - - // set access control list from /etc/initgroup - if (initgroups(pw->pw_name, pw->pw_gid) == -1) - ErrorInfo("RpdRetrieveSpecialPass: can't initgroups for uid %d" - " (errno: %d)", uid, GetErrno()); - // set uid and gid - if (setresgid(pw->pw_gid, pw->pw_gid, 0) == -1) - ErrorInfo("RpdRetrieveSpecialPass: can't setgid for gid %d" - " (errno: %d)", pw->pw_gid, GetErrno()); - if (setresuid(pw->pw_uid, pw->pw_uid, 0) == -1) - ErrorInfo("RpdRetrieveSpecialPass: can't setuid for uid %d" - " (errno: %d)", uid, GetErrno()); - } - - // The file now - char rootdpass[kMAXPATHLEN]; - SPrintf(rootdpass, kMAXPATHLEN, "%s/%s", pw->pw_dir, fpw); - - if (gDebug > 0) - ErrorInfo - ("RpdRetrieveSpecialPass: checking file %s for user %s",rootdpass, - pw->pw_name); - - - if ((fid = open(rootdpass, O_RDONLY)) == -1) { - ErrorInfo("RpdRetrieveSpecialPass: cannot open password file" - " %s (errno: %d)", rootdpass, GetErrno()); - rc = -1; - goto back; - } - // Check first the permissions: should be 0600 - struct stat st; - if (fstat(fid, &st) == -1) { - ErrorInfo("RpdRetrieveSpecialPass: cannot stat descriptor %d" - " %s (errno: %d)", fid, GetErrno()); - close(fid); - rc = -1; - goto back; - } - if (!S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || - (st.st_mode & (S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH)) != 0) { - ErrorInfo("RpdRetrieveSpecialPass: pass file %s: wrong permissions" - " 0%o (should be 0600)", rootdpass, (st.st_mode & 0777)); - ErrorInfo("RpdRetrieveSpecialPass: %d %d", - S_ISREG(st.st_mode),S_ISDIR(st.st_mode)); - close(fid); - rc = -2; - goto back; - } - - if ((n = read(fid, pass, lpwmax - 1)) <= 0) { - close(fid); - ErrorInfo("RpdRetrieveSpecialPass: cannot read password file" - " %s (errno: %d)", rootdpass, GetErrno()); - rc = -1; - goto back; - } - close(fid); - - // Get rid of special trailing chars - len = n; - while (len-- && (pass[len] == '\n' || pass[len] == 32)) - pass[len] = 0; - - // Null-terminate - pass[++len] = 0; - rc = len; - - back: - // Change back uid's - if (ouid == 0) { - // set uid and gid - if (setresgid(0, 0, 0) == -1) - ErrorInfo("RpdRetrieveSpecialPass: can't re-setgid for gid 0" - " (errno: %d)", GetErrno()); - if (setresuid(0, 0, 0) == -1) - ErrorInfo("RpdRetrieveSpecialPass: can't re-setuid for uid 0" - " (errno: %d)", GetErrno()); - } - - // We are done - return rc; -} - -} // namespace ROOT diff --git a/roottest/root/io/event/MainEvent.cxx b/roottest/root/io/event/MainEvent.cxx index bb97e320ba586..157c1a2560cad 100644 --- a/roottest/root/io/event/MainEvent.cxx +++ b/roottest/root/io/event/MainEvent.cxx @@ -85,7 +85,6 @@ #include "TBranch.h" #include "TFile.h" #include "TH1.h" -#include "TNetFile.h" #include "TRandom.h" #include "TStopwatch.h" #include "TTree.h" @@ -113,7 +112,6 @@ int main(int argc, char** argv) Int_t read = 0; Int_t arg4 = 1; Int_t arg5 = 600; //default number of tracks per event - Int_t netf = 0; const char* arg6 = 0; const char* arg7 = 0; @@ -133,7 +131,6 @@ int main(int argc, char** argv) if (arg4 == 11) { write = 1; hfill = 1;} if (arg4 == 20) { write = 0; read = 1;} //read sequential if (arg4 == 25) { write = 0; read = 2;} //read random - if (arg4 >= 30) { netf = 1; } //use TNetFile if (arg4 == 30) { write = 0; read = 1;} //netfile + read sequential if (arg4 == 35) { write = 0; read = 2;} //netfile + read random if (arg4 == 36) { write = 1; } //netfile + write sequential @@ -179,11 +176,7 @@ int main(int argc, char** argv) if (read) { // -- Read case TFile* hfile = nullptr; - if (netf) { - hfile = new TNetFile("root://localhost/root/test/EventNet.root"); - } else { - hfile = new TFile(gFilename); - } + hfile = new TFile(gFilename); TTree* tree = (TTree*) hfile->Get("T"); TBranch* branch = tree->GetBranch("event"); Event* event = nullptr; @@ -225,11 +218,7 @@ int main(int argc, char** argv) // pictures, graphics objects, detector geometries, tracks, events, etc.. // This file is now becoming the current directory. TFile* hfile = 0; - if (netf) { - hfile = new TNetFile("root://localhost/root/test/EventNet.root", "RECREATE", "TTree benchmark ROOT file"); - } else { - hfile = new TFile(gFilename, "RECREATE", "TTree benchmark ROOT file"); - } + hfile = new TFile(gFilename, "RECREATE", "TTree benchmark ROOT file"); hfile->SetCompressionLevel(comp); // Create histogram to show write_time in function of time diff --git a/roottest/root/treeformula/references/TreeFormulaReferencesGenerator.cxx b/roottest/root/treeformula/references/TreeFormulaReferencesGenerator.cxx index e86c71dbf75fd..4cea9e1299d4c 100644 --- a/roottest/root/treeformula/references/TreeFormulaReferencesGenerator.cxx +++ b/roottest/root/treeformula/references/TreeFormulaReferencesGenerator.cxx @@ -85,7 +85,6 @@ #include "Riostream.h" #include "TROOT.h" #include "TFile.h" -#include "TNetFile.h" #include "TRandom.h" #include "TTree.h" #include "TBranch.h" @@ -109,7 +108,6 @@ int main(int argc, char **argv) Int_t read = 0; Int_t arg4 = 1; Int_t arg5 = 600; //default number of tracks per event - Int_t netf = 0; const char *filename = "Event.root"; if (argc > 1) nevent = atoi(argv[1]); @@ -125,7 +123,6 @@ int main(int argc, char **argv) if (arg4 == 11) { write = 1; hfill = 1;} if (arg4 == 20) { write = 0; read = 1;} //read sequential if (arg4 == 25) { write = 0; read = 2;} //read random - if (arg4 >= 30) { netf = 1; } //use TNetFile if (arg4 == 30) { write = 0; read = 1;} //netfile + read sequential if (arg4 == 35) { write = 0; read = 2;} //netfile + read random if (arg4 == 36) { write = 1; } //netfile + write sequential @@ -153,10 +150,7 @@ int main(int argc, char **argv) // Read case if (read) { - if (netf) { - hfile = new TNetFile("root://localhost/root/test/EventNet.root"); - } else - hfile = new TFile(filename); + hfile = new TFile(filename); TTree *tree = (TTree*)hfile->Get("T"); TBranch *branch = tree->GetBranch("event"); branch->SetAddress(&event); @@ -186,10 +180,7 @@ int main(int argc, char **argv) // Note that this file may contain any kind of ROOT objects, histograms, // pictures, graphics objects, detector geometries, tracks, events, etc.. // This file is now becoming the current directory. - if (netf) { - hfile = new TNetFile("root://localhost/root/test/EventNet.root","RECREATE","TTree benchmark ROOT file"); - } else - hfile = new TFile(filename,"RECREATE","TTree benchmark ROOT file"); + hfile = new TFile(filename,"RECREATE","TTree benchmark ROOT file"); hfile->SetCompressionLevel(comp); // Create histogram to show write_time in function of time diff --git a/roottest/root/treeformula/schemaEvolution/MainEvent.cxx b/roottest/root/treeformula/schemaEvolution/MainEvent.cxx index b2acd45022f34..fa20afd458944 100644 --- a/roottest/root/treeformula/schemaEvolution/MainEvent.cxx +++ b/roottest/root/treeformula/schemaEvolution/MainEvent.cxx @@ -85,7 +85,6 @@ #include "TROOT.h" #include "TFile.h" -#include "TNetFile.h" #include "TRandom.h" #include "TTree.h" #include "TBranch.h" @@ -109,7 +108,6 @@ int main(int argc, char **argv) Int_t read = 0; Int_t arg4 = 1; Int_t arg5 = 600; //default number of tracks per event - Int_t netf = 0; if (argc > 1) nevent = atoi(argv[1]); if (argc > 2) comp = atoi(argv[2]); @@ -123,7 +121,6 @@ int main(int argc, char **argv) if (arg4 == 11) { write = 1; hfill = 1;} if (arg4 == 20) { write = 0; read = 1;} //read sequential if (arg4 == 25) { write = 0; read = 2;} //read random - if (arg4 >= 30) { netf = 1; } //use TNetFile if (arg4 == 30) { write = 0; read = 1;} //netfile + read sequential if (arg4 == 35) { write = 0; read = 2;} //netfile + read random if (arg4 == 36) { write = 1; } //netfile + write sequential @@ -152,10 +149,7 @@ int main(int argc, char **argv) // Read case if (read) { - if (netf) { - hfile = new TNetFile("root://localhost/root/test/EventNet.root"); - } else - hfile = new TFile("Event.root"); + hfile = new TFile("Event.root"); tree = (TTree*)hfile->Get("T"); TBranch *branch = tree->GetBranch("event"); branch->SetAddress(&event); @@ -185,10 +179,7 @@ int main(int argc, char **argv) // Note that this file may contain any kind of ROOT objects, histograms, // pictures, graphics objects, detector geometries, tracks, events, etc.. // This file is now becoming the current directory. - if (netf) { - hfile = new TNetFile("root://localhost/root/test/EventNet.root","RECREATE","TTree benchmark ROOT file"); - } else - hfile = new TFile("Event.root","RECREATE","TTree benchmark ROOT file"); + hfile = new TFile("Event.root","RECREATE","TTree benchmark ROOT file"); hfile->SetCompressionLevel(comp); // Create histogram to show write_time in function of time diff --git a/test/MainEvent.cxx b/test/MainEvent.cxx index 4ab5f991ae5fc..e35c8a2775c80 100644 --- a/test/MainEvent.cxx +++ b/test/MainEvent.cxx @@ -96,7 +96,6 @@ #include "Riostream.h" #include "TROOT.h" #include "TFile.h" -#include "TNetFile.h" #include "TRandom.h" #include "TTree.h" #include "TTreePerfStats.h" @@ -121,7 +120,6 @@ int MainEvent(int nevent, int comp, int split, int arg4, int arg5, int enable_im Int_t write = 1; // by default the tree is filled Int_t hfill = 0; // by default histograms are not filled Int_t read = 0; - Int_t netf = 0; Int_t punzip = 0; if (arg4 == 0) { write = 0; hfill = 0; read = 1;} @@ -132,7 +130,6 @@ int MainEvent(int nevent, int comp, int split, int arg4, int arg5, int enable_im if (arg4 == 20) { write = 0; read = 1;} //read sequential if (arg4 == 21) { write = 0; read = 1; punzip = 1;} //read sequential + parallel unzipping if (arg4 == 25) { write = 0; read = 2;} //read random - if (arg4 >= 30) { netf = 1; } //use TNetFile if (arg4 == 30) { write = 0; read = 1;} //netfile + read sequential if (arg4 == 35) { write = 0; read = 2;} //netfile + read random if (arg4 == 36) { write = 1; } //netfile + write sequential @@ -171,10 +168,7 @@ int MainEvent(int nevent, int comp, int split, int arg4, int arg5, int enable_im // Read case if (read) { - if (netf) { - hfile = new TNetFile("root://localhost/root/test/EventNet.root"); - } else - hfile = new TFile(outFiles.back().c_str()); + hfile = new TFile(outFiles.back().c_str()); tree = (TTree*)hfile->Get("T"); TBranch *branch = tree->GetBranch("event"); branch->SetAddress(&event); @@ -215,10 +209,7 @@ int MainEvent(int nevent, int comp, int split, int arg4, int arg5, int enable_im // Note that this file may contain any kind of ROOT objects, histograms, // pictures, graphics objects, detector geometries, tracks, events, etc.. // This file is now becoming the current directory. - if (netf) { - hfile = new TNetFile("root://localhost/root/test/EventNet.root","RECREATE","TTree benchmark ROOT file"); - } else - hfile = new TFile(outFiles.back().c_str(),"RECREATE","TTree benchmark ROOT file"); + hfile = new TFile(outFiles.back().c_str(),"RECREATE","TTree benchmark ROOT file"); hfile->SetCompressionLevel(comp); hfile->SetCompressionAlgorithm(compAlg);