proofd.cxx

Go to the documentation of this file.
00001 // @(#)root/proofd:$Id: proofd.cxx 36312 2010-10-12 10:15:40Z rdm $
00002 // Author: Fons Rademakers   02/02/97
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // Proofd                                                               //
00015 //                                                                      //
00016 // PROOF, Parallel ROOT Facility, front-end daemon.                     //
00017 // This small server is started either by inetd when a client requests  //
00018 // a connection to a PROOF server or by hand (i.e. from the command     //
00019 // line). By default proofd uses port 1093 (allocated by IANA,          //
00020 // www.iana.org, to proofd). If we don't want the PROOF server          //
00021 // to run on this specific node, e.g. because the system is being       //
00022 // shutdown or there are already too many servers running, we send      //
00023 // the client a re-route message and close the connection. Otherwise    //
00024 // we authenticate the user and exec the proofserv program.             //
00025 // To run proofd via inetd add the following line to /etc/services:     //
00026 //                                                                      //
00027 // proofd     1093/tcp                                                  //
00028 //                                                                      //
00029 // and to /etc/inetd.conf:                                              //
00030 //                                                                      //
00031 // proofd stream tcp nowait root /usr/local/root/bin/proofd -i \        //
00032 //    /usr/local/root                                                   //
00033 //                                                                      //
00034 // Force inetd to reread its conf file with "kill -HUP <pid inetd>".    //
00035 //                                                                      //
00036 // If xinetd is used instead, a file named 'proofd' should be created   //
00037 // under /etc/xinetd.d with content                                     //
00038 //                                                                      //
00039 // # default: off                                                       //
00040 // # description: The proof daemon                                      //
00041 // #                                                                    //
00042 // service proofd                                                       //
00043 // {                                                                    //
00044 //      disable         = no                                            //
00045 //      flags           = REUSE                                         //
00046 //      socket_type     = stream                                        //
00047 //      wait            = no                                            //
00048 //      user            = root                                          //
00049 //      server          = /usr/local/root/bin/proofd                    //
00050 //      server_args     = -i -d 0 /usr/local/root                       //
00051 // }                                                                    //
00052 //                                                                      //
00053 // and xinetd restarted (/sbin/service xinetd restart).                 //
00054 //                                                                      //
00055 // You can also start proofd by hand running directly under your        //
00056 // private account (no root system priviliges needed). For example to   //
00057 // start proofd listening on port 5252 just type:                       //
00058 //                                                                      //
00059 // prootd -p 5252 $ROOTSYS                                              //
00060 //                                                                      //
00061 // Notice: no & is needed. Proofd will go in background by itself.      //
00062 //                                                                      //
00063 // Proofd arguments:                                                    //
00064 //   -A [<rootauthrc>] Tells proofserv to read user's $HOME/.rootauthrc,//
00065 //                     if any; by default such private file is ignored  //
00066 //                     to allow complete control on the authentication  //
00067 //                     directives to the cluster administrator, via the //
00068 //                     system.rootauthrc file; if the optional argument //
00069 //                     <rootauthrc> is given and points to a valid file,//
00070 //                     this file takes the highest priority (private    //
00071 //                     user's file being still read with next-to-highest//
00072 //                     priority) providing a mean to use non-standard   //
00073 //                     file names for authentication directives.        //
00074 //   -b tcpwindowsize  specifies the tcp window size in bytes (e.g. see //
00075 //                     http://www.psc.edu/networking/perf_tune.html)    //
00076 //                     Default is 65535. Only change default for pipes  //
00077 //                     with a high bandwidth*delay product.             //
00078 //   -C hostcertfile   defines a file where to find information for the //
00079 //                     local host Globus information (see GLOBUS.README //
00080 //                     for details)                                     //
00081 //   -d level          level of debug info written to syslog            //
00082 //                     0 = no debug (default)                           //
00083 //                     1 = minimum                                      //
00084 //                     2 = medium                                       //
00085 //                     3 = maximum                                      //
00086 //   -D rootdaemonrc   read access rules from file <rootdaemonrc>.      //
00087 //                     By default <root_etc_dir>/system.rootdaemonrc is //
00088 //                     used for access rules; for privately started     //
00089 //                     daemons $HOME/.rootdaemonrc (if present) takes   //
00090 //                     highest priority.                                //
00091 //   -E                obsolete; up to v4.00.08 this option was used to //
00092 //                     force exclusivity of the authentication tokens;  //
00093 //                     with the new approach for authentication tab     //
00094 //                     files this option is dummy.                      //
00095 //   -f                do not run as daemon, run in the foreground      //
00096 //   -G gridmapfile    defines the gridmap file to be used for globus   //
00097 //                     authentication if different from globus default  //
00098 //                     (/etc/grid-security/gridmap); (re)defines the    //
00099 //                     GRIDMAP environment variable.                    //
00100 //   -h                print usage message                              //
00101 //   -i                says we were started by inetd                    //
00102 //   -noauth           do not require client authentication             //
00103 //   -p port#          specifies a different port to listen on          //
00104 //   -s <sshd_port>    specifies the port number for the sshd daemon    //
00105 //                     (deafult is 22)                                  //
00106 //   -S keytabfile     use this keytab file, instead of the default     //
00107 //                     (option only supported when compiled with        //
00108 //                     Kerberos5 support)                               //
00109 //   -T <tmpdir>       specifies the directory path to be used to place //
00110 //                     temporary files; default is /usr/tmp.            //
00111 //                     Useful if not running as root.                   //
00112 //   -w                do not check /etc/hosts.equiv, $HOME/.rhosts     //
00113 //                     for UsrPwd authentications; by default these     //
00114 //                     files are checked first by calling ruserok(...); //
00115 //                     if this option is specified a password is always //
00116 //                     required.
00117 //   rootsys_dir       directory which must contain bin/proofserv and   //
00118 //                     proof/etc/proof.conf. If not specified ROOTSYS   //
00119 //                     or built-in (as specified to ./configure) is     //
00120 //                     tried. (*MUST* be the last argument).            //
00121 //                                                                      //
00122 //  When your system uses shadow passwords you have to compile proofd   //
00123 //  with -DR__SHADOWPW. Since shadow passwords can only be accessed     //
00124 //  while being superuser (root) this works only when the server is     //
00125 //  started via inetd. Another solution is to create a file             //
00126 //  ~/.rootdpass containing an encrypted password. If this file exists  //
00127 //  its password is used for authentication. This method overrides      //
00128 //  all other authentication methods. To create an encrypted password   //
00129 //  do something like:                                                  //
00130 //     perl -e '$pw = crypt("<secretpasswd>","salt"); print "$pw\n"'    //
00131 //  and store this string in ~/.rootdpass.                              //
00132 //                                                                      //
00133 //  To use AFS for authentication compile proofd with the -DR__AFS      //
00134 //  flag. In that case you also need to link with the AFS libraries.    //
00135 //  See the Makefiles for more details.                                 //
00136 //                                                                      //
00137 //  To use Secure Remote Passwords (SRP) for authentication compile     //
00138 //  proofd with the -DR__SRP flag. In that case you also need to link   //
00139 //  with the SRP and gmp libraries. See the Makefile for more details.  //
00140 //  SRP is described at: http://srp.stanford.edu/.                      //
00141 //                                                                      //
00142 //  See README.AUTH for more details on the authentication features.    //
00143 //                                                                      //
00144 //////////////////////////////////////////////////////////////////////////
00145 
00146 // Protocol changes (see gProtocol):
00147 // 6: added support for kerberos5 authentication
00148 // 7: added support for Globus, SSH and uid/gid authentication and negotiation
00149 // 8: change in Kerberos authentication protocol
00150 // 9: change authentication cleaning protocol
00151 // 10: modified SSH protocol + support for server 'no authentication' mode
00152 // 11: added support for openSSL keys for encryption
00153 // 12: major authentication re-organization
00154 // 13: support for SSH authentication via SSH tunnel
00155 // 14: add env setup message
00156 
00157 #include "RConfigure.h"
00158 #include "RConfig.h"
00159 
00160 #include <ctype.h>
00161 #include <fcntl.h>
00162 #include <pwd.h>
00163 #include <stdio.h>
00164 #include <string.h>
00165 #include <strings.h>
00166 #include <string>
00167 #include <stdlib.h>
00168 #include <unistd.h>
00169 #include <sys/types.h>
00170 #include <time.h>
00171 #include <sys/stat.h>
00172 #include <sys/socket.h>
00173 #include <sys/param.h>
00174 #include <netinet/in.h>
00175 #include <arpa/inet.h>
00176 #include <netdb.h>
00177 #include <errno.h>
00178 #include <sys/un.h>
00179 #include "snprintf.h"
00180 
00181 #if defined(__CYGWIN__) && defined(__GNUC__)
00182 #   define cygwingcc
00183 #endif
00184 #if defined(linux) || defined(__sun) || defined(__sgi) || \
00185     defined(_AIX) || defined(__FreeBSD__) || defined(__APPLE__) || \
00186     defined(__MACH__) || defined(cygwingcc) || defined(__OpenBSD__)
00187 #include <grp.h>
00188 #include <sys/types.h>
00189 #include <signal.h>
00190 #define ROOT_SIGNAL_INCLUDED
00191 #endif
00192 
00193 #if defined(__alpha) && !defined(linux) && !defined(__FreeBSD__) && \
00194     !defined(__OpenBSD__)
00195 extern "C" int initgroups(const char *name, int basegid);
00196 #ifndef ROOT_SIGNAL_INCLUDED
00197 #include <signal.h>
00198 #endif
00199 #endif
00200 
00201 #if defined(__sgi) && !defined(__GNUG__) && (SGI_REL<62)
00202 extern "C" {
00203    int seteuid(int euid);
00204    int setegid(int egid);
00205 }
00206 #endif
00207 
00208 #if defined(_AIX)
00209 extern "C" {
00210    //int initgroups(const char *name, int basegid);
00211    int seteuid(uid_t euid);
00212    int setegid(gid_t egid);
00213 }
00214 #endif
00215 
00216 #if defined(__sun)
00217 #if defined(R__SUNGCC3)
00218 extern "C" int gethostname(char *, unsigned int);
00219 #else
00220 extern "C" int gethostname(char *, int);
00221 #endif
00222 #endif
00223 
00224 #include "proofdp.h"
00225 extern "C" {
00226 #include "rsadef.h"
00227 #include "rsalib.h"
00228 }
00229 
00230 // General globals
00231 int     gDebug                   = 0;
00232 
00233 //--- Local Globals ---------------------------------------------------------
00234 
00235 const int kMaxSlaves             = 32;
00236 
00237 static std::string gAuthrc;
00238 static std::string gConfDir;
00239 static std::string gOpenHost;
00240 static std::string gRootBinDir;
00241 static std::string gRpdAuthTab;   // keeps track of authentication info
00242 static std::string gTmpDir;
00243 static std::string gUser;
00244 static EService gService         = kPROOFD;
00245 static int gProtocol             = 14;       // increase when protocol changes
00246 static int gRemPid               = -1;      // remote process ID
00247 static std::string gReadHomeAuthrc = "0";
00248 static int gInetdFlag            = 0;
00249 static int gMaster               =-1;
00250 static int gRequireAuth          = 1;
00251 
00252 using namespace ROOT;
00253 
00254 //--- Error handlers -----------------------------------------------------------
00255 
00256 //______________________________________________________________________________
00257 void Err(int level, const char *msg, int size)
00258 {
00259    Perror((char *)msg, size);
00260    if (level > -1) NetSend(level, kROOTD_ERR);
00261 }
00262 //______________________________________________________________________________
00263 void ErrFatal(int level, const char *msg, int size)
00264 {
00265    Perror((char *)msg, size);
00266    if (level > -1) NetSend(msg, kMESS_STRING);
00267    exit(1);
00268 }
00269 //______________________________________________________________________________
00270 void ErrSys(int level, const char *msg, int size)
00271 {
00272    Perror((char *)msg, size);
00273    ErrFatal(level, msg, size);
00274 }
00275 
00276 //--- Proofd routines ----------------------------------------------------------
00277 
00278 #if defined(__sun)
00279 //______________________________________________________________________________
00280 extern "C" { void ProofdTerm(int)
00281 {
00282    // Termination upon receipt of a SIGTERM or SIGINT.
00283 
00284    ErrorInfo("ProofdTerm: rootd.cxx: got a SIGTERM/SIGINT");
00285    // Terminate properly
00286    RpdAuthCleanup(0,0);
00287    // Close network connection
00288    NetClose();
00289    // exit
00290    exit(0);
00291 }}
00292 #else
00293 //______________________________________________________________________________
00294 static void ProofdTerm(int)
00295 {
00296    // Termination upon receipt of a SIGTERM or SIGINT.
00297 
00298    ErrorInfo("ProofdTerm: rootd.cxx: got a SIGTERM/SIGINT");
00299    // Terminate properly
00300    RpdAuthCleanup(0,0);
00301    // Close network connection
00302    NetClose();
00303    // exit
00304    exit(0);
00305 }
00306 #endif
00307 
00308 //______________________________________________________________________________
00309 const char *RerouteUser()
00310 {
00311    // Look if user should be rerouted to another server node.
00312 
00313    std::string conffile = "proof.conf";
00314    FILE *proofconf;
00315 
00316    if (getenv("HOME")) {
00317       conffile.insert(0,"/.");
00318       conffile.insert(0,getenv("HOME"));
00319       // string::insert is buggy on some compilers (eg gcc 2.96):
00320       // new length correct but data not always null terminated
00321       conffile[conffile.length()] = 0;
00322    }
00323    if (!(proofconf = fopen(conffile.c_str(), "r"))) {
00324       conffile = "/etc/";
00325       conffile.insert(0,gConfDir);
00326       // string::insert is buggy on some compilers (eg gcc 2.96):
00327       // new length correct but data not always null terminated
00328       conffile[conffile.length()] = 0;
00329    }
00330    if (proofconf || (proofconf = fopen(conffile.c_str(), "r")) != 0) {
00331 
00332       // read configuration file
00333       static char user_on_node[32];
00334       struct stat statbuf;
00335       char line[256];
00336       char node_name[kMaxSlaves][32];
00337       int  nnodes = 0;
00338       int  i;
00339 
00340       strncpy(user_on_node, "any", 32);
00341       user_on_node[31] = 0;
00342 
00343       while (fgets(line, sizeof(line), proofconf) != 0) {
00344          char word[4][64];
00345          if (line[0] == '#') continue;  // skip comment lines
00346          // coverity[secure_coding]
00347          int nword = sscanf(line, "%63s %63s %63s %63s",
00348                             word[0], word[1], word[2], word[3]);
00349 
00350          //
00351          // all available nodes must be configured by a line
00352          //    node <name>
00353          //
00354          if (nword >= 2 && strcmp(word[0], "node") == 0) {
00355             if (gethostbyname(word[1]) != 0) {
00356                if (nnodes < kMaxSlaves) {
00357                   if (strlen(word[1]) < 32) {
00358                      strncpy(node_name[nnodes], word[1], 32);
00359                      node_name[nnodes][31] = 0;
00360                   }
00361                   nnodes++;
00362                }
00363             }
00364             continue;
00365          }
00366 
00367          //
00368          // users can be preferrably rerouted to a specific node
00369          //    user <name> on <node>
00370          //
00371          if (nword >= 4 && strcmp(word[0], "user") == 0 &&
00372              strcmp(word[1], gUser.c_str()) == 0 &&
00373              strcmp(word[2], "on") == 0) {
00374             // user <name> on <node>
00375             if (strlen(word[3]) < 32) {
00376                strncpy(user_on_node, word[3], 32);
00377                user_on_node[31] = 0;
00378             }
00379             continue;
00380          }
00381       }
00382       fclose(proofconf);
00383 
00384       // make sure the node is running
00385       for (i = 0; i < nnodes; i++) {
00386          if (strcmp(node_name[i], user_on_node) == 0) {
00387             return user_on_node;
00388          }
00389       }
00390 
00391       //
00392       // get the node name from next.node update by a daemon monitoring
00393       // the system load; make sure the file is not completely out of date
00394       //
00395       conffile = gConfDir + "/etc/next.node";
00396       proofconf = fopen(conffile.c_str(), "r");
00397       if (proofconf) {
00398          if (fstat(fileno(proofconf), &statbuf) == 0 &&
00399              difftime(time(0), statbuf.st_mtime) < 600) {
00400             if (fgets(line, sizeof(line), proofconf) != 0) {
00401                strncpy(user_on_node, line, 32);
00402                user_on_node[31] = 0;
00403                for (i = 0; i < nnodes; i++) {
00404                   if (strcmp(node_name[i], user_on_node) == 0) {
00405                      fclose(proofconf);
00406                      return user_on_node;
00407                   }
00408                }
00409             }
00410          }
00411          fclose(proofconf);
00412       }
00413    }
00414    return 0;
00415 }
00416 
00417 //______________________________________________________________________________
00418 int RpdProofGetAuthSetup(char **abuf)
00419 {
00420    // Receive buffer for final setup of authentication related stuff
00421    // This is base 64 string to decoded by proofserv, if needed
00422    int nrec = -1;
00423 
00424    if (RpdGetOffSet() > -1) {
00425       if ((nrec = RpdSecureRecv(abuf)) < 0) {
00426          ErrorInfo("RpdProofGetAuthSetup: sec: problems receiving buf");
00427          return -1;
00428       }
00429    } else {
00430       // No key: receive plainly
00431       EMessageTypes kind;
00432       char buflen[20];
00433       if (NetRecv(buflen, 20, kind) < 0) {
00434          ErrorInfo("RpdProofGetAuthSetup: plain: problems receiving buf length");
00435          return -1;
00436       }
00437       int len = atoi(buflen);
00438 
00439       // receive the buffer
00440       *abuf = new char[len + 1];
00441       if ((nrec = NetRecvRaw(*abuf, len)) < 0) {
00442          ErrorInfo("RpdProofGetAuthSetup: plain: problems receiving buf");
00443          delete[] *abuf;
00444          return -1;
00445       }
00446       (*abuf)[len] = 0;
00447    }
00448 
00449    if (gDebug > 1)
00450       ErrorInfo("RpdProofGetAuthSetup: proto: %d len: %d",
00451                 RpdGetAuthProtocol(), nrec);
00452 
00453    return nrec;
00454 }
00455 
00456 //______________________________________________________________________________
00457 void ProofdExec()
00458 {
00459    // Authenticate the user and exec the proofserv program.
00460    // gConfdir is the location where the PROOF config files and binaries live.
00461 
00462    char *argvv[3];
00463    std::string arg0;
00464    std::string msg;
00465 
00466 #ifdef R__DEBUG
00467    int debug = 1;
00468    while (debug)
00469       ;
00470 #endif
00471 
00472    // Remote Host
00473    NetGetRemoteHost(gOpenHost);
00474 
00475    // Socket descriptor
00476    int sockFd = NetGetSockFd();
00477 
00478    if (gDebug > 0)
00479       ErrorInfo("ProofdExec: gOpenHost = %s", gOpenHost.c_str());
00480 
00481    if (gDebug > 0)
00482       ErrorInfo("ProofdExec: gConfDir = %s", gConfDir.c_str());
00483 
00484    // only reroute in case of master server
00485    const char *node_name;
00486    if (gMaster && (node_name = RerouteUser()) != 0) {
00487       // send a reroute request to the client passing the IP address
00488 
00489       char host_name[32];
00490       gethostname(host_name, sizeof(host_name));
00491 
00492       // make sure that we are not already on the target node
00493       if (strcmp(host_name, node_name) != 0) {
00494          struct hostent *host = gethostbyname(host_name);
00495          struct hostent *node;    // gethostbyname(node_name) would overwrite
00496 
00497          if (host != 0) {
00498             struct in_addr *host_addr = (struct in_addr*)(host->h_addr);
00499             char host_numb[32];
00500             if (strlen(inet_ntoa(*host_addr)) < 32) {
00501                strncpy(host_numb, inet_ntoa(*host_addr), 32);
00502                host_numb[31] = 0;
00503             }
00504 
00505             if ((node = gethostbyname(node_name)) != 0) {
00506                struct in_addr *node_addr = (struct in_addr*)(node->h_addr);
00507                char node_numb[32];
00508                strncpy(node_numb, inet_ntoa(*node_addr), 32);
00509                node_numb[31] = 0;
00510                //
00511                // compare the string representation of the IP addresses
00512                // to avoid possible problems with host name aliases
00513                //
00514                if (strcmp(host_numb, node_numb) != 0) {
00515                   msg = std::string("Reroute:").append(node_numb);
00516                   NetSend(msg.c_str());
00517                   exit(0);
00518                }
00519             }
00520          }
00521       }
00522    }
00523 
00524    // Receive buffer for final setup of authentication related stuff
00525    // This is base 64 string to decoded by proofserv, if needed
00526    if (RpdGetClientProtocol() > 12 && gRequireAuth == 1) {
00527       char *authbuff = 0;
00528       int lab = 0;
00529       if ((lab = RpdProofGetAuthSetup(&authbuff)) > 0) {
00530          // Save it in an environment variable
00531          char *rootproofauthsetup = new char[20+strlen(authbuff)];
00532          snprintf(rootproofauthsetup, 20 + strlen(authbuff), "ROOTPROOFAUTHSETUP=%s", authbuff);
00533          putenv(rootproofauthsetup);
00534       } else if (lab < 0) {
00535          ErrorInfo("ProofdExec: problems receiving auth buffer");
00536       }
00537       if (authbuff) delete[] authbuff;
00538    }
00539 
00540    if(RpdGetClientProtocol() >= 16) {
00541       void          *vb = 0;
00542       Int_t          len = 0;
00543       EMessageTypes  kind = kMESS_ANY;
00544 
00545       int rc = NetRecvAllocate(vb, len, kind);
00546 
00547       if (rc < 0) {
00548          ErrorInfo("ProofdExec: error receiving kPROOF_SETENV message");
00549          return;
00550       }
00551 
00552       if (kind != kPROOF_SETENV) {
00553          ErrorInfo("ProofdExec: expecting kPROOF_SETENV, got %d", kind);
00554          return;
00555 
00556       }
00557 
00558       char *buf = (char *) vb;
00559       char *end = buf + len;
00560       const char name[] = "PROOF_ALLVARS=";
00561       int alen = strlen(name)+len;
00562       char *all = new char[alen]; // strlen("PROOF_ALLVARS=") = 14
00563       strlcpy(all, name, alen);
00564       while (buf < end) {
00565          if (gDebug > 0) ErrorInfo("ProofdExec: setting: %s", buf);
00566          char *p = index(buf, '=');
00567          if (p) {
00568             if (buf != (char *) vb) strlcat(all, ",", alen); // skip the first one
00569             strlcat(all, buf, alen);
00570             putenv(buf);
00571          }
00572          buf += strlen(buf) + 1;
00573       }
00574       if (gDebug > 0) ErrorInfo("ProofdExec: setting: %s", all);
00575       putenv(all);
00576    }
00577 
00578    if (gDebug > 0)
00579       ErrorInfo("ProofdExec: send Okay (SockFd: %d)", sockFd);
00580    NetSend("Okay");
00581 
00582    // Find a free filedescriptor outside the standard I/O range
00583    if (sockFd == 0 || sockFd == 1 || sockFd == 2) {
00584       Int_t fd;
00585       struct stat stbuf;
00586       for (fd = 3; fd < NOFILE; fd++) {
00587          ResetErrno();
00588          if (fstat(fd, &stbuf) == -1 && GetErrno() == EBADF) {
00589             if (dup2(sockFd, fd) < 0)
00590                ErrorInfo("ProofdExec: problems executing 'dup2' (errno: %d)", errno);
00591             close(sockFd);
00592             sockFd = fd;
00593             close(2);
00594             close(1);
00595             close(0);
00596             RpdSetSysLogFlag(1);   //syslog only from here
00597             break;
00598          }
00599       }
00600 
00601       if (fd == NOFILE) {
00602          NetSend("Cannot start proofserver -- no free filedescriptor");
00603          return;
00604       }
00605    }
00606 
00607    //
00608    // Set environments vars for proofserv
00609    // Config dir
00610    char *rootconf = new char[13+gConfDir.length()];
00611    snprintf(rootconf, 13+gConfDir.length(), "ROOTCONFDIR=%s", gConfDir.c_str());
00612    putenv(rootconf);
00613    if (gDebug > 0)
00614       ErrorInfo("ProofdExec: setting: %s", rootconf);
00615    // Temp dir
00616    char *roottmp = new char[12+gTmpDir.length()];
00617    snprintf(roottmp, 12+gTmpDir.length(), "ROOTTMPDIR=%s", gTmpDir.c_str());
00618    putenv(roottmp);
00619    if (gDebug > 0)
00620       ErrorInfo("ProofdExec: setting: %s", roottmp);
00621    // User, host, rpid
00622    char *rootentity = new char[gUser.length()+gOpenHost.length()+33];
00623    snprintf(rootentity, gUser.length()+gOpenHost.length()+33,
00624            "ROOTENTITY=%s:%d@%s", gUser.c_str(), gRemPid, gOpenHost.c_str());
00625    putenv(rootentity);
00626    if (gDebug > 2)
00627       ErrorInfo("ProofdExec: setting: %s", rootentity);
00628    // Open socket
00629    char *rootopensock = new char[33];
00630    snprintf(rootopensock, 33, "ROOTOPENSOCK=%d", sockFd);
00631    putenv(rootopensock);
00632    if (gDebug > 0)
00633       ErrorInfo("ProofdExec: setting: %s", rootopensock);
00634    // ReadHomeAuthrc option
00635    char *roothomeauthrc = new char[20];
00636    snprintf(roothomeauthrc, 20, "ROOTHOMEAUTHRC=%s", gReadHomeAuthrc.c_str());
00637    putenv(roothomeauthrc);
00638    if (gDebug > 0)
00639       ErrorInfo("ProofdExec: setting: %s", roothomeauthrc);
00640 
00641 #ifdef R__GLBS
00642    // ID of shm with exported credentials
00643    char *shmidcred = new char[25];
00644    snprintf(shmidcred, 25, "ROOTSHMIDCRED=%d", RpdGetShmIdCred());
00645    putenv(shmidcred);
00646    if (gDebug > 0)
00647       ErrorInfo("ProofdExec: setting: %s", shmidcred);
00648 #endif
00649 
00650    // start server version
00651    arg0 = gRootBinDir + "/proofserv";
00652    argvv[0] = (char *)arg0.c_str();
00653    argvv[1] = (char *)(gMaster ? "proofserv" : "proofslave");
00654    argvv[2] = 0;
00655 
00656 #ifndef ROOTPREFIX
00657    char *rootsys = new char[9+gConfDir.length()];
00658    snprintf(rootsys, 9+gConfDir.length(), "ROOTSYS=%s", gConfDir.c_str());
00659    putenv(rootsys);
00660    if (gDebug > 0)
00661       ErrorInfo("ProofdExec: setting: %s", rootsys);
00662 #endif
00663 #ifndef ROOTLIBDIR
00664    char *oldpath, *ldpath;
00665 #   if defined(__hpux) || defined(_HIUX_SOURCE)
00666    if ((oldpath = getenv("SHLIB_PATH")) && strlen(oldpath) > 0) {
00667       ldpath = new char[32+gConfDir.length()+strlen(oldpath)];
00668       snprintf(ldpath, 32+gConfDir.length()+strlen(oldpath),
00669                       "SHLIB_PATH=%s/lib:%s", gConfDir.c_str(), oldpath);
00670    } else {
00671       ldpath = new char[32+gConfDir.length()];
00672       snprintf(ldpath, 32+gConfDir.length(), "SHLIB_PATH=%s/lib", gConfDir.c_str());
00673    }
00674 #   elif defined(_AIX)
00675    if ((oldpath = getenv("LIBPATH")) && strlen(oldpath) > 0) {
00676       ldpath = new char[32+gConfDir.length()+strlen(oldpath)];
00677       snprintf(ldpath, 32+gConfDir.length()+strlen(oldpath),
00678                        "LIBPATH=%s/lib:%s", gConfDir.c_str(), oldpath);
00679    } else {
00680       ldpath = new char[32+gConfDir.length()];
00681       snprintf(ldpath, 32+gConfDir.length(), "LIBPATH=%s/lib", gConfDir.c_str());
00682    }
00683 #   elif defined(__APPLE__)
00684    if ((oldpath = getenv("DYLD_LIBRARY_PATH")) && strlen(oldpath) > 0) {
00685       ldpath = new char[32+gConfDir.length()+strlen(oldpath)];
00686       snprintf(ldpath, 32+gConfDir.length()+strlen(oldpath),
00687                       "DYLD_LIBRARY_PATH=%s/lib:%s", gConfDir.c_str(), oldpath);
00688    } else {
00689       ldpath = new char[32+gConfDir.length()];
00690       snprintf(ldpath, 32+gConfDir.length(), "DYLD_LIBRARY_PATH=%s/lib", gConfDir.c_str());
00691    }
00692 #   else
00693    if ((oldpath = getenv("LD_LIBRARY_PATH")) && strlen(oldpath) > 0) {
00694       ldpath = new char[32+gConfDir.length()+strlen(oldpath)];
00695       snprintf(ldpath, 32+gConfDir.length()+strlen(oldpath),
00696                       "LD_LIBRARY_PATH=%s/lib:%s", gConfDir.c_str(), oldpath);
00697    } else {
00698       ldpath = new char[32+gConfDir.length()];
00699       snprintf(ldpath, 32+gConfDir.length(), "LD_LIBRARY_PATH=%s/lib", gConfDir.c_str());
00700    }
00701 #   endif
00702    putenv(ldpath);
00703    if (gDebug > 0)
00704       ErrorInfo("ProofdExec: setting: %s", ldpath);
00705 #endif
00706 
00707    // Check if a special file for authentication directives
00708    // has been given for later use in TAuthenticate; if yes,
00709    // set the corresponding environment variable
00710    char *authrc = 0;
00711    if (gAuthrc.length()) {
00712       if (gDebug > 0)
00713          ErrorInfo("ProofdExec: setting ROOTAUTHRC to %s",gAuthrc.c_str());
00714       authrc = new char[15+gAuthrc.length()];
00715       snprintf(authrc, 15+gAuthrc.length(), "ROOTAUTHRC=%s", gAuthrc.c_str());
00716       putenv(authrc);
00717       if (gDebug > 0)
00718          ErrorInfo("ProofdExec: setting: %s", authrc);
00719    }
00720 
00721    // For backward compatibility
00722    char *keyfile = new char[15+strlen(RpdGetKeyRoot())];
00723    snprintf(keyfile, 15+strlen(RpdGetKeyRoot()), "ROOTKEYFILE=%s",RpdGetKeyRoot());
00724    putenv(keyfile);
00725    if (gDebug > 2)
00726       ErrorInfo("ProofdExec: setting: %s", keyfile);
00727 
00728    if (gDebug > 0)
00729       ErrorInfo("ProofdExec: execv(%s, %s)", argvv[0], argvv[1]);
00730 
00731    // Start proofserv
00732    execv(arg0.c_str(), argvv);
00733 
00734    // tell client that exec failed
00735    msg = "Cannot start PROOF server --- make sure " + arg0 + " exists!";
00736    NetSend(msg.c_str());
00737 }
00738 
00739 
00740 //______________________________________________________________________________
00741 void Usage(const char* name, int rc)
00742 {
00743    fprintf(stderr, "\nUsage: %s [options] [rootsys-dir]\n", name);
00744    fprintf(stderr, "\nOptions:\n");
00745    fprintf(stderr, "\t-A [<rootauthrc>] Use $HOME/.rootauthrc or specified file\n");
00746    fprintf(stderr, "\t                  (see documentation)\n");
00747    fprintf(stderr, "\t-b tcpwindowsize  Specify the tcp window size in bytes\n");
00748 #ifdef R__GLBS
00749    fprintf(stderr, "\t-C hostcertfile   Specify the location of the Globus host certificate\n");
00750 #endif
00751    fprintf(stderr, "\t-d level          set debug level [0..3]\n");
00752    fprintf(stderr, "\t-D rootdaemonrc   Use alternate rootdaemonrc file\n");
00753    fprintf(stderr, "\t                  (see documentation)\n");
00754    fprintf(stderr, "\t-E                Ignored for backward compatibility\n");
00755    fprintf(stderr, "\t-f                Run in foreground\n");
00756 #ifdef R__GLBS
00757    fprintf(stderr, "\t-G gridmapfile    Specify the location of th Globus gridmap\n");
00758 #endif
00759    fprintf(stderr, "\t-i                Running from inetd\n");
00760    fprintf(stderr, "\t-noauth           Do not require client authentication\n");
00761    fprintf(stderr, "\t-p port#          Specify a different port to listen on\n");
00762    fprintf(stderr, "\t-s sshd_port#     Specify the port for the sshd daemon\n");
00763 #ifdef R__KRB5
00764    fprintf(stderr, "\t-S keytabfile     Use an alternate keytab file\n");
00765 #endif
00766    fprintf(stderr, "\t-T <tmpdir>       Use an alternate temp dir\n");
00767    fprintf(stderr, "\t-w                Do not check /etc/hosts.equiv and $HOME/.rhosts\n");
00768 
00769    exit(rc);
00770 }
00771 
00772 //______________________________________________________________________________
00773 int main(int argc, char **argv)
00774 {
00775    char *s;
00776    int checkhostsequiv = 1;
00777    int tcpwindowsize  = 65535;
00778    int sshdport       = 22;
00779    int port1          = 0;
00780    int port2          = 0;
00781    int reuseallow     = 0x1F;
00782    int foregroundflag = 0;
00783    std::string altSRPpass = "";
00784    std::string daemonrc = "";
00785    std::string rootetcdir = "";
00786 #ifdef R__GLBS
00787    std::string gridmap = "";
00788    std::string hostcertconf = "";
00789 #endif
00790    char *progname = argv[0];
00791 
00792    // Init error handlers
00793    RpdSetErrorHandler(Err, ErrSys, ErrFatal);
00794 
00795    // Init syslog
00796    ErrorInit(argv[0]);
00797 
00798    // Output to syslog ...
00799    RpdSetSysLogFlag(1);
00800 
00801    // ... unless we are running in the foreground and we are
00802    // attached to terminal; make also sure that "-i" and "-f"
00803    // are not simultaneously specified
00804    int i = 1;
00805    for (i = 1; i < argc; i++) {
00806       if (!strncmp(argv[i],"-f",2))
00807          foregroundflag = 1;
00808       if (!strncmp(argv[i],"-i",2))
00809          gInetdFlag = 1;
00810    }
00811    if (foregroundflag) {
00812       if (isatty(0) && isatty(1)) {
00813          RpdSetSysLogFlag(0);
00814          ErrorInfo("main: running in foreground mode:"
00815                    " sending output to stderr");
00816       }
00817       if (gInetdFlag)
00818          Error(ErrFatal,-1,"-i and -f options are incompatible");
00819    }
00820 
00821    // To terminate correctly ... maybe not needed
00822    signal(SIGTERM, ProofdTerm);
00823    signal(SIGINT, ProofdTerm);
00824 
00825    while (--argc > 0 && (*++argv)[0] == '-')
00826       for (s = argv[0]+1; *s != 0; s++)
00827          switch (*s) {
00828 
00829             case 'A':
00830                gReadHomeAuthrc = std::string("1");
00831                // Next argument may be the name of a file with the
00832                // authentication directives to be used
00833                if((*(argv+1)) && (*(argv+1))[0] != '-') {
00834                   gAuthrc = std::string(*(argv+1));
00835                   struct stat st;
00836                   if (stat(gAuthrc.c_str(),&st) == -1 || !S_ISREG(st.st_mode)) {
00837                      // Not a regular file: discard it
00838                      gAuthrc.erase();
00839                   } else {
00840                      // Got a regular file as argument: go to next
00841                      argc--;
00842                      argv++;
00843                   }
00844                }
00845                break;
00846 
00847             case 'b':
00848                if (--argc <= 0) {
00849                   Error(ErrFatal,-1,"-b requires a buffersize in bytes as"
00850                                     " argument");
00851                }
00852                tcpwindowsize = atoi(*++argv);
00853                break;
00854 #ifdef R__GLBS
00855             case 'C':
00856                if (--argc <= 0) {
00857                   Error(ErrFatal,-1,"-C requires a file name for the host"
00858                                     " certificates file location");
00859                }
00860                hostcertconf = std::string(*++argv);
00861                break;
00862 #endif
00863             case 'd':
00864                if (--argc <= 0) {
00865                   Error(ErrFatal,-1,"-d requires a debug level as argument");
00866                }
00867                gDebug = atoi(*++argv);
00868                break;
00869 
00870             case 'D':
00871                if (--argc <= 0) {
00872                   Error(ErrFatal, kErrFatal,"-D requires a file path name"
00873                                     "  for the file defining access rules");
00874                }
00875                daemonrc = std::string(*++argv);
00876                break;
00877 
00878             case 'E':
00879                Error(ErrFatal, kErrFatal,"Option '-E' is now dummy"
00880                           " - ignored (see proofd/src/proofd.cxx for"
00881                           " additional details)");
00882                break;
00883 
00884             case 'f':
00885                if (gInetdFlag) {
00886                   Error(ErrFatal,-1,"-i and -f options are incompatible");
00887                }
00888                foregroundflag = 1;
00889                break;
00890 #ifdef R__GLBS
00891             case 'G':
00892                if (--argc <= 0) {
00893                   Error(ErrFatal,-1,"-G requires a file name for the gridmap"
00894                                     " file");
00895                }
00896                gridmap = std::string(*++argv);
00897                break;
00898 #endif
00899             case 'h':
00900                Usage(progname, 0);
00901                break;
00902 
00903             case 'i':
00904                if (foregroundflag) {
00905                   Error(ErrFatal,-1,"-i and -f options are incompatible");
00906                }
00907                gInetdFlag = 1;
00908                break;
00909 
00910             case 'n':
00911                if (!strncmp(argv[0]+1,"noauth",6)) {
00912                   gRequireAuth = 0;
00913                   s += 5;
00914                }
00915                break;
00916 
00917             case 'p':
00918                if (--argc <= 0) {
00919                   Error(ErrFatal,-1,"-p requires a port number as argument");
00920                }
00921                char *p;
00922                port1 = strtol(*++argv, &p, 10);
00923                if (*p == '-') {
00924                   p++;
00925                   port2 = strtol(p, &p, 10);
00926                } else if (*p == '\0')
00927                   port2 = port1;
00928                if (*p != '\0' || port2 < port1 || port2 < 0) {
00929                   Error(ErrFatal,kErrFatal,"invalid port number or range: %s",
00930                                      *argv);
00931                }
00932                break;
00933 
00934             case 'P':
00935                if (--argc <= 0) {
00936                   Error(ErrFatal,kErrFatal,"-P requires a file name for SRP"
00937                                     " password file");
00938                }
00939                altSRPpass = std::string(*++argv);
00940                break;
00941 
00942             case 'R':
00943                if (--argc <= 0) {
00944                   Error(ErrFatal,kErrFatal,"-R requires a hex but mask as"
00945                                     " argument");
00946                }
00947                reuseallow = strtol(*++argv, (char **)0, 16);
00948                break;
00949 
00950             case 's':
00951                if (--argc <= 0) {
00952                   Error(ErrFatal,kErrFatal,"-s requires as argument a port"
00953                                     " number for the sshd daemon");
00954                }
00955                sshdport = atoi(*++argv);
00956                break;
00957 #ifdef R__KRB5
00958             case 'S':
00959                if (--argc <= 0) {
00960                   Error(ErrFatal,-1,"-S requires a path to your keytab\n");
00961                }
00962                RpdSetKeytabFile((const char *)(*++argv));
00963                break;
00964 #endif
00965             case 'T':
00966                if (--argc <= 0) {
00967                   Error(ErrFatal,kErrFatal,"-T requires a dir path for"
00968                                     " temporary files [/usr/tmp]");
00969                }
00970                gTmpDir = std::string(*++argv);
00971                break;
00972 
00973             case 'w':
00974                checkhostsequiv = 0;
00975                break;
00976 
00977             default:
00978                if (!foregroundflag) fprintf(stderr, "\nUnknown command line option: %c\n", *s);
00979                Error(0, -1, "unknown command line option: %c", *s);
00980                Usage(progname, 1);
00981          }
00982 
00983    // dir for temporary files
00984    if (!gTmpDir.length())
00985       gTmpDir = "/usr/tmp";
00986    if (access(gTmpDir.c_str(), W_OK) == -1)
00987       gTmpDir = "/tmp";
00988 
00989    if (argc > 0) {
00990       gConfDir = std::string(*argv);
00991    } else {
00992       // try to guess the config directory...
00993 #ifndef ROOTDATADIR
00994       if (getenv("ROOTSYS")) {
00995          gConfDir = getenv("ROOTSYS");
00996          if (gDebug > 0)
00997             ErrorInfo("main: no config directory specified using ROOTSYS (%s)",
00998                       gConfDir.c_str());
00999       } else {
01000          Error(ErrFatal, -1, "main: no config directory specified");
01001       }
01002 #else
01003       gConfDir = ROOTDATADIR;
01004 #endif
01005    }
01006 #ifdef ROOTBINDIR
01007    gRootBinDir= ROOTBINDIR;
01008 #endif
01009 #ifdef ROOTETCDIR
01010    rootetcdir= ROOTETCDIR;
01011 #endif
01012 
01013    // Define gRootBinDir if not done already
01014    if (!gRootBinDir.length())
01015       gRootBinDir = std::string(gConfDir).append("/bin");
01016 
01017    // make sure it contains the executable we want to run
01018    std::string arg0 = std::string(gRootBinDir).append("/proofserv");
01019    if (access(arg0.c_str(), X_OK) == -1) {
01020       Error(ErrFatal,-1,"main: incorrect config directory specified (%s)",
01021                         gConfDir.c_str());
01022    }
01023    // Make it available to all the session via env
01024    if (gRootBinDir.length()) {
01025       char *tmp = new char[15 + gRootBinDir.length()];
01026       snprintf(tmp, 15 + gRootBinDir.length(), "ROOTBINDIR=%s", gRootBinDir.c_str());
01027       putenv(tmp);
01028    }
01029 
01030    // Define rootetcdir if not done already
01031    if (!rootetcdir.length())
01032       rootetcdir = std::string(gConfDir).append("/etc");
01033    // Make it available to all the session via env
01034    if (rootetcdir.length()) {
01035       char *tmp = new char[15 + rootetcdir.length()];
01036       snprintf(tmp, 15 + rootetcdir.length(), "ROOTETCDIR=%s", rootetcdir.c_str());
01037       putenv(tmp);
01038    }
01039 
01040    // If specified, set the special daemonrc file to be used
01041    if (daemonrc.length()) {
01042       char *tmp = new char[15+daemonrc.length()];
01043       snprintf(tmp, 15+daemonrc.length(), "ROOTDAEMONRC=%s", daemonrc.c_str());
01044       putenv(tmp);
01045    }
01046 #ifdef R__GLBS
01047    // If specified, set the special gridmap file to be used
01048    if (gridmap.length()) {
01049       char *tmp = new char[15+gridmap.length()];
01050       snprintf(tmp, 15+gridmap.length(), "GRIDMAP=%s", gridmap.c_str());
01051       putenv(tmp);
01052    }
01053    // If specified, set the special hostcert.conf file to be used
01054    if (hostcertconf.length()) {
01055       char *tmp = new char[15+hostcertconf.length()];
01056       snprintf(tmp, 15+hostcertconf.length(), "ROOTHOSTCERT=%s", hostcertconf.c_str());
01057       putenv(tmp);
01058    }
01059 #endif
01060 
01061    // Parent ID
01062    int proofdparentid = -1;      // Parent process ID
01063    if (!gInetdFlag)
01064       proofdparentid = getpid(); // Identifies this family
01065    else
01066       proofdparentid = getppid(); // Identifies this family
01067 
01068    // default job options
01069    unsigned int options = kDMN_RQAUTH | kDMN_HOSTEQ | kDMN_SYSLOG ;
01070    // modify them if required
01071    if (!gRequireAuth)
01072       options &= ~kDMN_RQAUTH;
01073    if (!checkhostsequiv)
01074       options &= ~kDMN_HOSTEQ;
01075    if (foregroundflag)
01076       options &= ~kDMN_SYSLOG;
01077    RpdInit(gService, proofdparentid, gProtocol, options,
01078            reuseallow, sshdport,
01079            gTmpDir.c_str(),altSRPpass.c_str(),2);
01080 
01081    // Generate Local RSA keys for the session
01082    if (RpdGenRSAKeys(0)) {
01083       Error(Err, -1, "proofd: unable to generate local RSA keys");
01084    }
01085 
01086    if (!gInetdFlag) {
01087 
01088       // Start proofd up as a daemon process (in the background).
01089       // Also initialize the network connection - create the socket
01090       // and bind our well-know address to it.
01091 
01092       if (!foregroundflag)
01093          DaemonStart(1, 0, gService);
01094 
01095       NetInit(gService, port1, port2, tcpwindowsize);
01096    }
01097 
01098    if (gDebug > 0)
01099       ErrorInfo("main: pid = %d, gInetdFlag = %d", getpid(), gInetdFlag);
01100 
01101    // Concurrent server loop.
01102    // The child created by NetOpen() handles the client's request.
01103    // The parent waits for another request. In the inetd case,
01104    // the parent from NetOpen() never returns.
01105 
01106    while (1) {
01107       if (NetOpen(gInetdFlag, gService) == 0) {
01108 
01109          // Init Session (get protocol, run authentication, login, ...)
01110          if ((gMaster = RpdInitSession(gService, gUser, gRemPid)) < 0) {
01111             if (gMaster == -1)
01112                Error(ErrFatal, -1, "proofd: failure initializing session");
01113             else if (gMaster == -2)
01114                // special session (eg. cleanup): just exit
01115                exit(0);
01116          }
01117 
01118          ProofdExec();     // child processes client's requests
01119          NetClose();       // then we are done
01120          exit(0);
01121       }
01122 
01123       // parent waits for another client to connect
01124 
01125    }
01126 
01127 }

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