rpdutils.cxx

Go to the documentation of this file.
00001 // @(#)root/rpdutils:$Id: rpdutils.cxx 36177 2010-10-08 09:22:57Z ganis $
00002 // Author: Gerardo Ganis    7/4/2003
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 // rpdutils                                                             //
00015 //                                                                      //
00016 // Set of utilities for rootd/proofd daemon authentication.             //
00017 //                                                                      //
00018 //////////////////////////////////////////////////////////////////////////
00019 
00020 #include "RConfigure.h"
00021 #include "RConfig.h"
00022 
00023 #include <ctype.h>
00024 #include <fcntl.h>
00025 #include <pwd.h>
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include <string>
00029 #include <stdlib.h>
00030 #include <unistd.h>
00031 #include <time.h>
00032 #include <sys/time.h>
00033 #include <sys/stat.h>
00034 #include <sys/socket.h>
00035 #include <netinet/in.h>
00036 #include <errno.h>
00037 #include <netdb.h>
00038 #include <math.h>
00039 #include "snprintf.h"
00040 
00041 #if defined(__CYGWIN__) && defined(__GNUC__)
00042 #   define cygwingcc
00043 #endif
00044 
00045 #if defined(linux) || defined(__sun) || defined(__sgi) || \
00046     defined(_AIX) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
00047     defined(__APPLE__) || defined(__MACH__) || defined(cygwingcc)
00048 #include <grp.h>
00049 #include <sys/types.h>
00050 #include <signal.h>
00051 #endif
00052 
00053 #ifdef _AIX
00054 extern "C" int ruserok(char *, int, char *, char *);
00055 #endif
00056 
00057 #if defined(__alpha) && !defined(linux)
00058 #   ifdef _XOPEN_SOURCE
00059 #      if _XOPEN_SOURCE+0 > 0
00060 #         define R__TRUE64
00061 #      endif
00062 #   endif
00063 #include <sys/mount.h>
00064 #ifndef R__TRUE64
00065 extern "C" int fstatfs(int file_descriptor, struct statfs *buffer);
00066 extern "C" int ruserok(const char *, int, const char *, const char *);
00067 #endif
00068 #elif defined(__APPLE__)
00069 #include <sys/mount.h>
00070 extern "C" int fstatfs(int file_descriptor, struct statfs *buffer);
00071 #elif defined(linux) || defined(__hpux)
00072 #include <sys/vfs.h>
00073 #elif defined(__FreeBSD__) || defined(__OpenBSD__)
00074 #include <sys/param.h>
00075 #include <sys/mount.h>
00076 #else
00077 #include <sys/statfs.h>
00078 #endif
00079 
00080 #if defined(linux)
00081 #   include <features.h>
00082 #   if __GNU_LIBRARY__ == 6
00083 #      ifndef R__GLIBC
00084 #         define R__GLIBC
00085 #      endif
00086 #   endif
00087 #endif
00088 #if defined(cygwingcc) || (defined(__MACH__) && !defined(__APPLE__))
00089 #   define R__GLIBC
00090 #endif
00091 
00092 #if (defined(__FreeBSD__) && (__FreeBSD__ < 4)) || defined(__OpenBSD__) || \
00093     (defined(__APPLE__) && (!defined(MAC_OS_X_VERSION_10_3) || \
00094      (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_3)))
00095 #include <sys/file.h>
00096 #define lockf(fd, op, sz)   flock((fd), (op))
00097 #ifndef F_LOCK
00098 #define F_LOCK             (LOCK_EX | LOCK_NB)
00099 #endif
00100 #ifndef F_ULOCK
00101 #define F_ULOCK             LOCK_UN
00102 #endif
00103 #endif
00104 
00105 #if defined(cygwingcc)
00106 #define F_LOCK F_WRLCK
00107 #define F_ULOCK F_UNLCK
00108 int ruserok(const char *, int, const char *, const char *) {
00109    return 0;
00110 }
00111 static int fcntl_lockf(int fd, int op, off_t off)
00112 {
00113    flock fl;
00114    fl.l_whence = SEEK_SET;
00115    fl.l_start  = off;
00116    fl.l_len    = 0;       // whole file
00117    fl.l_pid    = getpid();
00118    fl.l_type   = op;
00119    return fcntl(fd, F_SETLK, &fl);
00120 }
00121 #define lockf fcntl_lockf
00122 #endif
00123 
00124 #if defined(__sun) || defined(R__GLIBC)
00125 #include <crypt.h>
00126 #endif
00127 
00128 #if defined(__osf__) || defined(__sgi) || defined(R__MACOSX)
00129 extern "C" char *crypt(const char *, const char *);
00130 #endif
00131 
00132 #ifdef R__WIN32
00133 #define R__NOCRYPT
00134 #endif
00135 
00136 #ifdef R__NOCRYPT
00137 static std::string gRndmSalt = std::string("ABCDEFGH");
00138 #endif
00139 
00140 #if defined(__sun)
00141 #ifndef R__SHADOWPW
00142 #define R__SHADOWPW
00143 #endif
00144 #endif
00145 
00146 #ifdef R__SHADOWPW
00147 #include <shadow.h>
00148 #endif
00149 
00150 #ifdef R__AFS
00151 #include "AFSAuth.h"
00152 #endif
00153 
00154 #ifdef R__SRP
00155 extern "C" {
00156    #include <t_pwd.h>
00157    #include <t_server.h>
00158 }
00159 #endif
00160 
00161 #ifdef R__KRB5
00162 #include "Krb5Auth.h"
00163 #include <string>
00164 extern krb5_deltat krb5_clockskew;
00165 #endif
00166 
00167 #ifdef R__SSL
00168 // SSL specific headers for RSA keys
00169 #include <openssl/bio.h>
00170 #include <openssl/blowfish.h>
00171 #include <openssl/err.h>
00172 #include <openssl/pem.h>
00173 #include <openssl/rand.h>
00174 #include <openssl/rsa.h>
00175 #include <openssl/ssl.h>
00176 #endif
00177 
00178 #include "rpdp.h"
00179 #include "rsadef.h"
00180 #include "rsalib.h"
00181 //
00182 // To improve error logging for UsrPwd on the client side
00183 static ERootdErrors gUsrPwdErr[4][4] = {
00184    {kErrNoPasswd, kErrNoPassHEquNoFiles, kErrNoPassHEquBadFiles, kErrNoPassHEquFailed},
00185    {kErrBadPasswd, kErrBadPassHEquNoFiles, kErrBadPassHEquBadFiles, kErrBadPassHEquFailed},
00186    {kErrBadRtag, kErrBadRtagHEquNoFiles, kErrBadRtagHEquBadFiles, kErrBadRtagHEquFailed},
00187    {kErrBadPwdFile, kErrBadPwdFileHEquNoFiles, kErrBadPwdFileHEquBadFiles,
00188     kErrBadPwdFileHEquFailed}};
00189 
00190 //--- Machine specific routines ------------------------------------------------
00191 
00192 #if defined(__alpha) && !defined(linux) && !defined(__FreeBSD__) && \
00193     !defined(__OpenBSD__)
00194 extern "C" int initgroups(const char *name, int basegid);
00195 #endif
00196 
00197 #if defined(__sgi) && !defined(__GNUG__) && (SGI_REL<62)
00198 extern "C" {
00199    int seteuid(int euid);
00200    int setegid(int egid);
00201 }
00202 #endif
00203 
00204 #if defined(_AIX)
00205 extern "C" {
00206    int seteuid(uid_t euid);
00207    int setegid(gid_t egid);
00208 }
00209 #endif
00210 
00211 #if !defined(__hpux) && !defined(linux) && !defined(__FreeBSD__) && \
00212     !defined(__OpenBSD__) || defined(cygwingcc)
00213 static int setresgid(gid_t r, gid_t e, gid_t)
00214 {
00215    if (setgid(r) == -1)
00216       return -1;
00217    return setegid(e);
00218 }
00219 
00220 static int setresuid(uid_t r, uid_t e, uid_t)
00221 {
00222    if (setuid(r) == -1)
00223       return -1;
00224    return seteuid(e);
00225 }
00226 #else
00227 #if defined(linux) && !defined(R__HAS_SETRESUID)
00228 extern "C" {
00229    int setresgid(gid_t r, gid_t e, gid_t s);
00230    int setresuid(uid_t r, uid_t e, uid_t s);
00231 }
00232 #endif
00233 #endif
00234 
00235 #if defined(__sun)
00236 #if defined(R__SUNGCC3)
00237 extern "C" int gethostname(char *, unsigned int);
00238 #else
00239 extern "C" int gethostname(char *, int);
00240 #endif
00241 #endif
00242 
00243 extern int gDebug;
00244 
00245 namespace ROOT {
00246 
00247 //
00248 // rpdutils module globals
00249 ErrorHandler_t gErrSys   = 0;
00250 ErrorHandler_t gErrFatal = 0;
00251 ErrorHandler_t gErr      = 0;
00252 bool gSysLog = 0;
00253 std::string gServName[3] = { "sockd", "rootd", "proofd" };
00254 
00255 //
00256 // Local global consts
00257 static const int gAUTH_CLR_MSK = 0x1;     // Masks for authentication methods
00258 static const int gAUTH_SRP_MSK = 0x2;
00259 static const int gAUTH_KRB_MSK = 0x4;
00260 static const int gAUTH_GLB_MSK = 0x8;
00261 static const int gAUTH_SSH_MSK = 0x10;
00262 static const int gMAXTABSIZE = 50000000;
00263 
00264 static const std::string gAuthMeth[kMAXSEC] = { "UsrPwd", "SRP", "Krb5",
00265                                                 "Globus", "SSH", "UidGid" };
00266 static const std::string gAuthTab    = "/rpdauthtab";   // auth table
00267 static const std::string gDaemonRc   = ".rootdaemonrc"; // daemon access rules
00268 static const std::string gRootdPass  = ".rootdpass";    // special rootd passwd
00269 static const std::string gSRootdPass = "/.srootdpass";  // SRP passwd
00270 static const std::string gKeyRoot    = "/rpk.";         // Root for key files
00271 
00272 //
00273 // RW dir for temporary files (needed by gRpdAuthTab: do not move)
00274 static std::string gTmpDir = "/tmp";
00275 
00276 //
00277 // Local global vars
00278 static int gAuthProtocol = -1;  // Protocol used fro a successful authentication
00279 static char gBufOld[kMAXRECVBUF] = {0}; // msg sync for old client (<=3.05/07)
00280 static bool gCheckHostsEquiv = 1;
00281 static int gClientOld = 0;              // msg sync for old client (<=3.05/07)
00282 static int gClientProtocol = -1;
00283 static int gCryptRequired = -1;
00284 static std::string gCryptToken;
00285 static int gAllowMeth[kMAXSEC];
00286 static std::string gAltSRPPass;
00287 static int gAnon = 0;
00288 static int gExistingAuth = 0;
00289 static int gAuthListSent = 0;
00290 static int gHaveMeth[kMAXSEC];
00291 static EMessageTypes gKindOld;          // msg sync for old client (<=3.05/07)
00292 static int gMethInit = 0;
00293 static int gNumAllow = -1;
00294 static int gNumLeft = -1;
00295 static int gOffSet = -1;
00296 static std::string gOpenHost = "????";
00297 static int gParentId = -1;
00298 static char gPasswd[kMAXUSERLEN] = { 0 };
00299 static char gPubKey[kMAXPATHLEN] = { 0 };
00300 static int gPubKeyLen = 0;
00301 static int gRandInit = 0;
00302 static int gRemPid = -1;
00303 static bool gRequireAuth = 1;
00304 static int gReUseAllow = 0x1F;  // define methods for which tokens can be asked
00305 static int gReUseRequired = -1;
00306 static int gDoLogin = 0;  // perform login
00307 static std::string gRpdAuthTab = std::string(gTmpDir).append(gAuthTab);
00308 static std::string gRpdKeyRoot = std::string(gTmpDir).append(gKeyRoot);
00309 static rsa_NUMBER gRSA_d;
00310 static rsa_NUMBER gRSA_n;
00311 static int gRSAInit = 0;
00312 static int gRSAKey = 0;
00313 static rsa_KEY gRSAPriKey;
00314 static rsa_KEY_export gRSAPubExport[2] = {{0,0},{0,0}};
00315 static rsa_KEY gRSAPubKey;
00316 #ifdef R__SSL
00317 static BF_KEY gBFKey;            // Session symmetric key
00318 static RSA *gRSASSLKey = 0;      // Local RSA SSL key
00319 #endif
00320 static int gSaltRequired = -1;
00321 static int gSec = -1;
00322 static int gServerProtocol = -1;
00323 static EService gService = kROOTD;
00324 static int gSshdPort = 22;
00325 static int gTriedMeth[kMAXSEC];
00326 static char gUser[64] = { 0 };
00327 static char *gUserAllow[kMAXSEC] = { 0 };          // User access control
00328 static unsigned int gUserAlwLen[kMAXSEC] = { 0 };
00329 static unsigned int gUserIgnLen[kMAXSEC] = { 0 };
00330 static char *gUserIgnore[kMAXSEC] = { 0 };
00331 
00332 //
00333 // Kerberos stuff
00334 #ifdef R__KRB5
00335 static krb5_context gKcontext;
00336 static krb5_keytab gKeytab = 0;        // default Keytab file can be changed
00337 static std::string gKeytabFile = "";   // via RpdSetKeytabFile
00338 #endif
00339 
00340 //
00341 // Globus stuff
00342 #ifdef R__GLBS
00343 static int gShmIdCred = -1;
00344 static gss_cred_id_t gGlbCredHandle = GSS_C_NO_CREDENTIAL;
00345 static bool gHaveGlobus = 1;
00346 static std::string gGlobusSubjName;
00347 #endif
00348 
00349 //______________________________________________________________________________
00350 static int rpd_rand()
00351 {
00352    // rand() implementation using /udev/random or /dev/random, if available
00353 
00354 #ifndef WIN32
00355    int frnd = open("/dev/urandom", O_RDONLY);
00356    if (frnd < 0) frnd = open("/dev/random", O_RDONLY);
00357    int r;
00358    if (frnd >= 0) {
00359       ssize_t rs = read(frnd, (void *) &r, sizeof(int));
00360       close(frnd);
00361       if (r < 0) r = -r;
00362       if (rs == sizeof(int)) return r;
00363    }
00364    ErrorInfo("+++ERROR+++ : rpd_rand: neither /dev/urandom nor /dev/random are available or readable!");
00365    struct timeval tv;
00366    if (gettimeofday(&tv,0) == 0) {
00367       int t1, t2;
00368       memcpy((void *)&t1, (void *)&tv.tv_sec, sizeof(int));
00369       memcpy((void *)&t2, (void *)&tv.tv_usec, sizeof(int));
00370       r = t1 + t2;
00371       if (r < 0) r = -r;
00372       return r;
00373    }
00374    return -1;
00375 #else
00376    // No special random device available: use rand()
00377    return rand();
00378 #endif
00379 }
00380 
00381 //______________________________________________________________________________
00382 static int reads(int fd, char *buf, int len)
00383 {
00384    //  reads in at most one less than len characters from open
00385    //  descriptor fd and stores them into the buffer pointed to by buf.
00386    //  Reading stops after an EOF or a newline. If a newline is
00387    //  read, it  is stored into the buffer.
00388    //  A '\0' is stored after the last character in the buffer.
00389    //  The number of characters read is returned (newline included).
00390    //  Returns < 0 in case of error.
00391 
00392    int k = 0;
00393    int nread = -1;
00394    int nr = read(fd,buf,1);
00395    while (nr > 0 && buf[k] != '\n' && k < (len-1)) {
00396       k++;
00397       nr = read(fd,buf+k,1);
00398    }
00399    if (k >= len-1) {
00400       buf[k] = 0;
00401       nread = len-1;
00402    } else if (buf[k] == '\n'){
00403       if (k <= len-2) {
00404          buf[k+1] = 0;
00405          nread = k+1;
00406       } else {
00407          buf[k] = 0;
00408          nread = k;
00409       }
00410    } else if (nr == 0) {
00411       if (k > 0) {
00412          buf[k-1] = 0;
00413          nread = k-1;
00414       } else {
00415          buf[0] = 0;
00416          nread = 0;
00417       }
00418    } else if (nr < 0) {
00419       if (k > 0) {
00420          buf[k] = 0;
00421          nread = -(k-1);
00422       } else {
00423          buf[0] = 0;
00424          nread = -1;
00425       }
00426    }
00427    // Fix the lengths
00428    if (nread >= 0) buf[nread] = 0;
00429 
00430    return nread;
00431 }
00432 
00433 //______________________________________________________________________________
00434 static int rpdstrncasecmp(const char *str1, const char *str2, int n)
00435 {
00436    // Case insensitive string compare of n characters.
00437 
00438    while (n > 0) {
00439       int c1 = *str1;
00440       int c2 = *str2;
00441 
00442       if (isupper(c1))
00443          c1 = tolower(c1);
00444 
00445       if (isupper(c2))
00446          c2 = tolower(c2);
00447 
00448       if (c1 != c2)
00449          return c1 - c2;
00450 
00451       str1++;
00452       str2++;
00453       n--;
00454    }
00455    return 0;
00456 }
00457 
00458 //______________________________________________________________________________
00459 static int rpdstrcasecmp(const char *str1, const char *str2)
00460 {
00461    // Case insensitive string compare.
00462 
00463    return rpdstrncasecmp(str1, str2, strlen(str2) + 1);
00464 }
00465 
00466 //______________________________________________________________________________
00467 static volatile void *rpdmemset(volatile void *dst, int c, int len)
00468 {
00469    // To avoid problems due to compiler optmization
00470    // Taken from Viega&Messier, "Secure Programming Cookbook", O'Really, #13.2
00471    // (see discussion there)
00472    volatile char *buf;
00473 
00474    for (buf = (volatile char *)dst; len; (buf[--len] = c)) { }
00475    return dst;
00476 }
00477 
00478 #ifdef R__NOCRYPT
00479 //______________________________________________________________________________
00480 char *rpdcrypt(const char *pw, const char *sa)
00481 {
00482    // This applies simple nor encryption with sa to the first 64 bytes
00483    // pw. Returns the hex of the result (max length 128).
00484    // This is foreseen for systms where crypt is not available
00485    // (on windows ...), to provide some protection of tokens.
00486 
00487    static char buf[129];
00488    char tbuf[64];
00489    int np = (strlen(pw) < 64) ? strlen(pw) : 64;
00490    int ns = strlen(sa);
00491    char c;
00492 
00493    int i = 0;
00494    for (i=0; i<np; i++) {
00495       // We use in turn all the salt bits; and re-use
00496       // if they are not enough
00497       int ks = i%ns;
00498       tbuf[i] = pw[i]^sa[ks];
00499       // Convert the result in two hexs: the first ...
00500       int j = 0xF & tbuf[i];
00501       if (j < 10)
00502          c = 48 + j;
00503       else
00504          c = 55 + j;
00505       int k = 2*i;
00506       buf[k] = c;
00507       // .. the second
00508       j = (0xF0 & tbuf[i]) >> 4;
00509       if (j < 10)
00510          c = 48 + j;
00511       else
00512          c = 55 + j;
00513       k = 2*i + 1;
00514       buf[k] = c;
00515    }
00516    // Null termination
00517    buf[np*2] = 0;
00518 
00519    return buf;
00520 }
00521 #endif
00522 
00523 //______________________________________________________________________________
00524 void RpdSetSysLogFlag(int syslog)
00525 {
00526    // Change the value of the static gSysLog to syslog.
00527    // Recognized values:
00528    //                       0      log to syslog (for root started daemons)
00529    //                       1      log to stderr (for user started daemons)
00530 
00531    gSysLog = syslog;
00532    if (gDebug > 2)
00533       ErrorInfo("RpdSetSysLogFlag: gSysLog set to %d", gSysLog);
00534 }
00535 
00536 //______________________________________________________________________________
00537 void RpdSetMethInitFlag(int methinit)
00538 {
00539    // Change the value of the static gMethInit to methinit.
00540    // Recognized values:
00541    //                       0      reset
00542    //                       1      initialized already
00543 
00544    gMethInit = methinit;
00545    if (gDebug > 2)
00546       ErrorInfo("RpdSetMethInitFlag: gMethInit set to %d", gMethInit);
00547 }
00548 //______________________________________________________________________________
00549 const char *RpdGetKeyRoot()
00550 {
00551    // Return pointer to the root string for key files
00552    // Used by proofd.
00553    return (const char *)gRpdKeyRoot.c_str();
00554 }
00555 
00556 //______________________________________________________________________________
00557 int RpdGetClientProtocol()
00558 {
00559    // Return protocol version run by the client.
00560    // Used by proofd.
00561    return gClientProtocol;
00562 }
00563 
00564 //______________________________________________________________________________
00565 int RpdGetAuthProtocol()
00566 {
00567    // Return authentication protocol used for the handshake.
00568    // Used by proofd.
00569    return gAuthProtocol;
00570 }
00571 
00572 //______________________________________________________________________________
00573 int RpdGetOffSet()
00574 {
00575    // Return offset in the authtab file.
00576    // Used by proofd.
00577    return gOffSet;
00578 }
00579 
00580 #ifdef R__KRB5
00581 //______________________________________________________________________________
00582 void RpdSetKeytabFile(const char *keytabfile)
00583 {
00584    // Change the value of the static gKeytab to keytab.
00585    gKeytabFile = std::string(keytabfile);
00586    if (gDebug > 2)
00587       ErrorInfo("RpdSetKeytabFile: using keytab file %s", gKeytabFile.c_str());
00588 }
00589 
00590 //______________________________________________________________________________
00591 void RpdFreeKrb5Vars(krb5_context context, krb5_principal principal,
00592                      krb5_ticket *ticket, krb5_auth_context auth_context,
00593                      krb5_creds **creds)
00594 {
00595    // Free allocated quantities for Krb stuff
00596 
00597    if (context) {
00598       // free creds
00599       if (creds)
00600          krb5_free_tgt_creds(context,creds);
00601 
00602       // free auth_context
00603       if (auth_context)
00604          krb5_auth_con_free(context, auth_context);
00605 
00606       // free ticket
00607       if (ticket)
00608          krb5_free_ticket(context,ticket);
00609 
00610       // free principal
00611       if (principal)
00612          krb5_free_principal(context, principal);
00613 
00614       // free context
00615       krb5_free_context(context);
00616    }
00617 }
00618 
00619 #endif
00620 
00621 //______________________________________________________________________________
00622 int RpdGetAuthMethod(int kind)
00623 {
00624    int method = -1;
00625 
00626    if (kind == kROOTD_USER)
00627       method = 0;
00628    if (kind == kROOTD_SRPUSER)
00629       method = 1;
00630    if (kind == kROOTD_KRB5)
00631       method = 2;
00632    if (kind == kROOTD_GLOBUS)
00633       method = 3;
00634    if (kind == kROOTD_SSH)
00635       method = 4;
00636    if (kind == kROOTD_RFIO)
00637       method = 5;
00638 
00639    return method;
00640 }
00641 
00642 //______________________________________________________________________________
00643 int RpdDeleteKeyFile(int ofs)
00644 {
00645    // Delete Public Key file
00646    // Returns: 0 if ok
00647    //          1 if error unlinking (check errno);
00648    int retval = 0;
00649 
00650    std::string pukfile = gRpdKeyRoot;
00651    pukfile.append(ItoA(ofs));
00652 
00653    // Some debug info
00654    if (gDebug > 2) {
00655       ErrorInfo("RpdDeleteKeyFile: proc uid:%d gid:%d",
00656       getuid(),getgid());
00657    }
00658 
00659    // Unlink
00660    if (unlink(pukfile.c_str()) == -1) {
00661       if (gDebug > 0 && GetErrno() != ENOENT) {
00662          ErrorInfo("RpdDeleteKeyFile: problems unlinking pub"
00663                    " key file '%s' (errno: %d)",
00664                    pukfile.c_str(),GetErrno());
00665       }
00666       retval = 1;
00667    }
00668    return retval;
00669 }
00670 
00671 //______________________________________________________________________________
00672 int RpdUpdateAuthTab(int opt, const char *line, char **token, int ilck)
00673 {
00674    // Update tab file.
00675    // If ilck <= 0 open and lock the file; if ilck > 0, use file
00676    // descriptor ilck, which should correspond to an open and locked file.
00677    // If opt = -1 : delete file (backup saved in <file>.bak);
00678    // If opt =  0 : eliminate all inactive entries
00679    //               (if line="size" act only if size > gMAXTABSIZE)
00680    // if opt =  1 : append 'line'.
00681    // Returns -1 in case of error.
00682    // Returns offset for 'line' and token for opt = 1.
00683    // Returns new file size for opt = 0.
00684 
00685    int retval = -1;
00686    int itab = 0;
00687    char fbuf[kMAXPATHLEN];
00688 
00689    if (gDebug > 2)
00690       ErrorInfo("RpdUpdateAuthTab: analyzing: opt: %d, line: %s, ilck: %d",
00691                 opt, line, ilck);
00692 
00693    if (ilck <= 0) {
00694 
00695       // Open file for reading/ writing
00696       itab = open(gRpdAuthTab.c_str(), O_RDWR);
00697       if (itab == -1) {
00698          if (opt == 1 && GetErrno() == ENOENT) {
00699             // Try creating the file
00700             itab = open(gRpdAuthTab.c_str(), O_RDWR | O_CREAT, 0600);
00701             if (itab == -1) {
00702                ErrorInfo("RpdUpdateAuthTab: opt=%d: error opening %s"
00703                          "(errno: %d)",
00704                          opt, gRpdAuthTab.c_str(), GetErrno());
00705                return retval;
00706             }
00707          } else {
00708             ErrorInfo("RpdUpdateAuthTab: opt=%d: error opening %s"
00709                       " (errno: %d)",
00710                        opt, gRpdAuthTab.c_str(), GetErrno());
00711             return retval;
00712          }
00713       }
00714 
00715       // lock tab file
00716       if (lockf(itab, F_LOCK, (off_t) 1) == -1) {
00717          ErrorInfo("RpdUpdateAuthTab: opt=%d: error locking %s"
00718                    " (errno: %d)", opt, gRpdAuthTab.c_str(), GetErrno());
00719          close(itab);
00720          return retval;
00721       }
00722       if (gDebug > 0)
00723          ErrorInfo("RpdUpdateAuthTab: opt= %d - file LOCKED", opt);
00724    } else {
00725       itab = ilck;
00726    }
00727 
00728    // File size
00729    int fsize = 0;
00730    if ((fsize = lseek(itab, 0, SEEK_END)) == -1) {
00731       ErrorInfo("RpdUpdateAuthTab: opt=%d: lseek error (errno: %d)",
00732            opt, GetErrno());
00733       goto goingout;
00734    }
00735 
00736    // Set indicator to beginning
00737    if (lseek(itab, 0, SEEK_SET) == -1) {
00738       ErrorInfo("RpdUpdateAuthTab: opt=%d: lseek error (errno: %d)",
00739            opt, GetErrno());
00740       goto goingout;
00741    }
00742 
00743    if (opt == -1) {
00744 
00745       //
00746       // Save file in .bak and delete its content
00747 
00748       // Open backup file
00749       std::string bak = std::string(gRpdAuthTab).append(".bak");
00750       int ibak = open(bak.c_str(), O_RDWR | O_CREAT, 0600);
00751       if (ibak == -1) {
00752          ErrorInfo("RpdUpdateAuthTab: opt=%d: error opening/creating %s"
00753                    " (errno: %d)", opt, bak.c_str(), GetErrno());
00754          goto goingout;
00755       }
00756 
00757       // Truncate file to new length
00758       if (ftruncate(ibak, 0) == -1)
00759          ErrorInfo("RpdUpdateAuthTab: opt=%d: ftruncate error (%s)"
00760                    " (errno: %d)", opt, bak.c_str(), GetErrno());
00761 
00762       // Copy the content
00763       char buf[kMAXPATHLEN];
00764       int ofs = 0, nr = 0;
00765       while ((nr = reads(itab, buf, sizeof(buf)))) {
00766          int slen = strlen(buf);
00767 
00768          // Make sure there is a '\n' before writing
00769          if (buf[slen-1] != '\n') {
00770             if (slen >= kMAXPATHLEN -1)
00771                buf[slen-1] = '\n';
00772             else {
00773                buf[slen] = '\n';
00774                buf[slen+1] = '\0';
00775             }
00776          }
00777          if (slen) {
00778             while (write(ibak, buf, slen) < 0 && GetErrno() == EINTR)
00779                ResetErrno();
00780          }
00781 
00782          // Delete Public Key file
00783          RpdDeleteKeyFile(ofs);
00784          // Next OffSet
00785          ofs += slen;
00786       }
00787       close(ibak);
00788 
00789       // Truncate file to new length
00790       if (ftruncate(itab, 0) == -1)
00791          ErrorInfo("RpdUpdateAuthTab: opt=%d: ftruncate error (%s)"
00792                    " (errno: %d)", opt, gRpdAuthTab.c_str(), GetErrno());
00793       retval = 0;
00794 
00795    } else if (opt == 0) {
00796 
00797       //
00798       // Cleanup the file (remove inactive entries)
00799 
00800       // Now scan over entries
00801       int pr = 0, pw = 0;
00802       int lsec, act, oldofs = 0, bytesread = 0;
00803       char ln[kMAXPATHLEN], dumm[kMAXPATHLEN];
00804       bool fwr = 0;
00805 
00806       while ((bytesread = reads(itab, ln, sizeof(ln)))) {
00807 
00808          bool ok = 1;
00809          // Current position
00810          if ((pr = lseek(itab,0,SEEK_CUR)) < 0) {
00811             ErrorInfo("RpdUpdateAuthTab: opt=%d: problems lseeking file %s"
00812                       " (errno: %d)", opt, gRpdAuthTab.c_str(), errno);
00813             fwr = 1;
00814             ok = 0;
00815          }
00816 
00817          // Check file corruption: length and number of items
00818          int slen = bytesread;
00819          if (ok && slen < 1) {
00820             ErrorInfo("RpdUpdateAuthTab: opt=%d: file %s seems corrupted"
00821                       " (slen: %d)", opt, gRpdAuthTab.c_str(), slen);
00822             fwr = 1;
00823             ok = 0;
00824          }
00825          if (ok) {
00826             // Check file corruption: number of items
00827             int ns = sscanf(ln, "%d %d %4095s", &lsec, &act, dumm);
00828             if (ns < 3 ) {
00829                ErrorInfo("RpdUpdateAuthTab: opt=%d: file %s seems corrupted"
00830                          " (ns: %d)", opt, gRpdAuthTab.c_str(), ns);
00831                fwr = 1;
00832                ok = 0;
00833             }
00834          }
00835 
00836          if (ok && act > 0) {
00837             if (fwr) {
00838                // We have to update the key file name
00839                int nr = 0;
00840                if ((nr = RpdRenameKeyFile(oldofs,pw)) == 0) {
00841                   // Write the entry at new position
00842                   lseek(itab, pw, SEEK_SET);
00843 
00844                   if (ln[slen-1] != '\n') {
00845                      if (slen >= kMAXPATHLEN -1)
00846                         ln[slen-1] = '\n';
00847                      else {
00848                         ln[slen] = '\n';
00849                         ln[slen+1] = '\0';
00850                      }
00851                   }
00852                   while (write(itab, ln, strlen(ln)) < 0
00853                          && GetErrno() == EINTR)
00854                      ResetErrno();
00855                   pw += strlen(ln);
00856                } else
00857                   RpdDeleteKeyFile(oldofs);
00858                lseek(itab, pr, SEEK_SET);
00859             } else
00860                pw += strlen(ln);
00861          } else {
00862             fwr = 1;
00863          }
00864          // Set old offset
00865          oldofs = pr;
00866       }
00867 
00868       // Truncate file to new length
00869       if (ftruncate(itab, pw) == -1)
00870          ErrorInfo("RpdUpdateAuthTab: opt=%d: ftruncate error (errno: %d)",
00871               opt, GetErrno());
00872 
00873       // Return new file size
00874       retval = pw;
00875 
00876    } else if (opt == 1) {
00877 
00878       //
00879       // Add 'line' at the end
00880       // (check size and cleanup/truncate if needed)
00881 
00882       // Check size ...
00883       if ((int)(fsize+strlen(line)) > gMAXTABSIZE) {
00884 
00885          // If it is going to be too big, cleanup or truncate first
00886          fsize = RpdUpdateAuthTab(0,(const char *)0,0,itab);
00887 
00888          // If still too big: delete everything
00889          if ((int)(fsize+strlen(line)) > gMAXTABSIZE)
00890             fsize = RpdUpdateAuthTab(-1,(const char *)0,0,itab);
00891       }
00892       // We are going to write at the end
00893       retval = lseek(itab, 0, SEEK_END);
00894 
00895       // Save first RSA public key into file for later use by the
00896       // same or other rootd/proofd; we will update the tab file
00897       // only if this operation is successful
00898       int ntry = 10;
00899       int rs = 0;
00900       while ((rs = RpdSavePubKey(gPubKey, retval, gUser)) == 2 && ntry--) {
00901          // We are here if a file with the same name exists already
00902          // and can not be deleted: we shift the offset with a
00903          // dummy entry
00904          char ltmp[256];
00905          SPrintf(ltmp, 256,
00906                  "0 0 %d %d %s error: pubkey file in use: shift offset\n",
00907                  gRSAKey, gRemPid, gOpenHost.c_str());
00908 
00909          // adds line
00910          while (write(itab, ltmp, strlen(ltmp)) < 0 && GetErrno() == EINTR)
00911             ResetErrno();
00912 
00913          // Set to the new end
00914          retval = lseek(itab, 0, SEEK_END);
00915       }
00916 
00917       if (rs > 0) {
00918          // Something wrong
00919          retval = -1;
00920          if (gDebug > 0)
00921             ErrorInfo("RpdUpdateAuthTab: pub key could not be saved (%d)",rs);
00922       } else {
00923          // Generate token
00924          *token = RpdGetRandString(3, 8);   // 8 crypt-like chars
00925 #ifndef R__NOCRYPT
00926          char *cryptToken = crypt(*token, *token);
00927 #else
00928          char *cryptToken = rpdcrypt(*token,gRndmSalt.c_str());
00929 #endif
00930          SPrintf(fbuf, kMAXPATHLEN, "%s %s\n", line, cryptToken);
00931          if (gDebug > 2)
00932             ErrorInfo("RpdUpdateAuthTab: token: '%s'", cryptToken);
00933          // Save it for later use in kSOCKD servers
00934          gCryptToken = std::string(cryptToken);
00935 
00936          // adds line
00937          while (write(itab, fbuf, strlen(fbuf)) < 0 && GetErrno() == EINTR)
00938             ResetErrno();
00939       }
00940 
00941    } else {
00942 
00943       //
00944       // Unknown option
00945       ErrorInfo("RpdUpdateAuthTab: unrecognized option (opt= %d)", opt);
00946    }
00947 
00948    goingout:
00949    if (ilck == 0) {
00950       // unlock the file
00951       lseek(itab, 0, SEEK_SET);
00952       if (lockf(itab, F_ULOCK, (off_t) 1) == -1) {
00953          ErrorInfo("RpdUpdateAuthTab: error unlocking %s",
00954                    gRpdAuthTab.c_str());
00955       }
00956 
00957       // closing file ...
00958       close(itab);
00959    }
00960 
00961    return retval;
00962 }
00963 
00964 //______________________________________________________________________________
00965 int RpdCleanupAuthTab(const char *crypttoken)
00966 {
00967    // De-activates entry related to token with crypt crypttoken.
00968    // Returns: 0 if successful
00969    //         -4 if entry not found or inactive
00970    //         -1 problems opening auth tab file
00971    //         -2 problems locking auth tab file
00972    //         -3 auth tab file does not exists
00973 
00974    int retval = -4;
00975 
00976    if (gDebug > 2)
00977       ErrorInfo("RpdCleanupAuthTab: Crypt-token: '%s'",crypttoken);
00978 
00979    // Open file for update
00980    int itab = -1;
00981    if ((itab = open(gRpdAuthTab.c_str(), O_RDWR)) == -1) {
00982       if (GetErrno() == ENOENT) {
00983          if (gDebug > 0)
00984             ErrorInfo("RpdCleanupAuthTab: file %s does not exist",
00985                        gRpdAuthTab.c_str());
00986          return -3;
00987       } else {
00988          ErrorInfo("RpdCleanupAuthTab: error opening %s (errno: %d)",
00989                   gRpdAuthTab.c_str(), GetErrno());
00990          return -1;
00991       }
00992    }
00993 
00994    // lock tab file
00995    if (lockf(itab, F_LOCK, (off_t) 1) == -1) {
00996       ErrorInfo("RpdCleanupAuthTab: error locking %s (errno: %d)",
00997                 gRpdAuthTab.c_str(), GetErrno());
00998       close(itab);
00999       return -2;
01000    }
01001    if (gDebug > 0)
01002       ErrorInfo("RpdCleanupAuthTab: file LOCKED (ctkn: '%s')",crypttoken);
01003 
01004 
01005    // Now access entry or scan over entries
01006    int pr = 0, pw = 0;
01007    int nw, lsec, act, remid, pkey;
01008    char line[kMAXPATHLEN];
01009 
01010    // Set indicators
01011    if ((pr = lseek(itab, 0, SEEK_SET)) < 0) {
01012       ErrorInfo("RpdCleanupAuthTab: error lseeking %s (errno: %d)",
01013                 gRpdAuthTab.c_str(), GetErrno());
01014       close(itab);
01015       return -2;
01016    }
01017    pw = pr;
01018    while (reads(itab,line, sizeof(line))) {
01019 
01020       pr += strlen(line);
01021       if (gDebug > 2)
01022          ErrorInfo("RpdCleanupAuthTab: pr:%d pw:%d (line:%s) (pId:%d)",
01023                     pr, pw, line, gParentId);
01024 
01025       char dum1[kMAXPATHLEN] = {0}, host[kMAXUSERLEN] = {0}, user[kMAXUSERLEN] = {0},
01026            ctkn[30] = {0}, dum2[30] = {0};
01027       nw = sscanf(line, "%d %d %d %d %127s %127s %29s %4095s %29s",
01028                         &lsec, &act, &pkey, &remid, host, user, ctkn, dum1, dum2);
01029 
01030       int deactivate = 0;
01031 
01032       if (act > 0) {
01033 
01034          if (lsec == 3 && nw == 9) {
01035             if (!strncmp(dum2,crypttoken,strlen(crypttoken)))
01036                deactivate = 1;
01037          } else if (nw == 7) {
01038             if (!strncmp(ctkn,crypttoken,strlen(crypttoken)))
01039                deactivate = 1;
01040          }
01041 
01042          // Deactivate active entries: remote client has gone ...
01043          if (deactivate) {
01044 
01045             retval = 0;
01046 
01047             // Delete Public Key file
01048             RpdDeleteKeyFile(pw);
01049 
01050 #ifdef R__GLBS
01051             if (lsec == 3) {
01052                int shmid = atoi(ctkn);
01053                struct shmid_ds shm_ds;
01054                if (shmctl(shmid, IPC_RMID, &shm_ds) == -1) {
01055                   if (GetErrno() != EIDRM) {
01056                      ErrorInfo("RpdCleanupAuthTab: unable to mark shared"
01057                                " memory segment %d (buf:%s)", shmid, ctkn);
01058                      ErrorInfo("RpdCleanupAuthTab: for destruction"
01059                                " (errno: %d)", GetErrno());
01060                      retval++;
01061                   }
01062                }
01063             }
01064 #endif
01065             // Locate 'act' ... skeep initial spaces, if any
01066             int slen = (int)strlen(line);
01067             int ka = 0;
01068             while (ka < slen && line[ka] == 32)
01069                ka++;
01070             // skeep method
01071             while (ka < slen && line[ka] != 32)
01072                ka++;
01073             // skeep spaces before 'act'
01074             while (ka < slen && line[ka] == 32)
01075                ka++;
01076             // This is 'act'
01077             line[ka] = '0';
01078             // Make sure there is a '\n' before writing
01079             int sl = strlen(line);
01080             if (line[sl-1] != '\n') {
01081                if (sl >= kMAXPATHLEN -1)
01082                   line[sl-1] = '\n';
01083                else {
01084                   line[sl] = '\n';
01085                   line[sl+1] = '\0';
01086                }
01087             }
01088             // Write it now
01089             lseek(itab, pw, SEEK_SET);
01090             while (write(itab, line, strlen(line)) < 0
01091                    && GetErrno() == EINTR)
01092                ResetErrno();
01093             // We are done
01094             lseek(itab,  0, SEEK_END);
01095          }
01096       }
01097       pw = pr;
01098    }
01099 
01100    // unlock the file
01101    lseek(itab, 0, SEEK_SET);
01102    if (lockf(itab, F_ULOCK, (off_t) 1) == -1) {
01103       ErrorInfo("RpdCleanupAuthTab: error unlocking %s", gRpdAuthTab.c_str());
01104    }
01105    // closing file ...
01106    close(itab);
01107 
01108    return retval;
01109 }
01110 
01111 //______________________________________________________________________________
01112 int RpdCleanupAuthTab(const char *Host, int RemId, int OffSet)
01113 {
01114    // In tab file, cleanup (set inactive) entry at offset
01115    // 'OffSet' from remote PiD 'RemId' at 'Host'.
01116    // If Host="all" or RemId=0 discard all entries.
01117    // Return number of entries not cleaned properly ...
01118 
01119    int retval = 0;
01120 
01121    if (gDebug > 2)
01122       ErrorInfo("RpdCleanupAuthTab: Host: '%s', RemId:%d, OffSet: %d",
01123                 Host, RemId, OffSet);
01124 
01125    // Open file for update
01126    int itab = -1;
01127    if ((itab = open(gRpdAuthTab.c_str(), O_RDWR)) == -1) {
01128       if (GetErrno() == ENOENT) {
01129          if (gDebug > 0)
01130             ErrorInfo("RpdCleanupAuthTab: file %s does not exist",
01131                        gRpdAuthTab.c_str());
01132          return -3;
01133       } else {
01134          ErrorInfo("RpdCleanupAuthTab: error opening %s (errno: %d)",
01135                   gRpdAuthTab.c_str(), GetErrno());
01136          return -1;
01137       }
01138    }
01139 
01140    // lock tab file
01141    if (lockf(itab, F_LOCK, (off_t) 1) == -1) {
01142       ErrorInfo("RpdCleanupAuthTab: error locking %s (errno: %d)",
01143                 gRpdAuthTab.c_str(), GetErrno());
01144       close(itab);
01145       //     return retval;
01146       return -2;
01147    }
01148    if (gDebug > 0)
01149       ErrorInfo("RpdCleanupAuthTab: file LOCKED"
01150                 " (Host: '%s', RemId:%d, OffSet: %d)",
01151                   Host, RemId, OffSet);
01152 
01153    // Now access entry or scan over entries
01154    int pr = 0, pw = 0;
01155    int nw, lsec, act, remid, pkey;
01156    char line[kMAXPATHLEN];
01157 
01158    // Clean all flag
01159    int all = (!strcmp(Host, "all") || RemId == 0);
01160 
01161    // Set indicator
01162    if (all || OffSet < 0)
01163       pr = lseek(itab, 0, SEEK_SET);
01164    else
01165       pr = lseek(itab, OffSet, SEEK_SET);
01166    if (pr < 0) {
01167       ErrorInfo("RpdCleanupAuthTab: error lseeking %s (errno: %d)",
01168                 gRpdAuthTab.c_str(), GetErrno());
01169       close(itab);
01170       //     return retval;
01171       return -2;
01172    }
01173    pw = pr;
01174    while (reads(itab,line, sizeof(line))) {
01175 
01176       pr += strlen(line);
01177       if (gDebug > 2)
01178          ErrorInfo("RpdCleanupAuthTab: pr:%d pw:%d (line:%s) (pId:%d)",
01179                     pr, pw, line, gParentId);
01180 
01181       char dumm[kMAXPATHLEN], host[kMAXUSERLEN], user[kMAXUSERLEN], shmbuf[30];
01182       nw = sscanf(line, "%d %d %d %d %127s %127s %29s %4095s",
01183                         &lsec, &act, &pkey, &remid, host, user, shmbuf, dumm);
01184 
01185       if (nw > 5) {
01186          if (all || OffSet > -1 ||
01187             (strstr(line,Host) && (RemId == remid))) {
01188 
01189             // Delete Public Key file
01190             RpdDeleteKeyFile(pw);
01191 
01192 #ifdef R__GLBS
01193             if (lsec == 3 && act > 0) {
01194                int shmid = atoi(shmbuf);
01195                struct shmid_ds shm_ds;
01196                if (shmctl(shmid, IPC_RMID, &shm_ds) == -1) {
01197                   if (GetErrno() != EIDRM) {
01198                      ErrorInfo("RpdCleanupAuthTab: unable to mark shared"
01199                                " memory segment %d (buf:%s)", shmid, shmbuf);
01200                      ErrorInfo("RpdCleanupAuthTab: for destruction"
01201                                " (errno: %d)", GetErrno());
01202                      retval++;
01203                   }
01204                }
01205             }
01206 #endif
01207             // Deactivate active entries: remote client has gone ...
01208             if (act > 0) {
01209 
01210                // Locate 'act' ... skeep initial spaces, if any
01211                int slen = (int)strlen(line);
01212                int ka = 0;
01213                while (ka < slen && line[ka] == 32)
01214                   ka++;
01215                // skeep method
01216                while (ka < slen && line[ka] != 32)
01217                   ka++;
01218                // skeep spaces before 'act'
01219                while (ka < slen && line[ka] == 32)
01220                   ka++;
01221                // This is 'act'
01222                line[ka] = '0';
01223                // Make sure there is a '\n' before writing
01224                int sl = strlen(line);
01225                if (line[sl-1] != '\n') {
01226                   if (sl >= kMAXPATHLEN -1)
01227                      line[sl-1] = '\n';
01228                   else {
01229                      line[sl] = '\n';
01230                      line[sl+1] = '\0';
01231                   }
01232                }
01233                // Write it now
01234                lseek(itab, pw, SEEK_SET);
01235                while (write(itab, line, strlen(line)) < 0
01236                       && GetErrno() == EINTR)
01237                   ResetErrno();
01238                if (all || OffSet < 0)
01239                   lseek(itab, pr, SEEK_SET);
01240                else
01241                   lseek(itab,  0, SEEK_END);
01242             }
01243          }
01244       }
01245       pw = pr;
01246    }
01247 
01248    // unlock the file
01249    lseek(itab, 0, SEEK_SET);
01250    if (lockf(itab, F_ULOCK, (off_t) 1) == -1) {
01251       ErrorInfo("RpdCleanupAuthTab: error unlocking %s", gRpdAuthTab.c_str());
01252    }
01253    // closing file ...
01254    close(itab);
01255 
01256    return retval;
01257 }
01258 
01259 //______________________________________________________________________________
01260 int RpdCheckAuthTab(int Sec, const char *User, const char *Host, int RemId,
01261                     int *OffSet)
01262 {
01263    // Check authentication entry in tab file.
01264 
01265    int retval = 0;
01266    if (gDebug > 2)
01267       ErrorInfo("RpdCheckAuthTab: analyzing: %d %s %s %d %d", Sec, User,
01268                 Host, RemId, *OffSet);
01269 
01270    // Check OffSet first
01271    char *tkn = 0, *user =0;
01272    int shmid;
01273    bool goodOfs = RpdCheckOffSet(Sec,User,Host,RemId,
01274                                  OffSet,&tkn,&shmid,&user);
01275    if (gDebug > 2)
01276       ErrorInfo("RpdCheckAuthTab: goodOfs: %d", goodOfs);
01277 
01278    // Notify the result of the check
01279    int tag = 0;
01280    if (gClientProtocol >= 10) {
01281       if (goodOfs) {
01282          if (gClientProtocol > 11) {
01283             // Generate tag
01284             RpdInitRand();
01285             while ((tag = rpd_rand()) == 1) ; // .ne.1 for backward comptibility
01286 
01287             // We will receive the user token next
01288             NetSend(tag, kROOTD_AUTH);
01289          } else
01290             // We will receive the user token next
01291             NetSend(1, kROOTD_AUTH);
01292       } else {
01293          // No authentication available for re-use
01294          NetSend(0, kROOTD_AUTH);
01295          // Cleanup and return: we need a new one ...
01296          if (tkn) delete[] tkn;
01297          if (user) delete[] user;
01298          // ... no need to continue receiving the old token
01299          return retval;
01300       }
01301    }
01302 
01303    // Now Receive Token
01304    int ofs = *OffSet;
01305    char *token = 0;
01306    if (gRSAKey > 0) {
01307       if (RpdSecureRecv(&token) == -1) {
01308          ErrorInfo("RpdCheckAuthTab: problems secure-"
01309                    "receiving token %s",
01310                    "- may result in authentication failure ");
01311       }
01312 
01313    } else {
01314       EMessageTypes kind;
01315       int lenToken = 9;
01316       token = new char[lenToken];
01317       NetRecv(token, lenToken, kind);
01318       if (kind != kMESS_STRING)
01319          ErrorInfo
01320              ("RpdCheckAuthTab: got msg kind: %d instead of %d (kMESS_STRING)",
01321               kind, kMESS_STRING);
01322       // Invert Token
01323       for (int i = 0; i < (int) strlen(token); i++) {
01324          token[i] = ~token[i];
01325       }
01326    }
01327    if (gDebug > 2)
01328       ErrorInfo
01329           ("RpdCheckAuthTab: received from client: token: '%s' ",
01330            token);
01331 
01332    // Check tag, if there
01333    if (token && strlen(token) > 8) {
01334       // Create hex from tag
01335       char tagref[9] = {0};
01336       SPrintf(tagref,9,"%08x",tag);
01337       if (strncmp(token+8,tagref,8)) {
01338          ErrorInfo("RpdCheckAuthTab: token tag does not match - failure");
01339          goodOfs = 0;
01340       } else
01341          // Drop tag
01342          token[8] = 0;
01343    }
01344 
01345    // Now check Token validity
01346    if (goodOfs && token && RpdCheckToken(token, tkn)) {
01347 
01348       if (Sec == 3) {
01349 #ifdef R__GLBS
01350          // kGlobus:
01351          if (GlbsToolCheckContext(shmid)) {
01352             retval = 1;
01353             strlcpy(gUser, user, sizeof(gUser));
01354          } else {
01355             // set entry inactive
01356             RpdCleanupAuthTab(Host,RemId,*OffSet);
01357          }
01358 #else
01359          ErrorInfo
01360                 ("RpdCheckAuthTab: compiled without Globus support:%s",
01361                  " you shouldn't have got here!");
01362 #endif
01363       } else {
01364             retval = 1;
01365       }
01366 
01367       // Comunicate new offset to remote client
01368       if (retval) *OffSet = ofs;
01369    }
01370 
01371    if (tkn) delete[] tkn;
01372    if (token) delete[] token;
01373    if (user) delete[] user;
01374 
01375    return retval;
01376 }
01377 
01378 //______________________________________________________________________________
01379 int RpdCheckOffSet(int Sec, const char *User, const char *Host, int RemId,
01380                    int *OffSet, char **Token, int *ShmId, char **GlbsUser)
01381 {
01382    // Check offset received from client entry in tab file.
01383 
01384    int retval = 0;
01385    bool goodOfs = 0;
01386    int ofs = *OffSet >= 0 ? *OffSet : 0;
01387 
01388    if (gDebug > 2)
01389       ErrorInfo("RpdCheckOffSet: analyzing: %d %s %s %d %d", Sec, User,
01390                 Host, RemId, *OffSet);
01391 
01392    // Open file
01393    int itab = open(gRpdAuthTab.c_str(), O_RDWR);
01394    if (itab == -1) {
01395       if (GetErrno() == ENOENT)
01396          ErrorInfo("RpcCheckOffSet: file %s does not exist",
01397                    gRpdAuthTab.c_str());
01398       else
01399          ErrorInfo("RpcCheckOffSet: error opening %s (errno: %d)",
01400                    gRpdAuthTab.c_str(), GetErrno());
01401       return retval;
01402    }
01403    // lock tab file
01404    if (lockf(itab, F_LOCK, (off_t) 1) == -1) {
01405       ErrorInfo("RpcCheckOffSet: error locking %s (errno: %d)",
01406                 gRpdAuthTab.c_str(), GetErrno());
01407       close(itab);
01408       return retval;
01409    }
01410    if (gDebug > 0)
01411       ErrorInfo("RpdCheckOffSet: file LOCKED");
01412 
01413    // File is open: set position at wanted location
01414    if (lseek(itab, ofs, SEEK_SET) < 0) {
01415       ErrorInfo("RpcCheckOffSet: error lseeking %s (errno: %d)",
01416                 gRpdAuthTab.c_str(), GetErrno());
01417       close(itab);
01418       return retval;
01419    }
01420 
01421    // Now read the entry
01422    char line[kMAXPATHLEN];
01423    if (reads(itab,line, sizeof(line)) < 0) {
01424       ErrorInfo("RpcCheckOffSet: error reading %d bytes from %s (errno: %d)",
01425                 sizeof(line), gRpdAuthTab.c_str(), GetErrno());
01426       close(itab);
01427       return retval;
01428    }
01429 
01430    // and parse its content according to auth method
01431    int lsec, act, remid, shmid = -1;
01432    char host[kMAXPATHLEN], usr[kMAXPATHLEN], subj[kMAXPATHLEN],
01433        dumm[kMAXPATHLEN], tkn[20];
01434    int nw =
01435        sscanf(line, "%d %d %d %d %4095s %4095s %19s %4095s",
01436                     &lsec, &act, &gRSAKey, &remid, host, usr, tkn, dumm);
01437    if (gDebug > 2)
01438       ErrorInfo("RpdCheckOffSet: found line: %s", line);
01439 
01440    if (nw > 5 && act > 0) {
01441       if ((lsec == Sec)) {
01442          if (lsec == 3) {
01443             sscanf(line, "%d %d %d %d %4095s %4095s %d %4095s %19s %4095s",
01444                          &lsec, &act, &gRSAKey, &remid, host, usr, &shmid, subj, tkn, dumm);
01445             if ((remid == RemId)
01446                 && !strcmp(host, Host) && !strcmp(subj, User))
01447                goodOfs = 1;
01448          } else {
01449             if ((remid == RemId) &&
01450                 !strcmp(host, Host) && !strcmp(usr, User))
01451                goodOfs = 1;
01452          }
01453       }
01454    }
01455    if (!goodOfs) {
01456       // Tab may have been cleaned in the meantime ... try a scan
01457       lseek(itab, 0, SEEK_SET);
01458       ofs = 0;
01459       while (reads(itab, line, sizeof(line))) {
01460 
01461          nw = sscanf(line, "%d %d %d %d %4095s %4095s %19s %4095s",
01462                      &lsec, &act, &gRSAKey, &remid, host, usr, tkn, dumm);
01463          if (gDebug > 2)
01464             ErrorInfo("RpdCheckOffSet: found line: %s", line);
01465 
01466          if (nw > 5 && act > 0) {
01467             if (lsec == Sec) {
01468                if (lsec == 3) {
01469                   sscanf(line, "%d %d %d %d %4095s %4095s %d %4095s %19s %4095s",
01470                          &lsec, &act, &gRSAKey, &remid, host, usr, &shmid, subj, tkn, dumm);
01471                   if ((remid == RemId)
01472                       && !strcmp(host, Host) && !strcmp(subj, User)) {
01473                      goodOfs = 1;
01474                      goto found;
01475                   }
01476                } else {
01477                   if ((remid == RemId) &&
01478                       !strcmp(host, Host) && !strcmp(usr, User)) {
01479                      goodOfs = 1;
01480                      goto found;
01481                   }
01482                }
01483             }
01484          }
01485       }
01486    }
01487 
01488    found:
01489    // unlock the file
01490    lseek(itab, 0, SEEK_SET);
01491    if (lockf(itab, F_ULOCK, (off_t) 1) == -1) {
01492       ErrorInfo("RpcCheckOffSet: error unlocking %s",
01493                 gRpdAuthTab.c_str());
01494    }
01495    // closing file ...
01496    close(itab);
01497 
01498    // Read public key
01499    std::string pukfile = gRpdKeyRoot;
01500    pukfile.append(ItoA(*OffSet));
01501    if (gDebug > 2)
01502       ErrorInfo("RpdCheckOffSet: RSAKey ofs file: %d %d '%s' ",
01503                 gRSAKey, ofs, pukfile.c_str());
01504 
01505    struct passwd *pw = getpwnam(usr);
01506    if (pw) {
01507       uid_t fromUid = getuid();
01508       uid_t fromEUid = geteuid();
01509       // The check must be done with 'usr' UIDs to prevent
01510       // unauthorized users from forcing the server to read
01511       // manipulated key files.
01512       if (fromUid == 0)
01513          if (setresuid(pw->pw_uid, pw->pw_uid, fromEUid) == -1)
01514             // Since we could not set the user IDs, we will
01515             // not trust the client
01516             goodOfs = 0;
01517 
01518       // Get the key now
01519       if (goodOfs)
01520          if (RpdGetRSAKeys(pukfile.c_str(), 1) < 1)
01521             goodOfs = 0;
01522 
01523       // Reset original IDs
01524       if (getuid() != fromUid)
01525          setresuid(fromUid,fromEUid,pw->pw_uid);
01526 
01527    } else {
01528       // Since we could not set the user IDs, we will
01529       // not trust the client
01530       goodOfs = 0;
01531       if (gDebug > 0)
01532          ErrorInfo("RpdCheckOffSet: error in getpwname(%s) (errno: %d)",
01533                    usr,GetErrno());
01534    }
01535 
01536    if (gDebug > 2)
01537       ErrorInfo("RpdCheckOffSet: goodOfs: %d (active: %d)",
01538                 goodOfs, act);
01539 
01540    // Comunicate new offset to remote client
01541    if (goodOfs) {
01542 
01543       // Rename the key file, if needed
01544       if (*OffSet > 0 && *OffSet != ofs) {
01545          if (RpdRenameKeyFile(*OffSet,ofs) > 0) {
01546             goodOfs = 0;
01547             // Error: set entry inactive
01548             RpdCleanupAuthTab(Host,RemId,ofs);
01549          }
01550       }
01551 
01552       *OffSet = ofs;
01553       // return token if requested
01554       if (Token) {
01555          *Token = new char[strlen(tkn)+1];
01556          strlcpy(*Token,tkn,strlen(tkn)+1);
01557       }
01558       if (Sec == 3) {
01559          if (GlbsUser) {
01560             *GlbsUser = new char[strlen(usr)+1];
01561             strlcpy(*GlbsUser,usr,strlen(usr)+1);
01562          }
01563          if (ShmId)
01564             *ShmId = shmid;
01565       }
01566    }
01567 
01568    return goodOfs;
01569 }
01570 
01571 //______________________________________________________________________________
01572 int RpdRenameKeyFile(int oldofs, int newofs)
01573 {
01574    // Rename public file with new offset
01575    // Returns: 0 if OK
01576    //          1 if problems renaming
01577    int retval = 0;
01578 
01579    // Old name
01580    std::string oldname = gRpdKeyRoot;
01581    oldname.append(ItoA(oldofs));
01582    // New name
01583    std::string newname = gRpdKeyRoot;
01584    newname.append(ItoA(newofs));
01585 
01586    if (rename(oldname.c_str(), newname.c_str()) == -1) {
01587       if (gDebug > 0)
01588          ErrorInfo("RpdRenameKeyFile: error renaming key file"
01589                    " %s to %s (errno: %d)",
01590                    oldname.c_str(),newname.c_str(),GetErrno());
01591       retval = 2;
01592    }
01593 
01594    return retval;
01595 }
01596 
01597 //______________________________________________________________________________
01598 bool RpdCheckToken(char *token, char *tknref)
01599 {
01600    // Check token validity.
01601 
01602    // Get rid of '\n'
01603    char *s = strchr(token, '\n');
01604    if (s)
01605       *s = 0;
01606    s = strchr(tknref, '\n');
01607    if (s)
01608       *s = 0;
01609 
01610 #ifndef R__NOCRYPT
01611    char *tkn_crypt = crypt(token, tknref);
01612    int tlen = 13;
01613 #else
01614    char *tkn_crypt = rpdcrypt(token,gRndmSalt.c_str());
01615    int tlen = 16;
01616 #endif
01617 
01618    if (gDebug > 2)
01619       ErrorInfo("RpdCheckToken: ref:'%s' crypt:'%s'", tknref, tkn_crypt);
01620 
01621    if (!strncmp(tkn_crypt, tknref, tlen))
01622       return 1;
01623    else
01624       return 0;
01625 }
01626 
01627 //______________________________________________________________________________
01628 int RpdReUseAuth(const char *sstr, int kind)
01629 {
01630    // Check the requiring subject has already authenticated during this session
01631    // and its 'ticket' is still valid.
01632    // Not implemented for SRP and Krb5 (yet).
01633 
01634    int lenU, offset, opt;
01635    gOffSet = -1;
01636    gExistingAuth = 0;
01637    int auth= 0;
01638 
01639    if (gDebug > 2)
01640       ErrorInfo("RpdReUseAuth: analyzing: %s, %d", sstr, kind);
01641 
01642    char user[64];
01643 
01644    // kClear
01645    if (kind == kROOTD_USER) {
01646       if (!(gReUseAllow & gAUTH_CLR_MSK)) {
01647          return 0;              // re-authentication required by administrator
01648       }
01649       gSec = 0;
01650       // Decode subject string
01651       sscanf(sstr, "%d %d %d %d %63s", &gRemPid, &offset, &opt, &lenU, user);
01652       user[lenU] = '\0';
01653       if ((gReUseRequired = (opt & kAUTH_REUSE_MSK))) {
01654          gOffSet = offset;
01655          if (gRemPid > 0 && gOffSet > -1) {
01656             auth =
01657                 RpdCheckAuthTab(gSec, user, gOpenHost.c_str(), gRemPid, &gOffSet);
01658          }
01659          if ((auth == 1) && (offset != gOffSet))
01660             auth = 2;
01661          // Fill gUser and free allocated memory
01662          strlcpy(gUser, user, sizeof(gUser));
01663       }
01664    }
01665    // kSRP
01666    if (kind == kROOTD_SRPUSER) {
01667       if (!(gReUseAllow & gAUTH_SRP_MSK)) {
01668          return 0;              // re-authentication required by administrator
01669       }
01670       gSec = 1;
01671       // Decode subject string
01672       sscanf(sstr, "%d %d %d %d %63s", &gRemPid, &offset, &opt, &lenU, user);
01673       user[lenU] = '\0';
01674       if ((gReUseRequired = (opt & kAUTH_REUSE_MSK))) {
01675          gOffSet = offset;
01676          if (gRemPid > 0 && gOffSet > -1) {
01677             auth =
01678                 RpdCheckAuthTab(gSec, user, gOpenHost.c_str(), gRemPid, &gOffSet);
01679          }
01680          if ((auth == 1) && (offset != gOffSet))
01681             auth = 2;
01682          // Fill gUser and free allocated memory
01683          strlcpy(gUser, user, sizeof(gUser));
01684       }
01685    }
01686    // kKrb5
01687    if (kind == kROOTD_KRB5) {
01688       if (!(gReUseAllow & gAUTH_KRB_MSK)) {
01689          return 0;              // re-authentication required by administrator
01690       }
01691       gSec = 2;
01692       // Decode subject string
01693       sscanf(sstr, "%d %d %d %d %63s", &gRemPid, &offset, &opt, &lenU, user);
01694       user[lenU] = '\0';
01695       if ((gReUseRequired = (opt & kAUTH_REUSE_MSK))) {
01696          gOffSet = offset;
01697          if (gRemPid > 0 && gOffSet > -1) {
01698             auth =
01699                 RpdCheckAuthTab(gSec, user, gOpenHost.c_str(), gRemPid, &gOffSet);
01700          }
01701          if ((auth == 1) && (offset != gOffSet))
01702             auth = 2;
01703          // Fill gUser and free allocated memory
01704          strlcpy(gUser, user, sizeof(gUser));
01705       }
01706    }
01707    // kGlobus
01708    if (kind == kROOTD_GLOBUS) {
01709       if (!(gReUseAllow & gAUTH_GLB_MSK)) {
01710          return 0;              //  re-authentication required by administrator
01711       }
01712       gSec = 3;
01713       // Decode subject string
01714       int lenS;
01715       sscanf(sstr, "%d %d %d %d %63s", &gRemPid, &offset, &opt, &lenS, user);
01716       user[lenS] = '\0';
01717       if ((gReUseRequired = (opt & kAUTH_REUSE_MSK))) {
01718          gOffSet = offset;
01719          if (gRemPid > 0 && gOffSet > -1) {
01720             auth =
01721                 RpdCheckAuthTab(gSec, user, gOpenHost.c_str(), gRemPid, &gOffSet);
01722          }
01723          if ((auth == 1) && (offset != gOffSet))
01724             auth = 2;
01725       }
01726    }
01727    // kSSH
01728    if (kind == kROOTD_SSH) {
01729       if (!(gReUseAllow & gAUTH_SSH_MSK)) {
01730          return 0;              //  re-authentication required by administrator
01731       }
01732       gSec = 4;
01733       // Decode subject string
01734       char pipe[kMAXPATHLEN];
01735       sscanf(sstr, "%d %d %d %4095s %d %63s", &gRemPid, &offset, &opt, pipe, &lenU, user);
01736       user[lenU] = '\0';
01737       if ((gReUseRequired = (opt & kAUTH_REUSE_MSK))) {
01738          gOffSet = offset;
01739          if (gRemPid > 0 && gOffSet > -1) {
01740             auth =
01741                 RpdCheckAuthTab(gSec, user, gOpenHost.c_str(), gRemPid, &gOffSet);
01742          }
01743          if ((auth == 1) && (offset != gOffSet))
01744             auth = 2;
01745          // Fill gUser and free allocated memory
01746          strlcpy(gUser, user, sizeof(gUser));
01747       }
01748    }
01749 
01750    // Flag if existing token has been re-used
01751    if (auth > 0)
01752       gExistingAuth = 1;
01753 
01754    // Return value
01755    return auth;
01756 }
01757 
01758 //______________________________________________________________________________
01759 int RpdCheckAuthAllow(int Sec, const char *Host)
01760 {
01761    // Check if required auth method is allowed for 'Host'.
01762    // If 'yes', returns 0, if 'no', returns 1, the number of allowed
01763    // methods in NumAllow, and the codes of the allowed methods (in order
01764    // of preference) in AllowMeth. Memory for AllowMeth must be allocated
01765    // outside. Directives read from (in decreasing order of priority):
01766    // $ROOTDAEMONRC, $HOME/.rootdaemonrc (privately startd daemons only)
01767    // or $ROOTETCDIR/system.rootdaemonrc.
01768 
01769    int retval = 1, found = 0;
01770 
01771 #ifdef R__GBLS
01772    if (Sec == 3 && !gHaveGlobus) {
01773       ErrorInfo("RpdCheckAuthAllow: meth: 3:"
01774                 " server does not have globus/GSI credentials");
01775       return 1;
01776    }
01777 #endif
01778 
01779    std::string theDaemonRc;
01780 
01781    // Check if a non-standard file has been requested
01782    if (getenv("ROOTDAEMONRC"))
01783       theDaemonRc = getenv("ROOTDAEMONRC");
01784 
01785    if (theDaemonRc.length() <= 0) {
01786       if (getuid()) {
01787          // Check if user has a private daemon access file ...
01788          struct passwd *pw = getpwuid(getuid());
01789          if (pw != 0) {
01790             theDaemonRc = std::string(pw->pw_dir).append("/");
01791             theDaemonRc.append(gDaemonRc);
01792          } else {
01793             if (getenv("ROOTETCDIR")) {
01794                theDaemonRc = std::string(getenv("ROOTETCDIR")).append("/system");
01795                theDaemonRc.append(gDaemonRc);
01796             } else
01797                theDaemonRc = std::string("/etc/root/system").append(gDaemonRc);
01798          }
01799       } else {
01800          // If running as super-user, check system file only
01801          if (getenv("ROOTETCDIR")) {
01802             theDaemonRc = std::string(getenv("ROOTETCDIR")).append("/system");
01803             theDaemonRc.append(gDaemonRc);
01804          } else
01805             theDaemonRc = std::string("/etc/root/system").append(gDaemonRc);
01806       }
01807    }
01808    if (gDebug > 2)
01809       ErrorInfo("RpdCheckAuthAllow: Checking file: %s for meth:%d"
01810                 " host:%s (gNumAllow: %d)",
01811                 theDaemonRc.c_str(), Sec, Host, gNumAllow);
01812 
01813    // Check if info already loaded (not first call ...)
01814    if (gMethInit == 1) {
01815 
01816       // Look for the method in the allowed list and flag this method
01817       // as tried, if found ...
01818       int newtry = 0, i;
01819       for (i = 0; i < gNumAllow; i++) {
01820          if (gTriedMeth[i] == 0 && gAllowMeth[i] == Sec) {
01821             newtry = 1;
01822             gTriedMeth[i] = 1;
01823             gNumLeft--;
01824          }
01825       }
01826       if (newtry == 0) {
01827          ErrorInfo
01828              ("RpdCheckAuthAllow: new auth method proposed by %s",
01829               " client not in the list or already attempted");
01830          return retval;
01831       }
01832       retval = 0;
01833 
01834    } else {
01835 
01836       // Open file
01837       FILE *ftab = fopen(theDaemonRc.c_str(), "r");
01838       if (ftab == 0) {
01839          if (GetErrno() == ENOENT)
01840             ErrorInfo("RpdCheckAuthAllow: file %s does not exist",
01841                       theDaemonRc.c_str());
01842          else
01843             ErrorInfo("RpdCheckAuthAllow: error opening %s (errno: %d)",
01844                       theDaemonRc.c_str(), GetErrno());
01845       }
01846       // Now read the entry
01847       char line[kMAXPATHLEN], host[kMAXPATHLEN], rest[kMAXPATHLEN],
01848           cmth[kMAXPATHLEN];
01849       int nmet = 0, mth[6] = { 0 };
01850 
01851       int cont = 0, jm = -1;
01852       while (ftab && fgets(line, sizeof(line), ftab)) {
01853          int i;
01854          if (line[0] == '#')
01855             continue;           // skip comment lines
01856          if (line[strlen(line) - 1] == '\n')
01857             line[strlen(line) - 1] = '\0';   // get rid of '\n', if any ...
01858          // Analyze the line now ...
01859          int nw = 0;
01860          char *pstr = line;
01861          // Check if a continuation line
01862          if (cont == 1) {
01863             cont = 0;
01864             strlcpy(rest, pstr, kMAXPATHLEN); 
01865          } else {
01866             jm = -1;
01867             // Get 'host' first ...
01868             nw = sscanf(pstr, "%4095s %4095s", host, rest);
01869             if (nw < 2)
01870                continue;        // no method defined for this host
01871             pstr = line + strlen(host) + 1;
01872 
01873             // Check if a service is specified
01874             char *pcol = strstr(host, ":");
01875             if (pcol) {
01876                if (!strstr(pcol+1, gServName[gService].c_str()))
01877                   continue;
01878                else
01879                   host[(int)(pcol-host)] = '\0';
01880             }
01881             if (strlen(host) == 0)
01882                strlcpy(host, "default", kMAXPATHLEN);
01883 
01884             if (gDebug > 2)
01885                ErrorInfo("RpdCheckAuthAllow: found host: %s ", host);
01886 
01887             if (strcmp(host, "default")) {
01888                // now check validity of 'host' format
01889                if (!RpdCheckHost(Host,host)) {
01890                   goto next;
01891                }
01892             } else {
01893                // This is a default entry: ignore it if a host-specific entry was already
01894                // found, analyse it otherwise ...
01895                if (found == 1)
01896                   goto next;
01897             }
01898 
01899             // Reset mth[kMAXSEC]
01900             nmet = 0;
01901             for (i = 0; i < kMAXSEC; i++) {
01902                mth[i] = -1;
01903             }
01904 
01905          }
01906 
01907          // We are at the end and there will be a continuation line ...
01908          if (rest[0] == '\\') {
01909             cont = 1;
01910             continue;
01911          }
01912 
01913          while (pstr != 0) {
01914             int tmet = -1;
01915             char *pd = 0, *pd2 = 0;
01916             cmth[0] = '\0';
01917             rest[0] = '\0';
01918             nw = sscanf(pstr, "%4095s %4095s", cmth, rest);
01919             if (!strcmp(cmth, "none")) {
01920                nmet = 0;
01921                goto nexti;
01922             }
01923             pd = strchr(cmth, ':');
01924             // Parse the method
01925             char tmp[20];
01926             if (pd != 0) {
01927                int mlen = pd - cmth;
01928                strncpy(tmp, cmth, mlen);
01929                tmp[mlen] = '\0';
01930             } else {
01931                strlcpy(tmp, cmth, sizeof(tmp));
01932             }
01933 
01934             if (strlen(tmp) > 1) {
01935 
01936                for (tmet = 0; tmet < kMAXSEC; tmet++) {
01937                   if (!rpdstrcasecmp(gAuthMeth[tmet].c_str(), tmp))
01938                      break;
01939                }
01940                if (tmet < kMAXSEC) {
01941                   if (gDebug > 2)
01942                      ErrorInfo("RpdCheckAuthAllow: tmet %d", tmet);
01943                } else {
01944                   if (gDebug > 1)
01945                      ErrorInfo("RpdCheckAuthAllow: unknown methods"
01946                                " %s - ignore", tmp);
01947                   goto nexti;
01948                }
01949 
01950             } else {
01951                tmet = atoi(tmp);
01952             }
01953             jm = -1;
01954             if (gDebug > 2)
01955                ErrorInfo("RpdCheckAuthAllow: found method %d (have?:%d)",
01956                          tmet, (tmet >= 0 && tmet < kMAXSEC) ? gHaveMeth[tmet] : 0);
01957             if (tmet >= 0 && tmet < kMAXSEC) {
01958                if (gHaveMeth[tmet] == 1) {
01959                   int ii;
01960                   for (ii = 0; ii < nmet; ii++) {
01961                      if (mth[ii] == tmet) {
01962                         jm = ii;
01963                      }
01964                   }
01965                } else
01966                   goto nexti;
01967             } else
01968                goto nexti;
01969             if (jm == -1) {
01970                // New method ...
01971                mth[nmet] = tmet;
01972                jm = nmet;
01973                nmet++;
01974             }
01975             // Now parse users list, if any ...
01976             while (pd != 0 && (int) (pd[1]) != 32) {
01977                pd2 = strchr(pd + 1, ':');
01978                if (pd[1] == '-') {
01979                   pd += 2;
01980                   // Ignore
01981                   if (gUserIgnore[mth[jm]] == 0) {
01982                      gUserIgnLen[mth[jm]] = kMAXPATHLEN;
01983                      gUserIgnore[mth[jm]] = new char[gUserIgnLen[mth[jm]]];
01984                      gUserIgnore[mth[jm]][0] = '\0';
01985                   }
01986                   if (strlen(gUserIgnore[mth[jm]]) >
01987                       (gUserIgnLen[mth[jm]] - 10)) {
01988                      char *tmpUI = strdup(gUserIgnore[mth[jm]]);
01989                      free(gUserIgnore[mth[jm]]);
01990                      gUserIgnLen[mth[jm]] += kMAXPATHLEN;
01991                      gUserIgnore[mth[jm]] = new char[gUserIgnLen[mth[jm]]];
01992                      strlcpy(gUserIgnore[mth[jm]], tmpUI, sizeof(gUserIgnLen[mth[jm]]));
01993                      free(tmpUI);
01994                   }
01995                   char usr[256];
01996                   if (pd2 != 0) {
01997                      int ulen = pd2 - pd;
01998                      strncpy(usr, pd, ulen);
01999                      usr[ulen] = '\0';
02000                   } else {
02001                      strlcpy(usr, pd, sizeof(usr));
02002                   }
02003                   struct passwd *pw = getpwnam(usr);
02004                   if (pw != 0)
02005                      SPrintf(gUserIgnore[mth[jm]], gUserIgnLen[mth[jm]], "%s %d",
02006                              gUserIgnore[mth[jm]], (int)pw->pw_uid);
02007                } else {
02008                   pd += 1;
02009                   if (pd[1] == '+')
02010                      pd += 1;
02011                   // Keep
02012                   if (gUserAllow[mth[jm]] == 0) {
02013                      gUserAlwLen[mth[jm]] = kMAXPATHLEN;
02014                      gUserAllow[mth[jm]] = new char[gUserAlwLen[mth[jm]]];
02015                      gUserAllow[mth[jm]][0] = '\0';
02016                   }
02017                   if (strlen(gUserAllow[mth[jm]]) >
02018                       (gUserAlwLen[mth[jm]] - 10)) {
02019                      char *tmpUI = strdup(gUserAllow[mth[jm]]);
02020                      free(gUserAllow[mth[jm]]);
02021                      gUserAlwLen[mth[jm]] += kMAXPATHLEN;
02022                      gUserAllow[mth[jm]] = new char[gUserAlwLen[mth[jm]]];
02023                      strlcpy(gUserAllow[mth[jm]], tmpUI, sizeof(gUserAlwLen[mth[jm]]));
02024                      free(tmpUI);
02025                   }
02026                   char usr[256];
02027                   if (pd2 != 0) {
02028                      int ulen = pd2 - pd;
02029                      strncpy(usr, pd, ulen);
02030                      usr[ulen] = '\0';
02031                   } else {
02032                      strlcpy(usr, pd, sizeof(usr));
02033                   }
02034                   struct passwd *pw = getpwnam(usr);
02035                   if (pw != 0)
02036                      SPrintf(gUserAllow[mth[jm]], gUserIgnLen[mth[jm]], "%s %d",
02037                              gUserAllow[mth[jm]], (int)pw->pw_uid);
02038                }
02039                pd = pd2;
02040             }
02041             // Get next item
02042             nexti:
02043             if (nw > 1 && (int) rest[0] != 92) {
02044                pstr = strstr(pstr, rest);
02045             } else {
02046                if ((int) rest[0] == 92)
02047                   cont = 1;
02048                pstr = 0;
02049             }
02050          }
02051          if (gDebug > 2) {
02052             ErrorInfo("RpdCheckAuthAllow: for host %s found %d methods",
02053                       host, nmet);
02054             ErrorInfo("RpdCheckAuthAllow: %d %d %d %d %d %d", mth[0],
02055                       mth[1], mth[2], mth[3], mth[4], mth[5]);
02056          }
02057          // Found new entry matching: superseed previous result
02058          found = 1;
02059          retval = 1;
02060          gNumAllow = gNumLeft = nmet;
02061          for (i = 0; i < kMAXSEC; i++) {
02062             gAllowMeth[i] = -1;
02063             gTriedMeth[i] = 0;
02064             if (i < gNumAllow) {
02065                gAllowMeth[i] = mth[i];
02066                if (Sec == mth[i]) {
02067                   retval = 0;
02068                   gNumLeft--;
02069                   gTriedMeth[i] = 1;
02070                }
02071             }
02072          }
02073          next:
02074          continue;
02075       }
02076 
02077       // closing file ...
02078       if (ftab)
02079          fclose(ftab);
02080 
02081       // Host specific directives have been checked for ...
02082       gMethInit = 1;
02083 
02084       // Use defaults if nothing found
02085       if (!found) {
02086          if (gDebug > 2)
02087             ErrorInfo
02088             ("RpdCheckAuthAllow: no specific or 'default' entry found: %s",
02089              "using system defaults");
02090          int i;
02091          for (i = 0; i < gNumAllow; i++) {
02092             if (Sec == gAllowMeth[i]) {
02093                retval = 0;
02094                gNumLeft--;
02095                gTriedMeth[i] = 1;
02096             }
02097          }
02098 
02099       }
02100 
02101    }
02102    if (gDebug > 2) {
02103       ErrorInfo
02104           ("RpdCheckAuthAllow: returning: %d (gNumAllow: %d, gNumLeft:%d)",
02105            retval, gNumAllow, gNumLeft);
02106       int i, jm;
02107       for (i = 0; i < kMAXSEC; i++) {
02108          jm = gAllowMeth[i];
02109          if (gUserAlwLen[jm] > 0)
02110             ErrorInfo("RpdCheckAuthAllow: users allowed for method %d: %s",
02111                       jm, gUserAllow[jm]);
02112       }
02113       for (i = 0; i < kMAXSEC; i++) {
02114          jm = gAllowMeth[i];
02115          if (gUserIgnLen[jm] > 0)
02116             ErrorInfo("RpdCheckAuthAllow: users ignored for method %d: %s",
02117                       jm, gUserIgnore[jm]);
02118       }
02119    }
02120 
02121    return retval;
02122 }
02123 
02124 //______________________________________________________________________________
02125 int RpdCheckHost(const char *Host, const char *host)
02126 {
02127    // Checks if 'host' is compatible with 'Host' taking into account
02128    // wild cards in the host name
02129    // Returns 1 if successful, 0 otherwise ...
02130 
02131    int rc = 1;
02132 
02133    // Strings must be both defined
02134    if (!Host || !host)
02135       return 0;
02136 
02137    // If host is a just wild card accept it
02138    if (!strcmp(host,"*"))
02139       return 1;
02140 
02141    // Try now to understand whether it is an address or a name ...
02142    int name = 0, i = 0;
02143    for (i = 0; i < (int) strlen(host); i++) {
02144       if ((host[i] < 48 || host[i] > 57) &&
02145            host[i] != '*' && host[i] != '.') {
02146          name = 1;
02147          break;
02148       }
02149    }
02150 
02151    // If ref host is an IP, get IP of Host
02152    char *hh;
02153    if (!name) {
02154       hh = RpdGetIP(Host);
02155       if (gDebug > 2)
02156          ErrorInfo("RpdCheckHost: Checking Host IP: %s", hh);
02157    } else {
02158       hh = new char[strlen(Host)+1];
02159       strlcpy(hh,Host,strlen(Host)+1);
02160       if (gDebug > 2)
02161          ErrorInfo("RpdCheckHost: Checking Host name: %s", hh);
02162    }
02163 
02164    // Check if starts with wild
02165    // Starting with '.' defines a full (sub)domain
02166    int sos = 0;
02167    if (host[0] == '*' || host[0] == '.')
02168       sos = 1;
02169 
02170    // Check if ends with wild
02171    // Ending with '.' defines a name
02172    int eos = 0, le = strlen(host);
02173    if (host[le-1] == '*' || host[le-1] == '.')
02174       eos = 1;
02175 
02176    int first= 1;
02177    int ends= 0;
02178    int starts= 0;
02179    char *h = new char[strlen(host)+1];
02180    strlcpy(h,host,strlen(host)+1);
02181    char *tk = strtok(h,"*");
02182    while (tk) {
02183 
02184       char *ps = strstr(hh,tk);
02185       if (!ps) {
02186          rc = 0;
02187          break;
02188       }
02189       if (!sos && first && ps == hh)
02190          starts = 1;
02191       first = 0;
02192 
02193       if (ps == hh + strlen(hh) - strlen(tk))
02194          ends = 1;
02195 
02196       tk = strtok(0,"*");
02197 
02198    }
02199    delete[] h;
02200    delete[] hh;
02201 
02202    if ((!sos || !eos) && !starts && !ends)
02203       rc = 0;
02204 
02205    return rc;
02206 }
02207 
02208 //______________________________________________________________________________
02209 char *RpdGetIP(const char *host)
02210 {
02211    // Get IP address of 'host' as a string. String must be deleted by
02212    // the user.
02213 
02214    struct hostent *h;
02215    unsigned long ip;
02216    unsigned char ip_fld[4];
02217 
02218    // Check server name
02219    if ((h = gethostbyname(host)) == 0) {
02220       ErrorInfo("RpdGetIP: unknown host %s", host);
02221       return 0;
02222    }
02223    // Decode ...
02224    ip = ntohl(*(unsigned long *) h->h_addr_list[0]);
02225    ip_fld[0] = (unsigned char) ((0xFF000000 & ip) >> 24);
02226    ip_fld[1] = (unsigned char) ((0x00FF0000 & ip) >> 16);
02227    ip_fld[2] = (unsigned char) ((0x0000FF00 & ip) >> 8);
02228    ip_fld[3] = (unsigned char) ((0x000000FF & ip));
02229 
02230    // Prepare output
02231    char *output = new char[20];
02232    SPrintf(output, 20, "%d.%d.%d.%d",
02233            ip_fld[0], ip_fld[1], ip_fld[2], ip_fld[3]);
02234 
02235    // return
02236    return output;
02237 }
02238 
02239 //______________________________________________________________________________
02240 void RpdSendAuthList()
02241 {
02242    // Send list of authentication methods not yet tried.
02243 
02244    if (gDebug > 2)
02245       ErrorInfo("RpdSendAuthList: analyzing (gNumLeft: %d)", gNumLeft);
02246 
02247    // Send Number of methods left
02248    NetSend(gNumLeft, kROOTD_NEGOTIA);
02249 
02250    if (gNumLeft > 0) {
02251       int i = 0;
02252       std::string alist;
02253       char cm[5];
02254       for (i = 0; i < gNumAllow; i++) {
02255          if (gDebug > 2)
02256             ErrorInfo("RpdSendAuthList: gTriedMeth[%d]: %d", i,
02257                       gTriedMeth[i]);
02258          if (gTriedMeth[i] == 0) {
02259             SPrintf(cm, 5, " %d",gAllowMeth[i]);
02260             alist.append(cm);
02261          }
02262       }
02263       NetSend(alist.c_str(), alist.length() + 1, kMESS_STRING);
02264       if (gDebug > 2)
02265          ErrorInfo("RpdSendAuthList: sent list: %s", alist.c_str());
02266    }
02267 }
02268 
02269 //______________________________________________________________________________
02270 int RpdSshAuth(const char *sstr)
02271 {
02272    // Authenitcation via ssh.
02273 
02274    int auth = 0;
02275 
02276    if (gDebug > 2)
02277       ErrorInfo("RpdSshAuth: contacted by host: %s for user %s",
02278                 gOpenHost.c_str(),sstr);
02279 
02280    // Decode subject string
02281    char user[kMAXUSERLEN];
02282    char pipeId[10] = {0};
02283    int lenU, ofs, opt;
02284    char rproto[20] = {0};
02285    sscanf(sstr, "%d %d %d %9s %d %127s %19s", &gRemPid, &ofs, &opt, pipeId, &lenU, user, rproto);
02286    
02287    user[lenU] = '\0';
02288    gReUseRequired = (opt & kAUTH_REUSE_MSK);
02289 #if R__SSL
02290    if (gRSASSLKey) {
02291       // Determine type of RSA key required
02292       gRSAKey = (opt & kAUTH_RSATY_MSK) ? 2 : 1;
02293    } else
02294       gRSAKey = 1;
02295 #else
02296    gRSAKey = 1;
02297 #endif
02298 
02299    // Check if we have been called to notify failure ...
02300    if (gRemPid < 0) {
02301 
02302       if (gDebug > 2)
02303          ErrorInfo
02304              ("RpdSshAuth: this is a failure notification (%s,%s,%d,%s)",
02305               user, gOpenHost.c_str(), gRemPid, pipeId);
02306 
02307       struct passwd *pw = getpwnam(user);
02308       if (pw) {
02309          std::string pipeFile =
02310             std::string(pw->pw_dir) + std::string("/RootSshPipe.") + pipeId;
02311          FILE *fpipe = fopen(pipeFile.c_str(), "r");
02312          if (!fpipe) {
02313             pipeFile= gTmpDir + std::string("/RootSshPipe.") + pipeId;
02314             fpipe = fopen(pipeFile.c_str(), "r");
02315          } 
02316          char pipe[kMAXPATHLEN];
02317          if (fpipe) {
02318             while (fgets(pipe, sizeof(pipe), fpipe)) {
02319                if (pipe[strlen(pipe)-1] == '\n')
02320                pipe[strlen(pipe)-1] = 0;
02321             }
02322             fclose(fpipe);
02323             // Remove the temporary file
02324             unlink(pipeFile.c_str());
02325 
02326             if (SshToolNotifyFailure(pipe))
02327                ErrorInfo("RpdSshAuth: failure notification may have"
02328                          " failed ");
02329          } else {
02330             if (GetErrno() == ENOENT)
02331                ErrorInfo("RpdSshAuth: pipe file %s does not exists",
02332                           pipeFile.c_str());
02333             else
02334                ErrorInfo("RpdSshAuth: cannot open pipe file %s"
02335                       " (errno= %d)",pipeFile.c_str(),GetErrno());
02336          }
02337 
02338       } else
02339          ErrorInfo("RpdSshAuth: unable to get user info for '%s'"
02340                    " (errno: %d)",user,GetErrno());
02341 
02342       gClientProtocol = atoi(rproto);
02343 
02344       // Improved diagnostics, check if there is something listening on
02345       // port gSshdPort
02346       char buf[20] = {0};
02347 #if defined(linux)
02348       if (!RpdCheckSshd(0)) {
02349          // Nothing found by netstat ... try opening a socket
02350          if (!RpdCheckSshd(1)) {
02351             if (gDebug > 2)
02352                ErrorInfo("RpdSshAuth: sshd not found - return");
02353             if (gClientProtocol > 9) {
02354                SPrintf(buf, 20, "%d",gSshdPort);
02355                NetSend(strlen(buf), kROOTD_SSH);
02356                NetSend(buf, strlen(buf), kMESS_STRING);
02357             }
02358             return auth;
02359          }
02360       }
02361 #else
02362       if (!RpdCheckSshd(1)) {
02363          if (gDebug > 2)
02364             ErrorInfo("RpdSshAuth: sshd not found - return");
02365          if (gClientProtocol > 9) {
02366             SPrintf(buf, 20,"%d",gSshdPort);
02367             NetSend(strlen(buf), kROOTD_SSH);
02368             NetSend(buf, strlen(buf), kMESS_STRING);
02369          }
02370          return auth;
02371       }
02372 #endif
02373       if (gClientProtocol > 9) {
02374          SPrintf(buf,20,"OK");
02375          NetSend(strlen(buf), kROOTD_SSH);
02376          NetSend(buf, strlen(buf), kMESS_STRING);
02377          ErrorInfo("RpdSshAuth: failure notified");
02378       } else {
02379          NetSend(kErrAuthNotOK,kROOTD_ERR);
02380          ErrorInfo("RpdSshAuth: failure notified");
02381       }
02382       return auth;
02383    }
02384 
02385    // Protocol of our ssh implementation
02386    int sshproto = atoi(rproto);
02387 
02388    // Check user existence and get its environment
02389    struct passwd *pw = getpwnam(user);
02390    if (!pw) {
02391       ErrorInfo("RpdSshAuth: entry for user % not found in /etc/passwd",
02392                 user);
02393       NetSend(-2, kROOTD_SSH);
02394       return auth;
02395    }
02396    // Method cannot be attempted for anonymous users ... (ie data servers )...
02397    if (!strcmp(pw->pw_shell, "/bin/false")) {
02398       ErrorInfo("RpdSshAuth: no SSH for anonymous user '%s' ", user);
02399       NetSend(-2, kROOTD_SSH);
02400       return auth;
02401    }
02402 
02403    // Some useful variables
02404    char *pipeFile = 0;
02405    char *authFile = 0;
02406    char *uniquePipe = 0;
02407    std::string cmdInfo = "";
02408    int unixFd = -1;
02409    struct stat st0, st1;
02410 
02411    if (sshproto == 0) {
02412 
02413       // Now we create an internal (UNIX) socket to listen to the
02414       // result of sshd from ssh2rpd.
02415       // Path will be /tmp/rootdSSH_<random_string>
02416       if ((unixFd =
02417            SshToolAllocateSocket(pw->pw_uid, pw->pw_gid, &uniquePipe)) < 0) {
02418          ErrorInfo
02419              ("RpdSshAuth: can't allocate UNIX socket for authentication");
02420          NetSend(0, kROOTD_SSH);
02421          delete[] uniquePipe;
02422          return auth;
02423       }
02424 
02425       // Open a file to put the pipe to be read by ssh2rpd
02426       int itmp = 0;
02427       pipeFile = new char[strlen(pw->pw_dir) + 25];
02428       SPrintf(pipeFile, strlen(pw->pw_dir) + 25, "%s/RootSshPipe.XXXXXX", pw->pw_dir);
02429       mode_t oldumask = umask(0700);
02430       int ipipe = mkstemp(pipeFile);
02431       if (ipipe == -1) {
02432          delete[] pipeFile;
02433          pipeFile = new char[gTmpDir.length() + 25];
02434          SPrintf(pipeFile, gTmpDir.length() + 25, "%s/RootSshPipe.XXXXXX", gTmpDir.c_str());
02435          ipipe = mkstemp(pipeFile);
02436          itmp = 1;
02437       }
02438       umask(oldumask);
02439       FILE *fpipe = 0;
02440       if (ipipe == -1 || !(fpipe = fdopen(ipipe,"w")) ) {
02441          ErrorInfo("RpdSshAuth: failure creating pipe file %s (errno: %d)",
02442                     pipeFile,GetErrno());
02443          // Could not open the file: notify failure and close
02444          // properly everything
02445          if (SshToolNotifyFailure(uniquePipe))
02446             ErrorInfo("RpdSshAuth: failure notification perhaps"
02447                       " unsuccessful ... ");
02448          NetSend(kErrNoPipeInfo, kROOTD_ERR);
02449          delete[] uniquePipe;
02450          delete[] pipeFile;
02451          return auth;
02452       } else {
02453          // File open: fill it
02454          fprintf(fpipe,"%s\n",uniquePipe);
02455          fclose(fpipe);
02456          // Set strict protections
02457          chmod(pipeFile, 0600);
02458          // Set ownership of the pipe file to the user
02459          if (getuid() == 0)
02460             if (chown(pipeFile,pw->pw_uid,pw->pw_gid) == -1)
02461                ErrorInfo("RpdSshAuth: cannot change ownership of %s (errno: %d)",
02462                          pipeFile,GetErrno());
02463       }
02464 
02465       // Get ID
02466       char *pId = (char *)strstr(pipeFile,"SshPipe.")+strlen("SshPipe.");
02467       strlcpy(pipeId, pId, sizeof(pipeId));
02468 
02469       // Communicate command to be executed via ssh ...
02470       std::string rootbindir;
02471       if (getenv("ROOTBINDIR"))
02472          rootbindir = getenv("ROOTBINDIR");
02473       char dbgstr[4] = {0};
02474       snprintf(dbgstr,3,"%d ",gDebug);
02475       cmdInfo = std::string(rootbindir).append("/ssh2rpd ");
02476       cmdInfo.append(dbgstr);
02477       cmdInfo.append(" ");
02478       cmdInfo.append(pipeId);
02479 
02480       // Add Tmp dir, if used
02481       if (itmp) {
02482          cmdInfo.append(" ");
02483          cmdInfo.append(gTmpDir);
02484       }
02485 
02486    } else {
02487       // New protocol using scp
02488       // Allocate a file to be overwritten by the client
02489       authFile = new char[strlen(pw->pw_dir) + 25];
02490       SPrintf(authFile, strlen(pw->pw_dir) + 25, "%s/RootSshAuth.XXXXXX", pw->pw_dir);
02491       mode_t oldumask = umask(0700);
02492       int iauth = mkstemp(authFile);
02493       if (iauth == -1) {
02494          if (gDebug > 2)
02495             ErrorInfo("RpdSshAuth: failure creating Auth file %s (errno: %d)",
02496                       authFile,GetErrno());
02497          delete[] authFile;
02498          authFile = new char[gTmpDir.length() + 25];
02499          SPrintf(authFile, gTmpDir.length() + 25, "%s/RootSshAuth.XXXXXX", gTmpDir.c_str());
02500          if ((iauth = mkstemp(authFile)) == -1) {
02501             ErrorInfo("RpdSshAuth: failure creating Auth file %s (errno: %d)",
02502                       authFile,GetErrno());
02503             NetSend(kErrFileOpen, kROOTD_ERR);
02504             delete[] authFile;
02505             umask(oldumask);
02506             return auth;
02507          }
02508       }
02509       umask(oldumask);
02510 
02511       // Store stat result to check changes
02512       if (fstat(iauth, &st0) == -1)
02513          ErrorInfo("RpdSshAuth: cannot stat %s",authFile);
02514 
02515       // Make sure the permissions are the rigth ones
02516       if (fchmod(iauth,0600)) {
02517          if (gDebug > 0) {
02518             ErrorInfo("RpdSshAuth: chmod: could not change"
02519                       " '%s' permission (errno= %d)",authFile, errno);
02520             ErrorInfo("RpdSshAuth: path (uid,gid) are: %d %d",
02521                       st0.st_uid, st0.st_gid);
02522             NetSend(kErrNoChangePermission, kROOTD_ERR);
02523             delete[] authFile;
02524             return auth;
02525          }
02526       }
02527 
02528       if ((unsigned int)st0.st_uid != pw->pw_uid ||
02529           (unsigned int)st0.st_gid != pw->pw_gid) {
02530          if (fchown(iauth, pw->pw_uid, pw->pw_gid)) {
02531             if (gDebug > 0) {
02532                ErrorInfo("RpdSshAuth: chown: could not change file"
02533                          " '%s' ownership (errno= %d)",authFile, errno);
02534                ErrorInfo("RpdSshAuth: path (uid,gid) are: %d %d",
02535                          st0.st_uid, st0.st_gid);
02536                ErrorInfo("RpdSshAuth: may follow authentication problems");
02537             }
02538          }
02539       }
02540 
02541       // Reset reference time
02542       if (fstat(iauth, &st0) == -1)
02543          ErrorInfo("RpdSshAuth: cannot stat %s",authFile);
02544 
02545       // Send Back the name of the file
02546       if (gClientProtocol > 13) {
02547          // Add the full coordinates, so that it works in all cases,
02548          // included SSH tunnelling ...
02549          char hostname[64];
02550          gethostname(hostname, sizeof(hostname));
02551          char *cmd = new char[strlen(authFile) + strlen(user) + strlen(hostname) + 5];
02552          SPrintf(cmd, strlen(authFile) + strlen(user) + strlen(hostname) + 5,
02553                       " %s@%s:%s ", user, hostname, authFile);
02554          cmdInfo.append(cmd);
02555          delete[] cmd;
02556       } else {
02557          cmdInfo = std::string(authFile);
02558       }
02559    }
02560 
02561    // Add non-standard port, if so
02562    if (gSshdPort != 22) {
02563       char sshp[10];
02564       snprintf(sshp,10," p:%d",gSshdPort);
02565       cmdInfo.append(sshp);
02566    }
02567 
02568    // Add key type, if SSL
02569    if (gRSAKey == 2) {
02570       char key[10];
02571       snprintf(key,10," k:%d",gRSAKey);
02572       cmdInfo.append(key);
02573    }
02574 
02575    if (gDebug > 2)
02576       ErrorInfo("RpdSshAuth: sending cmdInfo (%d) %s", cmdInfo.length(),
02577                 cmdInfo.c_str());
02578    NetSend(cmdInfo.length(), kROOTD_SSH);
02579    NetSend(cmdInfo.c_str(), cmdInfo.length(), kROOTD_SSH);
02580 
02581    if (sshproto == 0) {
02582 
02583       // Old protocol:
02584       // Wait for verdict from sshd (via ssh2rpd ...)
02585       // Additional check on the username ...
02586       auth = SshToolGetAuth(unixFd, user);
02587 
02588       // Close socket
02589       SshToolDiscardSocket(uniquePipe, unixFd);
02590 
02591    } else {
02592 
02593       auth = 0;
02594 
02595       // New Protocol:
02596       // Get result from client and check it locally
02597       EMessageTypes kind;
02598       char res[5];
02599       NetRecv(res, 5, kind);
02600       if (kind != kROOTD_SSH) {
02601          ErrorInfo("RpdSshAuth: expecting message kind: %d"
02602                       " - received: %d", (int)kROOTD_SSH, kind);
02603          if (!strncmp(res,"1",1))
02604             NetSend(kErrBadOp, kROOTD_ERR);
02605          if (unlink(authFile) == -1)
02606             if (GetErrno() != ENOENT)
02607                ErrorInfo("RpdSshAuth: cannot unlink file %s (errno: %d)",
02608                          authFile,GetErrno());
02609          delete[] authFile;
02610          // Set to Auth failed
02611          auth = 0;
02612          return auth;
02613       }
02614       if (!strncmp(res,"0",1)) {
02615          // Failure
02616          if (unlink(authFile) == -1)
02617             if (GetErrno() != ENOENT)
02618                ErrorInfo("RpdSshAuth: cannot unlink file %s (errno: %d)",
02619                          authFile,GetErrno());
02620          delete[] authFile;
02621          // Set to Auth failed
02622          auth = 0;
02623          return auth;
02624       }
02625       if (!strncmp(res,"1",1)) {
02626          // Client pretends success: lets check it locally
02627          FILE *floc = fopen(authFile,"r");
02628          if (!floc) {
02629             ErrorInfo("RpdSshAuth: cannot open auth file:"
02630                       " %s (errno: %d)", authFile, GetErrno());
02631             NetSend(kErrFileOpen, kROOTD_ERR);
02632             if (unlink(authFile) == -1)
02633                if (GetErrno() != ENOENT)
02634                   ErrorInfo("RpdSshAuth: cannot unlink file %s (errno: %d)",
02635                             authFile,GetErrno());
02636             delete[] authFile;
02637             // Set to Auth failed
02638             auth = 0;
02639             return auth;
02640          }
02641          // Stat again file to check for modification
02642          if (fstat(fileno(floc), &st1) == -1) {
02643             ErrorInfo("RpdSshAuth: cannot fstat descriptor %d", fileno(floc));
02644             fclose(floc);
02645             delete[] authFile;
02646             // Set to Auth failed
02647             auth = 0;
02648             return auth;
02649          }
02650 
02651          char line[kMAXPATHLEN];
02652          while (fgets(line, sizeof(line), floc) != 0) {
02653             // Get rid of '\n'
02654             if (line[strlen(line) - 1] == '\n')
02655                line[strlen(line) - 1] = '\0';
02656             if (gDebug > 2)
02657                ErrorInfo("RpdSshAuth: read line ... '%s'", line);
02658             if (!strncmp(line,"k:",2)) {
02659                // The file contains some meaningful info ...
02660                auth = 1;
02661                // Get the key, if there
02662                char key[4], val[10];
02663                int nw = sscanf(line,"%3s %9s",key,val);
02664                if (nw >= 2 && strncmp(val,"-1",2)) {
02665                   gPubKeyLen = fread((void *)gPubKey,1,sizeof(gPubKey),floc);
02666                   // Import Key and Determine key type
02667                   gRSAKey = RpdGetRSAKeys(gPubKey, 0);
02668                   if (gRSAKey == 0) {
02669                      ErrorInfo("RpdSshAuth: could not import a valid key");
02670                      gReUseRequired = 0;
02671                   }
02672                }
02673             }
02674          }
02675          fclose(floc);
02676 
02677          // If the file is still empty or scrappy return
02678          if (auth == 0) {
02679             // Send error only if the client really got in
02680             // otherwise it already quit, and sending error
02681             // would screw up negotiation
02682             if (gDebug > 2)
02683                ErrorInfo("RpdSshAuth: %d %d",st1.st_ctime,st0.st_ctime);
02684             if (st1.st_ctime != st0.st_ctime)
02685                // the file has been overwritten: the client got in
02686                // but something went wrong
02687                NetSend(kErrAuthNotOK, kROOTD_ERR);
02688             if (unlink(authFile) == -1)
02689                if (GetErrno() != ENOENT)
02690                   ErrorInfo("RpdSshAuth: cannot unlink file %s (errno: %d)",
02691                             authFile, GetErrno());
02692             delete[] authFile;
02693             return auth;
02694          }
02695       } else {
02696          ErrorInfo("RpdSshAuth: got unknown reply: %s", res);
02697          NetSend(kErrBadMess, kROOTD_ERR);
02698          if (unlink(authFile) == -1)
02699             if (GetErrno() != ENOENT)
02700                ErrorInfo("RpdSshAuth: cannot unlink file %s (errno: %d)",
02701                          authFile,GetErrno());
02702          delete[] authFile;
02703          // Set to Auth failed
02704          auth = 0;
02705          return auth;
02706       }
02707       // Remove the file
02708       if (unlink(authFile) == -1)
02709          if (GetErrno() != ENOENT)
02710             ErrorInfo("RpdSshAuth: cannot unlink file %s (errno: %d)",
02711                       authFile,GetErrno());
02712    }
02713 
02714    // If failure, notify and return ...
02715    if (auth <= 0) {
02716       if (auth == -1)
02717          NetSend(kErrWrongUser, kROOTD_ERR);  // Send message length first
02718       else
02719          NetSend(kErrAuthNotOK, kROOTD_ERR);  // Send message length first
02720       delete[] uniquePipe;
02721       delete[] pipeFile;
02722       // Set to Auth failed
02723       auth = 0;
02724       return auth;
02725    }
02726    // notify the client
02727    if (gDebug > 0 && auth == 1)
02728       ErrorInfo("RpdSshAuth: user %s authenticated by sshd", user);
02729    gSec = 4;
02730 
02731    // Save username ...
02732    strlcpy(gUser, user, sizeof(gUser));
02733 
02734    char line[kMAXPATHLEN];
02735    if ((gReUseAllow & gAUTH_SSH_MSK) && gReUseRequired) {
02736 
02737       if (sshproto == 0) {
02738 
02739          // Ask for the RSA key
02740          NetSend(gRSAKey, kROOTD_RSAKEY);
02741 
02742          // Receive the key securely
02743          if (RpdRecvClientRSAKey()) {
02744             ErrorInfo("RpdSshAuth: could not import a valid key"
02745                       " - switch off reuse for this session");
02746             gReUseRequired = 0;
02747          }
02748       }
02749 
02750       // Set an entry in the auth tab file for later (re)use, if required ...
02751       int offset = -1;
02752       char *token = 0;
02753       if (gReUseRequired) {
02754          SPrintf(line, kMAXPATHLEN, "4 1 %d %d %s %s",
02755                  gRSAKey, gRemPid, gOpenHost.c_str(), gUser);
02756          offset = RpdUpdateAuthTab(1, line, &token);
02757       }
02758       // Comunicate login user name to client
02759       SPrintf(line, kMAXPATHLEN, "%s %d", gUser, offset);
02760       NetSend(strlen(line), kROOTD_SSH);   // Send message length first
02761       NetSend(line, kMESS_STRING);
02762 
02763       if (gReUseRequired && offset > -1) {
02764          // Send over the token
02765          if (!token || (token && RpdSecureSend(token) == -1)) {
02766             ErrorInfo
02767                 ("RpdSshAuth: problems secure-sending token"
02768                  " - may result in corrupted token");
02769          }
02770          if (token) delete[] token;
02771       }
02772       gOffSet = offset;
02773    } else {
02774       // Comunicate login user name to client
02775       SPrintf(line, kMAXPATHLEN, "%s -1", gUser);
02776       NetSend(strlen(line), kROOTD_SSH);   // Send message length first
02777       NetSend(line, kMESS_STRING);
02778    }
02779 
02780    // Release allocated memory
02781    delete[] uniquePipe;
02782    delete[] pipeFile;
02783    delete[] authFile;
02784 
02785    return auth;
02786 }
02787 
02788 //______________________________________________________________________________
02789 int RpdKrb5Auth(const char *sstr)
02790 {
02791    // Authenticate via Kerberos.
02792 
02793    int auth = 0;
02794 
02795 #ifdef R__KRB5
02796    NetSend(1, kROOTD_KRB5);
02797    // TAuthenticate will respond to our encouragement by sending krb5
02798    // authentication through the socket
02799 
02800    int retval;
02801 
02802    if (gDebug > 2)
02803       ErrorInfo("RpdKrb5Auth: analyzing ... %s", sstr);
02804 
02805    if (gClientProtocol > 8) {
02806       int lenU, ofs, opt;
02807       char dumm[256];
02808       // Decode subject string
02809       sscanf(sstr, "%d %d %d %d %255s", &gRemPid, &ofs, &opt, &lenU, dumm);
02810       gReUseRequired = (opt & kAUTH_REUSE_MSK);
02811 #if R__SSL
02812       if (gRSASSLKey) {
02813          // Determine type of RSA key required
02814          gRSAKey = (opt & kAUTH_RSATY_MSK) ? 2 : 1;
02815       } else
02816          gRSAKey = 1;
02817 #else
02818       gRSAKey = 1;
02819 #endif
02820    }
02821 
02822    // Init context
02823    retval = krb5_init_context(&gKcontext);
02824    if (retval) {
02825       ErrorInfo("RpdKrb5Auth: %s while initializing krb5",
02826             error_message(retval));
02827       return auth;
02828    }
02829 
02830    // Use special Keytab file, if specified
02831    if (gKeytabFile.length()) {
02832       if ((retval = krb5_kt_resolve(gKcontext, gKeytabFile.c_str(), &gKeytab)))
02833          ErrorInfo("RpdKrb5Auth: %s while resolving keytab file %s",
02834                         error_message(retval),gKeytabFile.c_str());
02835    }
02836 
02837    // get service principal
02838    const char *service = "host";
02839 
02840    if (gDebug > 2)
02841       ErrorInfo("RpdKrb5Auth: using service: %s ",service);
02842 
02843    krb5_principal server;
02844    if ((retval = krb5_sname_to_principal(gKcontext, 0, service,
02845                                          KRB5_NT_SRV_HST, &server))) {
02846       ErrorInfo("RpdKrb5Auth: while generating service name (%s): %d %s",
02847                 service, retval, error_message(retval));
02848       RpdFreeKrb5Vars(gKcontext, 0, 0, 0, 0);
02849       return auth;
02850    }
02851 
02852    // listen for authentication from the client
02853    krb5_auth_context auth_context = 0;
02854    krb5_ticket *ticket;
02855    char proto_version[100] = "krootd_v_1";
02856    int sock = NetGetSockFd();
02857 
02858    if (gDebug > 2)
02859       ErrorInfo("RpdKrb5Auth: recvauth ... ");
02860 
02861    if ((retval = krb5_recvauth(gKcontext, &auth_context,
02862                                (krb5_pointer) &sock, proto_version, server,
02863                                0, gKeytab,   // default gKeytab is 0
02864                                &ticket))) {
02865       ErrorInfo("RpdKrb5Auth: recvauth failed--%s", error_message(retval));
02866       RpdFreeKrb5Vars(gKcontext, server, 0, 0, 0);
02867       return auth;
02868    }
02869 
02870    // get client name
02871    char *cname;
02872    if ((retval =
02873         krb5_unparse_name(gKcontext, ticket->enc_part2->client, &cname))) {
02874       ErrorInfo("RpdKrb5Auth: unparse failed: %s", error_message(retval));
02875       RpdFreeKrb5Vars(gKcontext, server, ticket, auth_context, 0);
02876       return auth;
02877    }
02878    if (gDebug > 2)
02879          ErrorInfo("RpdKrb5Auth: name in ticket is: %s",cname);
02880 
02881    using std::string;
02882    std::string user = std::string(cname);
02883    free(cname);
02884    std::string reply = std::string("authenticated as ").append(user);
02885 
02886    // set user name
02887    // avoid using 'erase' (it is buggy with some compilers)
02888    snprintf(gUser,64,"%s",user.c_str());
02889    char *pc = 0;
02890    // cut off realm
02891    if ((pc = (char *)strstr(gUser,"@")))
02892       *pc = '\0';
02893    // drop instances, if any
02894    if ((pc = (char *)strstr(gUser,"/")))
02895       *pc = '\0';
02896 
02897    std::string targetUser = std::string(gUser);
02898 
02899    if (gClientProtocol >= 9) {
02900 
02901        // Receive target name
02902 
02903       if (gDebug > 2)
02904          ErrorInfo("RpdKrb5Auth: receiving target user ... ");
02905 
02906       EMessageTypes kind;
02907       char buffer[66];
02908       NetRecv(buffer, 65, kind);
02909 
02910       if (kind != kROOTD_KRB5) {
02911          ErrorInfo("RpdKrb5Auth: protocol error, received message"
02912                    " of type %d instead of %d\n",kind,kROOTD_KRB5);
02913       }
02914       buffer[65] = 0;
02915       targetUser = std::string(buffer);
02916 
02917       if (gDebug > 2)
02918          ErrorInfo("RpdKrb5Auth: received target user %s ",buffer);
02919    }
02920 
02921    if (gDebug > 2)
02922       ErrorInfo("RpdKrb5Auth: using ticket file: %s ... ",getenv("KRB5CCNAME"));
02923 
02924 
02925    // If the target user is not the owner of the principal
02926    // check if the user is authorized by the target user
02927    if (targetUser != gUser) {
02928       if (krb5_kuserok(gKcontext, ticket->enc_part2->client,
02929                                         targetUser.c_str())) {
02930          if (gDebug > 2)
02931          ErrorInfo("RpdKrb5Auth: change user from %s to %s successful",
02932                    gUser,targetUser.c_str());
02933          snprintf(gUser,64,"%s",targetUser.c_str());
02934          reply =  std::string("authenticated as ").append(gUser);
02935       } else {
02936          ErrorInfo("RpdKrb5Auth: could not change user from %s to %s",
02937                    gUser,targetUser.c_str());
02938          ErrorInfo("RpdKrb5Auth: continuing with user: %s",gUser);
02939       }
02940    }
02941 
02942    // Get credentials if in a PROOF session
02943    if (gClientProtocol >= 9 &&
02944       (gService == kPROOFD || gClientProtocol < 11)) {
02945 
02946       char *data = 0;
02947       int size = 0;
02948       if (gDebug > 2)
02949          ErrorInfo("RpdKrb5Auth: receiving forward cred ... ");
02950 
02951       {
02952          EMessageTypes kind;
02953          char bufLen[20];
02954          NetRecv(bufLen, 20, kind);
02955 
02956          if (kind != kROOTD_KRB5) {
02957             ErrorInfo("RpdKrb5Auth: protocol error, received"
02958                       " message of type %d instead of %d\n",
02959                       kind, kROOTD_KRB5);
02960          }
02961 
02962          size = atoi(bufLen);
02963          if (gDebug > 3)
02964             ErrorInfo("RpdKrb5Auth: got len '%s' %d ", bufLen, size);
02965 
02966          data = new char[size+1];
02967 
02968          // Receive and decode encoded public key
02969          int Nrec = NetRecvRaw(data, size);
02970 
02971          if (gDebug > 3)
02972             ErrorInfo("RpdKrb5Auth: received %d ", Nrec);
02973       }
02974 
02975       krb5_data forwardCreds;
02976       forwardCreds.data = data;
02977       forwardCreds.length = size;
02978 
02979       if (gDebug > 2)
02980          ErrorInfo("RpdKrb5Auth: received forward cred ... %d %d %d",
02981                    data[0], data[1], data[2]);
02982 
02983       int net = sock;
02984       retval = krb5_auth_con_genaddrs(gKcontext, auth_context, net,
02985                    KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
02986       if (retval) {
02987          ErrorInfo("RpdKrb5Auth: failed auth_con_genaddrs is: %s\n",
02988                    error_message(retval));
02989       }
02990 
02991       bool forwarding = true;
02992       krb5_creds **creds = 0;
02993       if ((retval = krb5_rd_cred(gKcontext, auth_context,
02994                                  &forwardCreds, &creds, 0))) {
02995          ErrorInfo("RpdKrb5Auth: rd_cred failed--%s", error_message(retval));
02996          forwarding = false;
02997       }
02998       if (data) delete[] data;
02999 
03000       struct passwd *pw = getpwnam(gUser);
03001       if (forwarding && pw) {
03002          Int_t fromUid = getuid();
03003          Int_t fromEUid = geteuid();
03004 
03005          if (setresuid(pw->pw_uid, pw->pw_uid, fromEUid) == -1) {
03006             ErrorInfo("RpdKrb5Auth: can't setuid for user %s", gUser);
03007             NetSend(kErrNotAllowed, kROOTD_ERR);
03008             RpdFreeKrb5Vars(gKcontext, server, ticket, auth_context, creds);
03009             return auth;
03010          }
03011 
03012          if (gDebug>5)
03013             ErrorInfo("RpdKrb5Auth: saving ticket to cache ...");
03014 
03015          krb5_context context;
03016          // Init context
03017          retval = krb5_init_context(&context);
03018          if (retval) {
03019             ErrorInfo("RpdKrb5Auth: %s while initializing second krb5",
03020                 error_message(retval));
03021             NetSend(kErrNotAllowed, kROOTD_ERR);
03022             RpdFreeKrb5Vars(gKcontext, server, ticket, auth_context, creds);
03023             return auth;
03024          }
03025 
03026          krb5_ccache cache = 0;
03027          char ccacheName[256];
03028          SPrintf(ccacheName,256,"%240s_root_%d",krb5_cc_default_name(context),getpid());
03029          if ((retval = krb5_cc_resolve(context, ccacheName, &cache))) {
03030             ErrorInfo("RpdKrb5Auth: cc_default failed--%s",
03031                       error_message(retval));
03032             NetSend(kErrNotAllowed, kROOTD_ERR);
03033             krb5_free_context(context);
03034             RpdFreeKrb5Vars(gKcontext, server, ticket, auth_context, creds);
03035             return auth;
03036          }
03037          {
03038             char *ccname = new char[strlen("KRB5CCNAME")+strlen(ccacheName)+2];
03039             SPrintf(ccname, strlen("KRB5CCNAME")+strlen(ccacheName)+2, "KRB5CCNAME=%.*s", strlen(ccacheName), ccacheName);
03040             putenv(ccname);
03041          }
03042 
03043          if (gDebug > 5)
03044             ErrorInfo("RpdKrb5Auth: working (1) on ticket to cache (%s) ... ",
03045                       krb5_cc_get_name(context,cache));
03046 
03047          // this is not working (why?)
03048          // this would mean that if a second user comes in, it will tremple
03049          // the existing one :(
03050          //       if ((retval = krb5_cc_gen_new(context,&cache))) {
03051          //          ErrorInfo("RpdKrb5Auth: cc_gen_new failed--%s",
03052          //                    error_message(retval));
03053          //          return auth;
03054          //       }
03055 
03056          const char *cacheName = krb5_cc_get_name(context,cache);
03057 
03058          if (gDebug>5)
03059             ErrorInfo("RpdKrb5Auth: working (2) on ticket"
03060                       " to cache (%s) ... ",cacheName);
03061 
03062          if ((retval = krb5_cc_initialize(context,cache,
03063                                           ticket->enc_part2->client))) {
03064             ErrorInfo("RpdKrb5Auth: cc_initialize failed--%s",
03065                       error_message(retval));
03066             RpdFreeKrb5Vars(gKcontext, server, ticket, auth_context, creds);
03067             krb5_free_context(context);
03068             NetSend(kErrNotAllowed, kROOTD_ERR);
03069             return auth;
03070          }
03071 
03072          if ((retval = krb5_cc_store_cred(context,cache, *creds))) {
03073             ErrorInfo("RpdKrb5Auth: cc_store_cred failed--%s",
03074                        error_message(retval));
03075             NetSend(kErrNotAllowed, kROOTD_ERR);
03076             krb5_free_context(context);
03077             RpdFreeKrb5Vars(gKcontext, server, ticket, auth_context, creds);
03078             return auth;
03079          }
03080          if (gDebug>5)
03081             ErrorInfo("RpdKrb5Auth: done ticket to cache (%s) ... ",
03082                       cacheName);
03083 
03084          if ((retval = krb5_cc_close(context,cache))) {
03085             ErrorInfo("RpdKrb5Auth: cc_close failed--%s",
03086                        error_message(retval));
03087             NetSend(kErrNotAllowed, kROOTD_ERR);
03088             krb5_free_context(context);
03089             RpdFreeKrb5Vars(gKcontext, server, ticket, auth_context, creds);
03090             return auth;
03091          }
03092 
03093          // free context
03094          krb5_free_context(context);
03095 
03096          //       if ( chown( cacheName, pw->pw_uid, pw->pw_gid) != 0 ) {
03097          //          ErrorInfo("RpdKrb5Auth: could not change the owner"
03098          //                    " ship of the cache file %s",cacheName);
03099          //       }
03100 
03101          if (setresuid(fromUid,fromEUid,pw->pw_uid) == -1) {
03102             ErrorInfo("RpdKrb5Auth: can't setuid back to original uid");
03103             NetSend(kErrNotAllowed, kROOTD_ERR);
03104             RpdFreeKrb5Vars(gKcontext, server, ticket, auth_context, creds);
03105             return auth;
03106          }
03107       }
03108 
03109       // free creds
03110       krb5_free_tgt_creds(gKcontext,creds);
03111    }
03112 
03113    NetSend(reply.c_str(), kMESS_STRING);
03114 
03115    // free allocated stuff
03116    RpdFreeKrb5Vars(gKcontext, server, ticket, auth_context, (krb5_creds **)0);
03117 
03118    // Authentication was successfull
03119    auth = 1;
03120    gSec = 2;
03121 
03122    if (gClientProtocol > 8) {
03123 
03124       char line[kMAXPATHLEN];
03125       if ((gReUseAllow & gAUTH_KRB_MSK) && gReUseRequired) {
03126 
03127          // Ask for the RSA key
03128          NetSend(gRSAKey, kROOTD_RSAKEY);
03129 
03130          // Receive the key securely
03131          if (RpdRecvClientRSAKey()) {
03132             ErrorInfo("RpdKrb5Auth: could not import a valid key"
03133                       " - switch off reuse for this session");
03134             gReUseRequired = 0;
03135          }
03136 
03137          // Set an entry in the auth tab file for later (re)use,
03138          // if required ...
03139          int offset = -1;
03140          char *token = 0;
03141          if (gReUseRequired) {
03142             SPrintf(line, kMAXPATHLEN, "2 1 %d %d %s %s",
03143                     gRSAKey, gRemPid, gOpenHost.c_str(), gUser);
03144             offset = RpdUpdateAuthTab(1, line, &token);
03145             if (gDebug > 2)
03146                ErrorInfo("RpdKrb5Auth: line:%s offset:%d", line, offset);
03147          }
03148          // Comunicate login user name to client
03149          SPrintf(line, kMAXPATHLEN, "%s %d", gUser, offset);
03150          NetSend(strlen(line), kROOTD_KRB5);   // Send message length first
03151          NetSend(line, kMESS_STRING);
03152 
03153          // Send Token
03154          if (gReUseRequired && offset > -1) {
03155             if (!token || (token && RpdSecureSend(token) == -1)) {
03156                ErrorInfo("RpdKrb5Auth: problems secure-sending token"
03157                          " - may result in corrupted token");
03158             }
03159             if (token) delete[] token;
03160          }
03161          gOffSet = offset;
03162 
03163       } else {
03164 
03165          // Comunicate login user name to client
03166          SPrintf(line, kMAXPATHLEN, "%s -1", gUser);
03167          NetSend(strlen(line), kROOTD_KRB5);   // Send message length first
03168          NetSend(line, kMESS_STRING);
03169 
03170       }
03171    } else {
03172       NetSend(user.c_str(), kMESS_STRING);
03173    }
03174 
03175    if (gDebug > 0)
03176       ErrorInfo("RpdKrb5Auth: user %s authenticated", gUser);
03177 #else
03178 
03179    // no krb5 support
03180    if (sstr) { }   // remove compiler warning
03181 
03182    NetSend(0, kROOTD_KRB5);
03183 #endif
03184 
03185    return auth;
03186 }
03187 
03188 //______________________________________________________________________________
03189 int RpdSRPUser(const char *sstr)
03190 {
03191    // Use Secure Remote Password protocol.
03192    // Check user id in $HOME/.srootdpass file.
03193 
03194    int auth = 0;
03195 
03196    if (!*sstr) {
03197       NetSend(kErrBadUser, kROOTD_ERR);
03198       ErrorInfo("RpdSRPUser: bad user name");
03199       return auth;
03200    }
03201 
03202 #ifdef R__SRP
03203 
03204    // Decode subject string
03205    char user[kMAXUSERLEN] = { 0 };
03206    if (gClientProtocol > 8) {
03207       int lenU, ofs, opt;
03208       char dumm[20];
03209       sscanf(sstr, "%d %d %d %d %127s %19s", &gRemPid, &ofs, &opt, &lenU, user, dumm);
03210       lenU = (lenU > kMAXUSERLEN) ? kMAXUSERLEN-1 : lenU;
03211       user[lenU] = '\0';
03212       gReUseRequired = (opt & kAUTH_REUSE_MSK);
03213 #if R__SSL
03214       if (gRSASSLKey) {
03215          // Determine type of RSA key required
03216          gRSAKey = (opt & kAUTH_RSATY_MSK) ? 2 : 1;
03217       } else
03218          gRSAKey = 1;
03219 #else
03220       gRSAKey = 1;
03221 #endif
03222    } else {
03223       SPrintf(user,kMAXUSERLEN,"%s",sstr);
03224    }
03225 
03226    struct passwd *pw = getpwnam(user);
03227    if (!pw) {
03228       NetSend(kErrNoUser, kROOTD_ERR);
03229       ErrorInfo("RpdSRPUser: user %s unknown", user);
03230       return auth;
03231    }
03232    // Method cannot be attempted for anonymous users ... (ie data servers )...
03233    if (!strcmp(pw->pw_shell, "/bin/false")) {
03234       NetSend(kErrNotAllowed, kROOTD_ERR);
03235       ErrorInfo("RpdSRPUser: no SRP for anonymous user '%s' ", user);
03236       return auth;
03237    }
03238    // If server is not started as root and user is not same as the
03239    // one who started rootd then authetication is not ok.
03240    uid_t uid = getuid();
03241    if (uid && uid != pw->pw_uid) {
03242       NetSend(kErrBadUser, kROOTD_ERR);
03243       ErrorInfo("RpdSRPUser: user not same as effective user of rootd");
03244       return auth;
03245    }
03246 
03247    NetSend(auth, kROOTD_AUTH);
03248 
03249    strlcpy(gUser, user, sizeof(gUser));
03250 
03251    std::string srootdpass, srootdconf;
03252    if (gAltSRPPass.length()) {
03253       srootdpass = gAltSRPPass;
03254    } else {
03255       srootdpass = std::string(pw->pw_dir).append(gSRootdPass);
03256    }
03257    srootdconf = srootdpass + std::string(".conf");
03258 
03259    FILE *fp1 = fopen(srootdpass.c_str(), "r");
03260    if (!fp1) {
03261       NetSend(kErrFileOpen, kROOTD_ERR);
03262       ErrorInfo("RpdSRPUser: error opening %s", srootdpass.c_str());
03263       return auth;
03264    }
03265    FILE *fp2 = fopen(srootdconf.c_str(), "r");
03266    if (!fp2) {
03267       NetSend(kErrFileOpen, kROOTD_ERR);
03268       ErrorInfo("RpdSRPUser: error opening %s", srootdconf.c_str());
03269       if (fp1)
03270          fclose(fp1);
03271       return auth;
03272    }
03273 
03274    struct t_pw *tpw = t_openpw(fp1);
03275    if (!tpw) {
03276       NetSend(kErrFileOpen, kROOTD_ERR);
03277       ErrorInfo("RpdSRPUser: unable to open password file %s",
03278                 srootdpass.c_str());
03279       fclose(fp1);
03280       fclose(fp2);
03281       return auth;
03282    }
03283 
03284    struct t_conf *tcnf = t_openconf(fp2);
03285    if (!tcnf) {
03286       NetSend(kErrFileOpen, kROOTD_ERR);
03287       ErrorInfo("RpdSRPUser: unable to open configuration file %s",
03288                 srootdconf.c_str());
03289       t_closepw(tpw);
03290       fclose(fp1);
03291       fclose(fp2);
03292       return auth;
03293    }
03294 #if R__SRP_1_1
03295    struct t_server *ts = t_serveropen(gUser, tpw, tcnf);
03296 #else
03297    struct t_server *ts = t_serveropenfromfiles(gUser, tpw, tcnf);
03298 #endif
03299    if (!ts) {
03300       NetSend(kErrNoUser, kROOTD_ERR);
03301       ErrorInfo("RpdSRPUser: user %s not found SRP password file", gUser);
03302       return auth;
03303    }
03304 
03305    if (tcnf)
03306       t_closeconf(tcnf);
03307    if (tpw)
03308       t_closepw(tpw);
03309    if (fp2)
03310       fclose(fp2);
03311    if (fp1)
03312       fclose(fp1);
03313 
03314    char hexbuf[MAXHEXPARAMLEN];
03315 
03316    // send n to client
03317    NetSend(t_tob64(hexbuf, (char *) ts->n.data, ts->n.len), kROOTD_SRPN);
03318    // send g to client
03319    NetSend(t_tob64(hexbuf, (char *) ts->g.data, ts->g.len), kROOTD_SRPG);
03320    // send salt to client
03321    NetSend(t_tob64(hexbuf, (char *) ts->s.data, ts->s.len),
03322            kROOTD_SRPSALT);
03323 
03324    struct t_num *B = t_servergenexp(ts);
03325 
03326    // receive A from client
03327    EMessageTypes kind;
03328    if (NetRecv(hexbuf, MAXHEXPARAMLEN, kind) < 0) {
03329       NetSend(kErrFatal, kROOTD_ERR);
03330       ErrorInfo("RpdSRPUser: error receiving A from client");
03331       return auth;
03332    }
03333    if (kind != kROOTD_SRPA) {
03334       NetSend(kErrFatal, kROOTD_ERR);
03335       ErrorInfo("RpdSRPUser: expected kROOTD_SRPA message");
03336       return auth;
03337    }
03338 
03339    unsigned char buf[MAXPARAMLEN];
03340    struct t_num A;
03341    A.data = buf;
03342    A.len = t_fromb64((char *) A.data, hexbuf);
03343 
03344    // send B to client
03345    NetSend(t_tob64(hexbuf, (char *) B->data, B->len), kROOTD_SRPB);
03346 
03347    t_servergetkey(ts, &A);
03348 
03349    // receive response from client
03350    if (NetRecv(hexbuf, MAXHEXPARAMLEN, kind) < 0) {
03351       NetSend(kErrFatal, kROOTD_ERR);
03352       ErrorInfo("RpdSRPUser: error receiving response from client");
03353       return auth;
03354    }
03355    if (kind != kROOTD_SRPRESPONSE) {
03356       NetSend(kErrFatal, kROOTD_ERR);
03357       ErrorInfo("RpdSRPUser: expected kROOTD_SRPRESPONSE message");
03358       return auth;
03359    }
03360 
03361    unsigned char cbuf[20];
03362    t_fromhex((char *) cbuf, hexbuf);
03363 
03364    if (!t_serververify(ts, cbuf)) {
03365 
03366       // authentication successful
03367       if (gDebug > 0)
03368          ErrorInfo("RpdSRPUser: user %s authenticated", gUser);
03369       auth = 1;
03370       gSec = 1;
03371 
03372       if (gClientProtocol > 8) {
03373 
03374          char line[kMAXPATHLEN];
03375          if ((gReUseAllow & gAUTH_SRP_MSK) && gReUseRequired) {
03376 
03377             // Ask for the RSA key
03378             NetSend(gRSAKey, kROOTD_RSAKEY);
03379 
03380             // Receive the key securely
03381             if (RpdRecvClientRSAKey()) {
03382                ErrorInfo
03383                    ("RpdSRPAuth: could not import a valid key"
03384                     " - switch off reuse for this session");
03385                gReUseRequired = 0;
03386             }
03387 
03388             // Set an entry in the auth tab file for later (re)use, if required ...
03389             int offset = -1;
03390             char *token = 0;
03391             if (gReUseRequired) {
03392                SPrintf(line, kMAXPATHLEN, "1 1 %d %d %s %s",
03393                        gRSAKey, gRemPid, gOpenHost.c_str(), gUser);
03394                offset = RpdUpdateAuthTab(1, line, &token);
03395             }
03396             // Comunicate login user name to client
03397             SPrintf(line, kMAXPATHLEN, "%s %d", gUser, offset);
03398             NetSend(strlen(line), kROOTD_SRPUSER);   // Send message length first
03399             NetSend(line, kMESS_STRING);
03400 
03401             if (gReUseRequired && offset > -1) {
03402                // Send Token
03403                if (RpdSecureSend(token) == -1) {
03404                   ErrorInfo("RpdSRPUser: problems secure-sending token"
03405                             " - may result in corrupted token");
03406                }
03407                if (token) delete[] token;
03408             }
03409             gOffSet = offset;
03410 
03411          } else {
03412             // Comunicate login user name to client
03413             SPrintf(line, kMAXPATHLEN, "%s -1", gUser);
03414             NetSend(strlen(line), kROOTD_SRPUSER);   // Send message length first
03415             NetSend(line, kMESS_STRING);
03416          }
03417 
03418       }
03419 
03420    } else {
03421       if (gClientProtocol > 8) {
03422          NetSend(kErrBadPasswd, kROOTD_ERR);
03423          ErrorInfo("RpdSRPUser: authentication failed for user %s", gUser);
03424          return auth;
03425       }
03426    }
03427 
03428    t_serverclose(ts);
03429 
03430 #else
03431    NetSend(0, kROOTD_SRPUSER);
03432 #endif
03433    return auth;
03434 }
03435 
03436 //______________________________________________________________________________
03437 int RpdCheckHostsEquiv(const char *host, const char *ruser,
03438                        const char *user, int &errout)
03439 {
03440    // Check if the requesting {host,user} can be granted immediate
03441    // login on the base of the information found in /etc/hosts.equiv
03442    // and/or $HOME/.rhosts. The two files must be trustable, i.e. owned
03443    // and modifiable only by 'root' and by 'user', respectively (0600).
03444    // Returns 1 in case access can be granted, 0 in any other case
03445    // (errout contains a code for error logging on the client side)
03446    //
03447    // NB: entries granting access in one of the two files cannot be
03448    //     overriden in the other file; so, system admins cannot close
03449    //     access from a host and user cannot stop access to their
03450    //     account if the administrator has decided so; as an example,
03451    //     if this entry is found in /etc/hosts.equiv
03452    //
03453    //     remote.host.dom auser
03454    //
03455    //     (allowing user named 'auser' from host 'remote.host.dom' to
03456    //     login to any non-root local account without specifying a
03457    //     password) the following entries in $home/.rhosts are ignored
03458    //
03459    //     remote.host.dom -auser
03460    //     -remote.host.dom
03461    //
03462    //     and access to 'auser' is always granted. This is a "feature"
03463    //     of ruserok.
03464    //
03465 
03466    int rc = 0;
03467 
03468    // Effective uid
03469    int rootuser = 0;
03470    if (!geteuid() && !getegid())
03471       rootuser = 1;
03472 
03473    // Check the files only if i) at least one exists; ii) those existing
03474    // have the right permission settings
03475    bool badfiles = 0;
03476    int  nfiles = 0;
03477 
03478    // Check system file /etc/hosts.equiv if non-root
03479    char hostsequiv[20] = { "/etc/hosts.equiv" };
03480    if (!rootuser) {
03481 
03482       // Get info about the file ...
03483       struct stat st;
03484       if (stat(hostsequiv,&st) == -1) {
03485          if (GetErrno() != ENOENT) {
03486             ErrorInfo("RpdCheckHostsEquiv: cannot stat /etc/hosts.equiv"
03487                       " (errno: %d)",GetErrno());
03488             badfiles = 1;
03489          } else
03490             if (gDebug > 1)
03491                ErrorInfo("RpdCheckHostsEquiv: %s does not exist",
03492                          hostsequiv);
03493       } else {
03494 
03495          // Require 'root' ownership
03496          if (st.st_uid || st.st_gid) {
03497             if (gDebug > 0)
03498                ErrorInfo("RpdCheckHostsEquiv: /etc/hosts.equiv not owned by"
03499                          " system (uid: %d, gid: %d)",st.st_uid,st.st_gid);
03500             badfiles = 1;
03501          } else {
03502 
03503             // Require WRITE permission only for owner
03504             if ((st.st_mode & S_IWGRP) || (st.st_mode & S_IWOTH)) {
03505                if (gDebug > 0)
03506                   ErrorInfo("RpdCheckHostsEquiv: group or others have write"
03507                             " permission on /etc/hosts.equiv: do not trust"
03508                             " it (g: %d, o: %d)",
03509                             (st.st_mode & S_IWGRP),(st.st_mode & S_IWOTH));
03510                badfiles = 1;
03511             } else
03512                // Good file
03513                nfiles++;
03514          }
03515       }
03516    }
03517 
03518    // Check local file
03519    char rhosts[kMAXPATHLEN] = {0};
03520    if (!badfiles) {
03521 
03522       struct passwd *pw = getpwnam(user);
03523       if (pw) {
03524          int ldir = strlen(pw->pw_dir);
03525          ldir = (ldir > kMAXPATHLEN - 9) ? (kMAXPATHLEN - 9) : ldir;
03526          memcpy(rhosts,pw->pw_dir,ldir);
03527          memcpy(rhosts+ldir,"/.rhosts",8);
03528          rhosts[ldir+8] = 0;
03529          if (gDebug > 2)
03530             ErrorInfo("RpdCheckHostsEquiv: checking for user file %s ...",rhosts);
03531       } else {
03532          if (gDebug > 0)
03533             ErrorInfo("RpdCheckHostsEquiv: cannot get user info with getpwnam"
03534                    " (errno: %d)",GetErrno());
03535          badfiles = 1;
03536       }
03537 
03538       if (!badfiles) {
03539          // Check the $HOME/.rhosts file ... ownership and protections
03540          struct stat st;
03541          if (stat(rhosts,&st) == -1) {
03542             if (GetErrno() != ENOENT) {
03543                ErrorInfo("RpdCheckHostsEquiv: cannot stat $HOME/.rhosts"
03544                       " (errno: %d)",GetErrno());
03545                badfiles = 1;
03546             } else
03547                ErrorInfo("RpdCheckHostsEquiv: %s/.rhosts does not exist",
03548                          pw->pw_dir);
03549          } else {
03550 
03551             // Only use file when its access rights are 0600
03552             if (!S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) ||
03553                 (st.st_mode & 0777) != (S_IRUSR | S_IWUSR)) {
03554                if (gDebug > 0)
03555                   ErrorInfo("RpdCheckHostsEquiv: unsecure permission setting"
03556                             " found for $HOME/.rhosts: 0%o (must be 0600)",
03557                             (st.st_mode & 0777));
03558                badfiles = 1;
03559             } else
03560                // Good file
03561                nfiles++;
03562          }
03563       }
03564    }
03565 
03566    // if files are not available or have wrong permissions or are
03567    // not accessible, give up
03568    if (!nfiles) {
03569       if (gDebug > 0)
03570          ErrorInfo("RpdCheckHostsEquiv: no files to check");
03571       errout = 1;
03572       if (badfiles) {
03573          if (gDebug > 0)
03574             ErrorInfo("RpdCheckHostsEquiv: config files cannot be used"
03575                       " (check permissions)");
03576          errout = 2;
03577       }
03578       return rc;
03579    }
03580 
03581    // Ok, now use ruserok to find out if {host,ruser,user}
03582    // is trusted
03583 #if defined(__sgi) || defined(_AIX) || defined(__alpha)
03584    if (ruserok((char*)host,rootuser,(char*)ruser,(char*)user) == 0) {
03585 #else
03586    if (ruserok(host,rootuser,ruser,user) == 0) {
03587 #endif
03588       if (gDebug > 0)
03589          ErrorInfo("RpdCheckHostsEquiv: remote user %s authorized to"
03590                    " access %s's area",ruser,user);
03591       rc = 1;
03592    } else {
03593       if (gDebug > 0)
03594          ErrorInfo("RpdCheckHostsEquiv: no special permission from"
03595                    " %s or %s",hostsequiv,rhosts);
03596       errout = 3;
03597    }
03598 
03599    return rc;
03600 }
03601 
03602 //______________________________________________________________________________
03603 int RpdCheckSpecialPass(const char *passwd)
03604 {
03605    // Check recieved user's password against password in $HOME/.rootdpass.
03606    // The password is retrieved in RpdUser and temporarly saved in gPasswd.
03607    // Returns 1 in case of success authentication, 0 otherwise.
03608 
03609    // Check inputs
03610    if (!passwd)
03611       return 0;
03612 
03613    // and the saved the password
03614    if (strlen(gPasswd) <= 0)
03615       return 0;
03616 
03617    // Ok, point to the saved passwd (retrieved in RpdUser)
03618    char *rootdpass = gPasswd;
03619    int n = 0;
03620 
03621    if (gClientProtocol > 8 && gSaltRequired > 0) {
03622       n = strlen(rootdpass);
03623       if (strncmp(passwd, rootdpass, n + 1) != 0) {
03624          if (gDebug > 0)
03625             ErrorInfo("RpdCheckSpecialPass: wrong password");
03626          rpdmemset((volatile void *)rootdpass,0,n);
03627          return 0;
03628       }
03629    } else {
03630 #ifndef R__NOCRYPT
03631       char *pass_crypt = crypt(passwd, rootdpass);
03632 #else
03633       char *pass_crypt = (char *)passwd;
03634 #endif
03635       n = strlen(rootdpass);
03636       if (strncmp(pass_crypt, rootdpass, n+1) != 0) {
03637          if (gDebug > 0)
03638             ErrorInfo("RpdCheckSpecialPass: wrong password");
03639          rpdmemset((volatile void *)rootdpass,0,n);
03640          return 0;
03641       }
03642    }
03643 
03644    if (gDebug > 0)
03645       ErrorInfo
03646           ("RpdCheckSpecialPass: user %s authenticated via ~/.rootdpass",
03647            gUser);
03648 
03649    rpdmemset((volatile void *)rootdpass,0,n);
03650    return 1;
03651 }
03652 
03653 //______________________________________________________________________________
03654 int RpdPass(const char *pass, int errheq)
03655 {
03656    // Check user's password.
03657 
03658    char passwd[128];
03659    char *passw;
03660    char *pass_crypt;
03661    struct passwd *pw;
03662 #ifdef R__SHADOWPW
03663    struct spwd *spw;
03664 #endif
03665    int afs_auth = 0;
03666 #ifdef R__AFS
03667    char *reason;
03668 #endif
03669 
03670    if (gDebug > 2)
03671       ErrorInfo("RpdPass: Enter (pass length: %d)", (int)strlen(pass));
03672 
03673    int auth = 0;
03674    errheq = (errheq > -1 && errheq < 4) ? errheq : 0;
03675    if (!*gUser) {
03676       if (gClientProtocol > 11)
03677          NetSend(gUsrPwdErr[0][errheq], kROOTD_ERR);
03678       else
03679          NetSend(kErrFatal, kROOTD_ERR);
03680       if (gDebug > 0)
03681          ErrorInfo("RpdPass: user needs to be specified first");
03682       return auth;
03683    }
03684 
03685    if (!pass) {
03686       if (gClientProtocol > 11)
03687          NetSend(gUsrPwdErr[1][errheq], kROOTD_ERR);
03688       else
03689          NetSend(kErrNoPasswd, kROOTD_ERR);
03690       if (gDebug > 0)
03691          ErrorInfo("RpdPass: no password specified");
03692       return auth;
03693    }
03694    int n = strlen(pass);
03695    // Passwd length should be in the correct range ...
03696    if (!n) {
03697       if (gClientProtocol > 11)
03698          NetSend(gUsrPwdErr[1][errheq], kROOTD_ERR);
03699       else
03700          NetSend(kErrBadPasswd, kROOTD_ERR);
03701       if (gDebug > 0)
03702          ErrorInfo("RpdPass: null passwd not allowed");
03703       return auth;
03704    }
03705    if (n > (int) sizeof(passwd)) {
03706       if (gClientProtocol > 11)
03707          NetSend(gUsrPwdErr[1][errheq], kROOTD_ERR);
03708       else
03709          NetSend(kErrBadPasswd, kROOTD_ERR);
03710       if (gDebug > 0)
03711          ErrorInfo("RpdPass: passwd too long");
03712       return auth;
03713    }
03714    // Inversion is done in RpdUser, if needed
03715    strlcpy(passwd, pass, sizeof(passwd));
03716 
03717    // Special treatment for anonimous ...
03718    if (gAnon) {
03719       strlcpy(gPasswd, passwd, sizeof(gPasswd));
03720       goto authok;
03721    }
03722    // ... and SpecialPass ...
03723    if (RpdCheckSpecialPass(passwd)) {
03724       goto authok;
03725    }
03726    // Get local passwd info for gUser
03727    if (!(pw = getpwnam(gUser))) {
03728       ErrorInfo("RpdPass: getpwnam failed!");
03729       return auth;
03730    }
03731 
03732 #ifdef R__AFS
03733    void *tok = GetAFSToken(gUser, passwd, 0, -1, &reason);
03734    afs_auth = (tok) ? 1 : 0;
03735    // We do not need the token anymore
03736    DeleteAFSToken(tok);
03737    if (!afs_auth) {
03738       if (gDebug > 0)
03739          ErrorInfo("RpdPass: AFS login failed for user %s: %s",
03740                     gUser, reason);
03741       // try conventional login...
03742 #endif
03743 
03744 #ifdef R__SHADOWPW
03745       // System V Rel 4 style shadow passwords
03746       if ((spw = getspnam(gUser)) == 0) {
03747          if (gDebug > 0)
03748             ErrorInfo("RpdPass: Shadow passwd not available for user %s",
03749                    gUser);
03750          passw = pw->pw_passwd;
03751       } else
03752          passw = spw->sp_pwdp;
03753 #else
03754       passw = pw->pw_passwd;
03755 #endif
03756 #ifndef R__NOCRYPT
03757       if (gClientProtocol <= 8 || !gSaltRequired) {
03758          char salt[20] = {0};
03759          int lenS = 2;
03760          if (!strncmp(passw, "$1$", 3)) {
03761             // Shadow passwd
03762             char *pd = strstr(passw + 4, "$");
03763             lenS = (int) (pd - passw);
03764             strncpy(salt, passw, lenS);
03765          } else
03766             strncpy(salt, passw, lenS);
03767          salt[lenS] = 0;
03768          pass_crypt = crypt(passwd, salt);   // Comment this
03769       } else {
03770          pass_crypt = passwd;
03771       }
03772 #else
03773       pass_crypt = passwd;
03774 #endif
03775       n = strlen(passw);
03776       if (strncmp(pass_crypt, passw, n + 1) != 0) {
03777          if (gClientProtocol > 11)
03778             NetSend(gUsrPwdErr[1][errheq], kROOTD_ERR);
03779          else
03780             NetSend(kErrBadPasswd, kROOTD_ERR);
03781          if (gDebug > 0)
03782             ErrorInfo("RpdPass: invalid password for user %s", gUser);
03783          return auth;
03784       }
03785       if (gDebug > 2)
03786          ErrorInfo("RpdPass: valid password for user %s", gUser);
03787 #ifdef R__AFS
03788    } else                            // afs_auth
03789       if (gDebug > 2)
03790          ErrorInfo("RpdPass: AFS login successful for user %s", gUser);
03791 #endif
03792 
03793    authok:
03794    auth = afs_auth ? 5 : 1;
03795    gSec = 0;
03796 
03797    if (gClientProtocol > 8) {
03798       // Set an entry in the auth tab file for later (re)use, if required ...
03799       int offset = -1;
03800       char *token = 0;
03801       char line[kMAXPATHLEN];
03802       if ((gReUseAllow & gAUTH_CLR_MSK) && gReUseRequired) {
03803 
03804          SPrintf(line, kMAXPATHLEN, "0 1 %d %d %s %s",
03805                  gRSAKey, gRemPid, gOpenHost.c_str(), gUser);
03806          if (!afs_auth || gService == kPROOFD)
03807             offset = RpdUpdateAuthTab(1, line, &token);
03808          if (gDebug > 2)
03809             ErrorInfo("RpdPass: got offset %d", offset);
03810 
03811          // Comunicate login user name to client
03812          SPrintf(line, kMAXPATHLEN, "%s %d", gUser, offset);
03813          if (gDebug > 2)
03814             ErrorInfo("RpdPass: sending back line %s", line);
03815          NetSend(strlen(line), kROOTD_PASS);   // Send message length first
03816          NetSend(line, kMESS_STRING);
03817 
03818          if (offset > -1) {
03819             if (gDebug > 2)
03820                ErrorInfo("RpdPass: sending token %s (Crypt: %d)", token,
03821                          gCryptRequired);
03822             if (gCryptRequired) {
03823                // Send over the token
03824                if (RpdSecureSend(token) == -1) {
03825                   if (gDebug > 0)
03826                      ErrorInfo("RpdPass: problems secure-sending token"
03827                             " - may result in corrupted token");
03828                }
03829             } else {
03830                // Send token inverted
03831                for (int i = 0; i < (int) strlen(token); i++) {
03832                   token[i] = ~token[i];
03833                }
03834                NetSend(token, kMESS_STRING);
03835             }
03836             delete[] token;
03837          }
03838          gOffSet = offset;
03839 
03840       } else {
03841          // Comunicate login user name to client
03842          SPrintf(line, kMAXPATHLEN, "%s -1", gUser);
03843          if (gDebug > 2)
03844             ErrorInfo("RpdPass: sending back line %s", line);
03845          NetSend(strlen(line), kROOTD_PASS);   // Send message length first
03846          NetSend(line, kMESS_STRING);
03847       }
03848    }
03849 
03850    return auth;
03851 }
03852 
03853 //______________________________________________________________________________
03854 int RpdGlobusInit()
03855 {
03856    // Prepare for globus authentication: check hostcer.conf and get
03857    // the credential handle. This is run once at daemon start-up
03858 
03859 #ifdef R__GLBS
03860    // Now we open the certificates and we check if we are able to
03861    // autheticate the client. In the affirmative case we initialize
03862    // our credentials and we send our subject name to the client ...
03863    // NB: we look first for a specific certificate for ROOT (default
03864    // location under /etc/grid-security/root); if this is does not
03865    // work we try to open the host certificate, which however may
03866    // require super-user privileges; finally we check if valid proxies
03867    // (for the user who started the server) are available.
03868    char *subject_name = 0;
03869    int certRc = GlbsToolCheckCert(&subject_name);
03870    if (certRc)
03871       certRc = GlbsToolCheckProxy(&subject_name);
03872    if (certRc) {
03873       ErrorInfo("RpdGlobusInit: no valid server credentials found: globus disabled");
03874       gHaveGlobus = 0;
03875       return 1;
03876    } else {
03877 
03878       // Save the subject name
03879       gGlobusSubjName = subject_name;
03880       delete [] subject_name;
03881 
03882       // Inquire Globus credentials:
03883       // This is looking to file X509_USER_CERT for valid a X509 cert (default
03884       // /etc/grid-security/hostcert.pem) and to dir X509_CERT_DIR for trusted CAs
03885       // (default /etc/grid-security/certificates).
03886       OM_uint32 majStat = 0;
03887       OM_uint32 minStat = 0;
03888       if ((majStat =
03889            globus_gss_assist_acquire_cred(&minStat, GSS_C_ACCEPT,
03890                                           &gGlbCredHandle)) !=
03891           GSS_S_COMPLETE) {
03892          GlbsToolError("RpdGlobusInit: gss_assist_acquire_cred", majStat,
03893                        minStat, 0);
03894          if (getuid() > 0)
03895             ErrorInfo("RpdGlobusInit: non-root: make sure you have"
03896                       " initialized (manually) your proxies");
03897          return 1;
03898       }
03899    }
03900 #endif
03901    // Done
03902    return 0;
03903 }
03904 
03905 //______________________________________________________________________________
03906 int RpdGlobusAuth(const char *sstr)
03907 {
03908    // Authenticate via Globus.
03909 
03910    int auth = 0;
03911 
03912 #ifndef R__GLBS
03913 
03914    if (sstr) { }  // use sstr
03915    NetSend(0, kROOTD_GLOBUS);
03916    return auth;
03917 
03918 #else
03919 
03920    if (!gHaveGlobus) {
03921       // No valid credentials
03922       if (sstr) { }  // use sstr
03923       return auth;
03924    }
03925 
03926    OM_uint32 MajStat = 0;
03927    OM_uint32 MinStat = 0;
03928    OM_uint32 GssRetFlags = 0;
03929    gss_ctx_id_t GlbContextHandle = GSS_C_NO_CONTEXT;
03930    gss_cred_id_t GlbDelCredHandle = GSS_C_NO_CREDENTIAL;
03931    int GlbTokenStatus = 0;
03932    char *GlbClientName;
03933    FILE *FILE_SockFd;
03934    char *gridmap_default = "/etc/grid-security/grid-mapfile";
03935    EMessageTypes kind;
03936    int lSubj, offset = -1;
03937    char *user = 0;
03938    int ulen = 0;
03939 
03940    if (gDebug > 2)
03941       ErrorInfo("RpdGlobusAuth: contacted by host: %s", gOpenHost.c_str());
03942 
03943    // Tell the remote client that we may accept Globus credentials ...
03944    NetSend(1, kROOTD_GLOBUS);
03945 
03946    // Decode subject string
03947    char Subj[kMAXPATHLEN];
03948    int opt;
03949    char dumm[20];
03950    sscanf(sstr, "%d %d %d %d %4095s %19s", &gRemPid, &offset, &opt, &lSubj, Subj, dumm);
03951 
03952    Subj[lSubj] = '\0';
03953    gReUseRequired = (opt & kAUTH_REUSE_MSK);
03954 #if R__SSL
03955    if (gRSASSLKey) {
03956       // Determine type of RSA key required
03957       gRSAKey = (opt & kAUTH_RSATY_MSK) ? 2 : 1;
03958    } else
03959       gRSAKey = 1;
03960 #else
03961    gRSAKey = 1;
03962 #endif
03963    if (gDebug > 2)
03964       ErrorInfo("RpdGlobusAuth: gRemPid: %d, Subj: %s (%d %d)", gRemPid,
03965                 Subj, lSubj, strlen(Subj));
03966 
03967    if (gClientProtocol < 17) {
03968       // GlbClientName will be determined from the security context ...
03969       // Now wait for client to communicate the issuer name of the certificate ...
03970       char *answer = new char[20];
03971       NetRecv(answer, (int) sizeof(answer), kind);
03972       if (kind != kMESS_STRING) {
03973          Error(gErr, kErrAuthNotOK,
03974                 "RpdGlobusAuth: client_issuer_name:received unexpected"
03975                 " type of message (%d)",kind);
03976          if (answer) delete[] answer;
03977          return auth;
03978       }
03979       int client_issuer_name_len = atoi(answer);
03980       if (answer) delete[] answer;
03981       char *client_issuer_name = new char[client_issuer_name_len + 1];
03982       NetRecv(client_issuer_name, client_issuer_name_len, kind);
03983       if (kind != kMESS_STRING) {
03984          Error(gErr, kErrAuthNotOK,
03985                "RpdGlobusAuth: client_issuer_name:received unexpected"
03986                " type of message (%d)",kind);
03987          if (client_issuer_name) delete[] client_issuer_name;
03988          return auth;
03989       }
03990       if (gDebug > 2)
03991          ErrorInfo("RpdGlobusAuth: client issuer name is: %s",
03992                    client_issuer_name);
03993    }
03994 
03995    // Send our subject to the clients: it is needed to start
03996    // the handshake
03997    int sjlen = gGlobusSubjName.length() + 1;
03998    int bsnd = NetSend(sjlen, kROOTD_GLOBUS);
03999    if (gDebug > 2)
04000       ErrorInfo("RpdGlobusAuth: sent: %d (due >=%d))", bsnd, 2 * sizeof(sjlen));
04001    bsnd = NetSend(gGlobusSubjName.c_str(), sjlen, kMESS_STRING);
04002    if (gDebug > 2)
04003       ErrorInfo("RpdGlobusAuth: sent: %d (due >=%d))", bsnd, sjlen);
04004 
04005    // We need to associate a FILE* stream with the socket
04006    // It will automatically closed when the socket will be closed ...
04007    FILE_SockFd = fdopen(NetGetSockFd(), "w+");
04008 
04009    // Now we are ready to start negotiating with the Client
04010    if ((MajStat =
04011         globus_gss_assist_accept_sec_context(&MinStat, &GlbContextHandle,
04012                                              gGlbCredHandle, &GlbClientName,
04013                                              &GssRetFlags, 0,
04014                                              &GlbTokenStatus,
04015                                              &GlbDelCredHandle,
04016                                              globus_gss_assist_token_get_fd,
04017                                              (void *) FILE_SockFd,
04018                                              globus_gss_assist_token_send_fd,
04019                                              (void *) FILE_SockFd)) !=
04020        GSS_S_COMPLETE) {
04021       GlbsToolError("RpdGlobusAuth: gss_assist_accept_sec_context",
04022                     MajStat, MinStat, GlbTokenStatus);
04023       return auth;
04024    } else {
04025       auth = 1;
04026       gSec = 3;
04027       if (gDebug > 0)
04028          ErrorInfo("RpdGlobusAuth: user: %s \n authenticated",
04029                    GlbClientName);
04030    }
04031 
04032    // Check if there might be the need of credentials ...
04033    if (gService == kPROOFD) {
04034       // Check that we got delegation to autheticate the slaves
04035       if (GssRetFlags | GSS_C_DELEG_FLAG) {
04036          if (gDebug > 2)
04037             ErrorInfo("RpdGlobusAuth: Pointer to del cred is %p", GlbDelCredHandle);
04038       } else {
04039          Error(gErr, kErrAuthNotOK,
04040                "RpdGlobusAuth: did not get delegated credentials (RetFlags: 0x%x)",
04041                GssRetFlags);
04042          return auth;
04043       }
04044       // Now we have to export these delegated credentials to a shared memory segment
04045       // for later use in 'proofserv' ...
04046       //   credential= (gss_buffer_t)malloc(sizeof(gss_buffer_desc));
04047       gss_buffer_t credential = new gss_buffer_desc;
04048       if ((MajStat =
04049            gss_export_cred(&MinStat, GlbDelCredHandle, 0, 0,
04050                            credential)) != GSS_S_COMPLETE) {
04051          GlbsToolError("RpdGlobusAuth: gss_export_cred", MajStat, MinStat,
04052                        0);
04053          return auth;
04054       } else if (gDebug > 2)
04055          ErrorInfo("RpdGlobusAuth: credentials prepared for export");
04056 
04057       // Now store it in shm for later use in proofserv ...
04058       int rc;
04059       if ((rc = GlbsToolStoreToShm(credential, &gShmIdCred))) {
04060          ErrorInfo
04061              ("RpdGlobusAuth: credentials not correctly stored in shm (rc: %d)",
04062               rc);
04063       }
04064       if (gDebug > 2)
04065          ErrorInfo
04066              ("RpdGlobusAuth: credentials stored in shared memory segment %d",
04067               gShmIdCred);
04068 
04069       delete credential;
04070    } else {
04071       if (gDebug > 2)
04072          ErrorInfo("RpdGlobusAuth: no need for delegated credentials (%s)",
04073                    gServName[gService].c_str());
04074    }
04075 
04076    // For Now we set the gUser to the certificate owner using the gridmap file ...
04077    // Should be understood if this is really necessary ...
04078    if (getenv("GRIDMAP") == 0) {
04079       // The installation did not specify a special location for the gridmap file
04080       // We assume the usual default ...
04081       setenv("GRIDMAP", gridmap_default, 1);
04082       if (gDebug > 2)
04083          ErrorInfo("RpdGlobusAuth: gridmap: using default file (%s)",
04084                    gridmap_default);
04085    } else if (gDebug > 2)
04086       ErrorInfo("RpdGlobusAuth: gridmap: using file %s",
04087                 getenv("GRIDMAP"));
04088 
04089    // Get local login name for the subject ...
04090    char AnonUser[10] = "rootd";
04091    if (globus_gss_assist_gridmap(GlbClientName, &user)) {
04092       if (gDebug > 2)
04093          ErrorInfo
04094              ("RpdGlobusAuth: unable to get local username from gridmap: using: %s",
04095               AnonUser);
04096       user = strdup(AnonUser);
04097       if (gDebug > 2)
04098          ErrorInfo("RpdGlobusAuth: user: %s", user);
04099    }
04100    if (!strcmp(user, "anonymous"))
04101       user = strdup(AnonUser);
04102    if (!strcmp(user, AnonUser))
04103       gAnon = 1;
04104 
04105    // No reuse for anonymous users
04106    gReUseRequired = (gAnon == 1) ? 0 : gReUseRequired;
04107 
04108    // Fill gUser and free allocated memory
04109    ulen = strlen(user);
04110    strncpy(gUser, user, ulen + 1);
04111 
04112    char line[kMAXPATHLEN];
04113    if ((gReUseAllow & gAUTH_GLB_MSK) && gReUseRequired) {
04114 
04115       // Ask for the RSA key
04116       NetSend(gRSAKey, kROOTD_RSAKEY);
04117 
04118       // Receive the key securely
04119       if (RpdRecvClientRSAKey()) {
04120          ErrorInfo
04121              ("RpdGlobusAuth: could not import a valid key"
04122               " - switch off reuse for this session");
04123          gReUseRequired = 0;
04124       }
04125 
04126       // Store security context and related info for later use ...
04127       offset = -1;
04128       char *token = 0;
04129       if (gReUseRequired) {
04130          int ShmId = GlbsToolStoreContext(GlbContextHandle, user);
04131          if (ShmId > 0) {
04132             SPrintf(line, kMAXPATHLEN, "3 1 %d %d %s %s %d %s",
04133                     gRSAKey, gRemPid, gOpenHost.c_str(),
04134                     user, ShmId, GlbClientName);
04135             offset = RpdUpdateAuthTab(1, line, &token);
04136          } else if (gDebug > 0)
04137             ErrorInfo
04138                 ("RpdGlobusAuth: unable to export context to shm for later use");
04139       }
04140       // Comunicate login user name to client (and token)
04141       SPrintf(line, kMAXPATHLEN, "%s %d", gUser, offset);
04142       NetSend(strlen(line), kROOTD_GLOBUS);   // Send message length first
04143       NetSend(line, kMESS_STRING);
04144 
04145       if (gReUseRequired && offset > -1) {
04146          // Send Token
04147          if (RpdSecureSend(token) == -1) {
04148             ErrorInfo("RpdGlobusAuth: problems secure-sending token"
04149                       " - may result in corrupted token");
04150          }
04151          if (token) delete[] token;
04152       }
04153       gOffSet = offset;
04154    } else {
04155       // Comunicate login user name to client (and token)
04156       SPrintf(line, kMAXPATHLEN, "%s %d", gUser, offset);
04157       NetSend(strlen(line), kROOTD_GLOBUS);   // Send message length first
04158       NetSend(line, kMESS_STRING);
04159    }
04160 
04161    // and free allocated memory
04162    free(user);
04163    free(GlbClientName);
04164 
04165    if (gDebug > 0)
04166       ErrorInfo("RpdGlobusAuth: client mapped to local user %s ", gUser);
04167 
04168    return auth;
04169 
04170 #endif
04171 }
04172 
04173 //______________________________________________________________________________
04174 int RpdRfioAuth(const char *sstr)
04175 {
04176    // Check if user and group id specified in the request exist in the
04177    // passwd file. If they do then grant access. Very insecure: to be used
04178    // with care.
04179 
04180    int auth = 0;
04181 
04182    if (gDebug > 2)
04183       ErrorInfo("RpdRfioAuth: analyzing ... %s", sstr);
04184 
04185    if (!*sstr) {
04186       NetSend(kErrBadUser, kROOTD_ERR);
04187       ErrorInfo("RpdRfioAuth: subject string is empty");
04188       return auth;
04189    }
04190    // Decode subject string
04191    unsigned int uid, gid;
04192    sscanf(sstr, "%u %u", &uid, &gid);
04193 
04194    // Now inquire passwd ...
04195    struct passwd *pw;
04196    if ((pw = getpwuid((uid_t) uid)) == 0) {
04197       NetSend(kErrBadUser, kROOTD_ERR);
04198       ErrorInfo("RpdRfioAuth: uid %u not found", uid);
04199       return auth;
04200    }
04201    // Check if authorized
04202    char cuid[20];
04203    SPrintf(cuid, 20, "%u", uid);
04204    if (gUserIgnLen[5] > 0 && strstr(gUserIgnore[5], cuid) != 0) {
04205       NetSend(kErrNotAllowed, kROOTD_ERR);
04206       ErrorInfo
04207           ("RpdRfioAuth: user (%u,%s) not authorized to use (uid:gid) method",
04208            uid, pw->pw_name);
04209       return auth;
04210    }
04211    if (gUserAlwLen[5] > 0 && strstr(gUserAllow[5], cuid) == 0) {
04212       NetSend(kErrNotAllowed, kROOTD_ERR);
04213       ErrorInfo
04214           ("RpdRfioAuth: user (%u,%s) not authorized to use (uid:gid) method",
04215            uid, pw->pw_name);
04216       return auth;
04217    }
04218 
04219    // Now check group id ...
04220    if (gid != (unsigned int) pw->pw_gid) {
04221       NetSend(kErrBadUser, kROOTD_ERR);
04222       ErrorInfo
04223           ("RpdRfioAuth: group id does not match (remote:%u,local:%u)",
04224            gid, (unsigned int) pw->pw_gid);
04225       return auth;
04226    }
04227    // Set username ....
04228    strlcpy(gUser, pw->pw_name, sizeof(gUser));
04229 
04230 
04231    // Notify, if required ...
04232    if (gDebug > 0)
04233       ErrorInfo("RpdRfioAuth: user %s authenticated (uid:%u, gid:%u)",
04234                 gUser, uid, gid);
04235 
04236    // Set Auth flag
04237    auth = 1;
04238    gSec = 5;
04239 
04240    return auth;
04241 }
04242 
04243 //______________________________________________________________________________
04244 void RpdAuthCleanup(const char *sstr, int opt)
04245 {
04246    // Terminate correctly by cleaning up the auth table (and shared
04247    // memories in case of Globus) and closing the file.
04248    // Called upon receipt of a kROOTD_CLEANUP and on SIGPIPE.
04249 
04250    int rpid = 0, sec = -1, offs = -1, nw = 0;
04251    char usr[64] = {0};
04252    if (sstr)
04253       nw = sscanf(sstr, "%d %d %d %63s", &rpid, &sec, &offs, usr);
04254 
04255    // Turn back to superuser for cleaning, if the case
04256    if (getuid() == 0) {
04257       if (setresgid(0, 0, 0) == -1)
04258          if (gDebug > 0)
04259             ErrorInfo("RpdAuthCleanup: can't setgid to superuser");
04260       if (setresuid(0, 0, 0) == -1)
04261          if (gDebug > 0)
04262             ErrorInfo("RpdAuthCleanup: can't setuid to superuser");
04263    }
04264    if (opt == 0) {
04265       RpdCleanupAuthTab("all", 0, -1);            // Cleanup everything (SIGPIPE)
04266       ErrorInfo("RpdAuthCleanup: cleanup ('all',0) done");
04267    } else if (opt == 1) {
04268       if (nw == 1) {
04269          // host specific cleanup
04270          RpdCleanupAuthTab(gOpenHost.c_str(), rpid, -1);
04271          ErrorInfo("RpdAuthCleanup: cleanup ('%s',%d) done",
04272                    gOpenHost.c_str(), rpid);
04273       } else if (nw == 4) {
04274          // (host,usr,method) specific cleanup
04275          if (RpdCheckOffSet(sec,usr,gOpenHost.c_str(),rpid,&offs,0,0,0)) {
04276             RpdCleanupAuthTab(gOpenHost.c_str(), rpid, offs);
04277             ErrorInfo("RpdAuthCleanup: cleanup (%s,%d,%d,%d,%s) done",
04278                       gOpenHost.c_str(), rpid, sec, offs, usr);
04279          } else {
04280             ErrorInfo("RpdAuthCleanup: cleanup not done: %s",
04281                       "wrong offset or already cleaned up");
04282          }
04283       }
04284    }
04285 }
04286 
04287 //______________________________________________________________________________
04288 void RpdInitAuth()
04289 {
04290 
04291    // Size check done in RpdUpdateAuthTab(1,...)
04292 
04293    // Reset
04294    int i;
04295    gNumAllow = gNumLeft = 0;
04296    for (i = 0; i < kMAXSEC; i++) {
04297       gAllowMeth[i] = -1;
04298       gHaveMeth[i] = 1;
04299    }
04300 
04301    // List of default authentication methods
04302    RpdDefaultAuthAllow();
04303 }
04304 
04305 //______________________________________________________________________________
04306 void RpdDefaultAuthAllow()
04307 {
04308    // Check configuration options and running daemons to build a default list
04309    // of secure methods.
04310 
04311    if (gDebug > 2)
04312       ErrorInfo("RpdDefaultAuthAllow: Enter");
04313 
04314    // UsrPwdClear
04315    gAllowMeth[gNumAllow] = 0;
04316    gNumAllow++;
04317    gNumLeft++;
04318 
04319    // SSH
04320    gAllowMeth[gNumAllow] = 4;
04321    gNumAllow++;
04322    gNumLeft++;
04323 
04324    // SRP
04325 #ifdef R__SRP
04326    gAllowMeth[gNumAllow] = 1;
04327    gNumAllow++;
04328    gNumLeft++;
04329 #else
04330    // Don't have this method
04331    gHaveMeth[1] = 0;
04332 #endif
04333 
04334    // Kerberos
04335 #ifdef R__KRB5
04336    gAllowMeth[gNumAllow] = 2;
04337    gNumAllow++;
04338    gNumLeft++;
04339 #else
04340    // Don't have this method
04341    gHaveMeth[2] = 0;
04342 #endif
04343 
04344    // Globus
04345 #ifdef R__GLBS
04346    gAllowMeth[gNumAllow] = 3;
04347    gNumAllow++;
04348    gNumLeft++;
04349 #else
04350    // Don't have this method
04351    gHaveMeth[3] = 0;
04352 #endif
04353 
04354    if (gDebug > 2) {
04355       int i;
04356       std::string temp;
04357       char cm[5];
04358       if (gNumAllow == 0)
04359          temp.append("none");
04360       for (i = 0; i < gNumAllow; i++) {
04361          SPrintf(cm, 5, " %3d",gAllowMeth[i]);
04362          temp.append(cm);
04363       }
04364       ErrorInfo
04365           ("RpdDefaultAuthAllow: default list of secure methods available: %s",
04366            temp.c_str());
04367    }
04368 }
04369 
04370 //______________________________________________________________________________
04371 int RpdCheckDaemon(const char *daemon)
04372 {
04373    // Check the running of process 'daemon'.
04374    // Info got from 'ps ax'.
04375 
04376    char cmd[kMAXPATHLEN] = { 0 };
04377    int ch, i = 0, cnt = 0;
04378 
04379    if (gDebug > 2)
04380       ErrorInfo("RpdCheckDaemon: Enter ... %s", daemon);
04381 
04382    // Return if empty
04383    if (daemon == 0 || strlen(daemon) == 0)
04384       return cnt;
04385 
04386    // Build command
04387    SPrintf(cmd, kMAXPATHLEN, "ps ax | grep %s 2>/dev/null", daemon);
04388 
04389    // Run it ...
04390    FILE *fp = popen(cmd, "r");
04391    if (fp != 0) {
04392       for (ch = fgetc(fp); ch != EOF; ch = fgetc(fp)) {
04393          if (ch != 10) {
04394             cmd[i++] = ch;
04395          } else {
04396             cmd[i] = '\0';
04397             if (strstr(cmd, "grep") == 0 && strstr(cmd, "rootd") == 0
04398                 && strstr(cmd, "proofd") == 0) {
04399                cnt++;
04400             }
04401             i = 0;
04402          }
04403       }
04404       if (i > 0) {
04405          cmd[i] = '\0';
04406          cnt++;
04407       }
04408       pclose(fp);
04409       if (gDebug > 2)
04410          ErrorInfo("RpdCheckDaemon: found %d instances of daemon %s",
04411                    cnt, daemon);
04412 
04413    } else {
04414       ErrorInfo("RpdCheckDaemon: problems executing cmd ...");
04415    }
04416    return cnt;
04417 }
04418 
04419 //______________________________________________________________________________
04420 int RpdCheckSshd(int opt)
04421 {
04422    // Tries to connect to sshd daemon on its standard port (22)
04423    // Used if RpdCheckDaemon returns a negative result
04424 
04425    if (gDebug > 2)
04426       ErrorInfo("RpdCheckSshd: Enter ... ");
04427 
04428    int rc = 0;
04429    if (opt == 0) {
04430 
04431       //
04432       // Check netstat output ...
04433       //
04434 
04435       // build check string
04436       char cs[20];
04437       SPrintf(cs, 20, ":%d",gSshdPort);
04438 
04439       // Run 'netstat' to check listening processes
04440       char cmd[kMAXPATHLEN] = { 0 };
04441       SPrintf(cmd, kMAXPATHLEN,
04442            "netstat -apn 2>/dev/null | grep LISTEN | grep -v LISTENING");
04443       FILE *fp= popen(cmd,"r");
04444       if (fp != 0) {
04445          while (fgets(cmd, sizeof(cmd), fp) != 0) {
04446             if (gDebug > 3)
04447                ErrorInfo("RpdCheckSshd: read: %s",cmd);
04448             if (strstr(cmd,cs)) {
04449                rc = 1;
04450                break;
04451             }
04452          }
04453          pclose(fp);
04454       } else {
04455          ErrorInfo("RpdCheckSshd: Problems executing 'netstat' ...");
04456       }
04457 
04458       if (gDebug > 2 && rc) {
04459          ErrorInfo("RpdCheckSshd: %s: %s %d", "diagnostics report",
04460                    "something is listening on port", gSshdPort);
04461       }
04462 
04463       if (!rc) {
04464          ErrorInfo("RpdCheckSshd: nothing seem to listening on port %d",
04465                    gSshdPort);
04466       }
04467 
04468    } else if (opt == 1) {
04469 
04470       //
04471       // Open a socket on port gSshdPort ...
04472       //
04473 
04474       // First get local host address
04475       struct hostent *h = gethostbyname("localhost");
04476       if (h == 0) {
04477          // Make further attempt with HOSTNAME
04478          if (getenv("HOSTNAME") == 0) {
04479             ErrorInfo("RpdCheckSshd: unable to resolve local host name");
04480             return 0;
04481          } else {
04482             h = gethostbyname(getenv("HOSTNAME"));
04483             if (h == 0) {
04484                ErrorInfo
04485                    ("RpdCheckSshd: local host name is unknown to gethostbyname: '%s'",
04486                     getenv("HOSTNAME"));
04487                return 0;
04488             }
04489          }
04490       }
04491 
04492       // Fill relevant sockaddr_in structure
04493       struct sockaddr_in servAddr;
04494       servAddr.sin_zero[0] = 0;
04495       servAddr.sin_family = h->h_addrtype;
04496       memcpy((char *) &servAddr.sin_addr.s_addr, h->h_addr_list[0],
04497              h->h_length);
04498       servAddr.sin_port = htons(gSshdPort);
04499 
04500       // create AF_INET socket
04501       int sd = socket(AF_INET, SOCK_STREAM, 0);
04502       if (sd < 0) {
04503          ErrorInfo("RpdCheckSshd: cannot open new AF_INET socket (errno:%d) ",
04504                    errno);
04505          return 0;
04506       }
04507 
04508       /* bind any port number */
04509       struct sockaddr_in localAddr;
04510       localAddr.sin_zero[0] = 0;
04511       localAddr.sin_family = AF_INET;
04512       localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
04513       localAddr.sin_port = htons(0);
04514       if (bind(sd, (struct sockaddr *) &localAddr, sizeof(localAddr)) < 0) {
04515          ErrorInfo("RpdCheckSshd: cannot bind to local port %u", gSshdPort);
04516          return 0;
04517       }
04518       // connect to server
04519       if (connect(sd, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0) {
04520          ErrorInfo("RpdCheckSshd: cannot connect to local port %u",
04521                    gSshdPort);
04522          return 0;
04523       }
04524       // Sshd successfully contacted
04525       if (gDebug > 2)
04526          ErrorInfo("RpdCheckSshd: success!");
04527       rc = 1;
04528    }
04529 
04530    return rc;
04531 }
04532 
04533 //______________________________________________________________________________
04534 int RpdUser(const char *sstr)
04535 {
04536    // Check user id. If user id is not equal to rootd's effective uid, user
04537    // will not be allowed access, unless effective uid = 0 (i.e. root).
04538    const int kMaxBuf = 256;
04539    char recvbuf[kMaxBuf];
04540    EMessageTypes kind;
04541    struct passwd *pw;
04542    if (gDebug > 2)
04543       ErrorInfo("RpdUser: Enter ... %s", sstr);
04544 
04545    int auth = 0;
04546 
04547    // Nothing can be done if empty message
04548    if (!*sstr) {
04549       NetSend(kErrBadUser, kROOTD_ERR);
04550       ErrorInfo("RpdUser: received empty string");
04551       return auth;
04552    }
04553    // Parse input message
04554    char user[kMAXUSERLEN] = {0};
04555    char ruser[kMAXUSERLEN] = {0};
04556    if (gClientProtocol > 8) {
04557       int ulen, ofs, opt, rulen;
04558       // Decode subject string
04559       int nw = sscanf(sstr, "%d %d %d %d %63s %d %63s",
04560                             &gRemPid, &ofs, &opt, &ulen, user, &rulen, ruser);
04561       ulen = (ulen >= kMAXUSERLEN) ? kMAXUSERLEN-1 : ulen;
04562       rulen = (rulen >= kMAXUSERLEN) ? kMAXUSERLEN-1 : rulen;
04563       user[ulen] = '\0';
04564       if (nw > 5)
04565          ruser[rulen] = '\0';
04566       gReUseRequired = (opt & kAUTH_REUSE_MSK);
04567       gCryptRequired = (opt & kAUTH_CRYPT_MSK);
04568       gSaltRequired  = (opt & kAUTH_SSALT_MSK);
04569       gOffSet = ofs;
04570 #if R__SSL
04571       if (gRSASSLKey) {
04572          // Determine type of RSA key required
04573          gRSAKey = (opt & kAUTH_RSATY_MSK) ? 2 : 1;
04574       } else
04575          gRSAKey = 1;
04576 #else
04577       gRSAKey = 1;
04578 #endif
04579    } else {
04580       SPrintf(user,kMAXUSERLEN,"%s",sstr);
04581    }
04582    if (gDebug > 2)
04583       ErrorInfo("RpdUser: gReUseRequired: %d gCryptRequired: %d gRSAKey: %d",
04584                 gReUseRequired, gCryptRequired, gRSAKey);
04585 
04586    ERootdErrors err = kErrNoUser;
04587    if (gService == kROOTD) {
04588       // Default anonymous account ...
04589       if (!strcmp(user, "anonymous")) {
04590          user[0] = '\0';
04591          strlcpy(user, "rootd", sizeof(user));
04592       }
04593    }
04594 
04595    if ((pw = getpwnam(user)) == 0) {
04596       NetSend(err, kROOTD_ERR);
04597       ErrorInfo("RpdUser: user %s unknown", user);
04598       return auth;
04599    }
04600 
04601    // If server is not started as root and user is not same as the
04602    // one who started rootd then authetication is not ok.
04603    uid_t uid = getuid();
04604    if (uid && uid != pw->pw_uid) {
04605       NetSend(kErrBadUser, kROOTD_ERR);
04606       ErrorInfo("RpdUser: user not same as effective user of rootd");
04607       return auth;
04608    }
04609 
04610    // Check if the administrator allows authentication
04611    char cuid[20];
04612    SPrintf(cuid, 20, "%d", (int)pw->pw_uid);
04613    if (gUserIgnLen[0] > 0 && strstr(gUserIgnore[0], cuid) != 0) {
04614       NetSend(kErrNotAllowed, kROOTD_ERR);
04615       ErrorInfo
04616           ("RpdUser: user (%d,%s) not authorized to use UsrPwd method",
04617            uid, pw->pw_name);
04618       return auth;
04619    }
04620    if (gUserAlwLen[0] > 0 && strstr(gUserAllow[0], cuid) == 0) {
04621       NetSend(kErrNotAllowed, kROOTD_ERR);
04622       ErrorInfo
04623           ("RpdUser: user (%d,%s) not authorized to use UsrPwd method",
04624            uid, pw->pw_name);
04625       return auth;
04626    }
04627 
04628    // Check /etc/hosts.equiv and/or $HOME/.rhosts
04629    int errheq = 0;
04630    if (gCheckHostsEquiv && strlen(ruser)) {
04631       if (RpdCheckHostsEquiv(gOpenHost.c_str(),ruser,user,errheq)) {
04632          auth = 3;
04633          strlcpy(gUser, user, sizeof(gUser));
04634          return auth;
04635       }
04636    }
04637 
04638    // Check if of type anonymous ...
04639    if (!strcmp(pw->pw_shell, "/bin/false")) {
04640       err = kErrNoAnon;
04641       gAnon = 1;
04642       gReUseRequired = 0;
04643    }
04644 
04645    // Check if authorized
04646    // If not anonymous, try to get passwd
04647    // (if our system uses shadow passwds and we are not superuser
04648    // we cannot authenticate users ...)
04649    //   char *passw = 0;
04650    gPasswd[0] = 0;
04651    char *passw = gPasswd;
04652    int errrdp = 0;
04653    if (gAnon == 0) {
04654 
04655       // Check ROOT specific passwd first
04656       int rcsp = RpdRetrieveSpecialPass(user,gRootdPass.c_str(),
04657                                         gPasswd,sizeof(gPasswd));
04658       if (rcsp < 0)
04659          errrdp = (rcsp == -2) ? 3 : 0;
04660 
04661       if (strlen(passw) == 0 || !strcmp(passw, "x")) {
04662 #ifdef R__AFS
04663          gSaltRequired = 0;
04664 #else
04665 
04666 #ifdef R__SHADOWPW
04667          struct spwd *spw = 0;
04668          // System V Rel 4 style shadow passwords
04669          if ((spw = getspnam(user)) == 0) {
04670             if (gDebug > 0) {
04671                ErrorInfo("RpdUser: Shadow passwd not accessible for user %s",user);
04672                ErrorInfo("RpdUser: trying normal system passwd");
04673             }
04674          } else
04675             passw = spw->sp_pwdp;
04676 #else
04677          passw = pw->pw_passwd;
04678 #endif
04679          // Check if successful
04680          if (strlen(passw) == 0 || !strcmp(passw, "x")) {
04681             if (gClientProtocol > 11)
04682                NetSend(gUsrPwdErr[errrdp][errheq], kROOTD_ERR);
04683             else
04684                NetSend(kErrNotAllowed, kROOTD_ERR);
04685             ErrorInfo("RpdUser: passwd hash not available for user %s", user);
04686             ErrorInfo
04687                 ("RpdUser: user %s cannot be authenticated with this method",
04688                  user);
04689             return auth;
04690          }
04691 #endif
04692       }
04693    }
04694    // Ok: Save username and go to next steps
04695    strlcpy(gUser, user, sizeof(gUser));
04696 
04697    // Salt vars
04698    char salt[30] = { 0 };
04699    char ctag[11] = { 0 };
04700    int  rtag = 0;
04701    int lenS = 0;
04702 
04703    if (gClientProtocol > 8) {
04704 
04705       // Prepare status flag to send back
04706       if (gAnon == 1) {
04707          // Anonymous user: we will receive a text pass in the form
04708          // user@remote.host.dom
04709          NetSend(-1, kROOTD_AUTH);
04710 
04711       } else {
04712 
04713          if (gCryptRequired) {
04714             // Named user: first we receive a session public key
04715             // Ask for the RSA key
04716             NetSend(gRSAKey, kROOTD_RSAKEY);
04717 
04718             // Receive the key securely
04719             if (RpdRecvClientRSAKey()) {
04720                ErrorInfo("RpdUser: could not import a valid key -"
04721                          " switch off reuse for this session");
04722                gReUseRequired = 0;
04723             }
04724 
04725             // We get a random tag
04726             if (gClientProtocol > 11) {
04727                RpdInitRand();
04728                rtag = rpd_rand();
04729                SPrintf(ctag, 11, "#%08x#",rtag);
04730             }
04731 
04732             if (gSaltRequired) {
04733                // The crypt man page says that alternative salts can be in the form '$1$...$';
04734                // but on Ubuntu 10.04 the salt are in the form '$j$...$' where j is 6 or other. 
04735                if (passw[0] == '$' && passw[2] == '$') {
04736                   // Shadow passwd
04737                   char *pd = strstr(passw + 4, "$");
04738                   lenS = (int) (pd - passw);
04739                   strncpy(salt, passw, lenS);
04740                   salt[lenS] = 0;
04741                } else {
04742                   lenS = 2;
04743                   strncpy(salt, passw, lenS);
04744                   salt[lenS] = 0;
04745                }
04746                if (gDebug > 2)
04747                   ErrorInfo("RpdUser: salt: '%s' ",salt);
04748 
04749                // We add the random tag here
04750                if (gClientProtocol > 11) {
04751                   strncpy(&salt[lenS],ctag,10);
04752                   salt[lenS+10] = 0;
04753                }
04754 
04755                // Send it over encrypted
04756                if (RpdSecureSend(salt) == -1) {
04757                   ErrorInfo("RpdUser: problems secure-sending salt -"
04758                             " may result in corrupted salt");
04759                }
04760             } else {
04761                if (gClientProtocol > 11) {
04762                   // We send the random tag here
04763                   if (RpdSecureSend(ctag) == -1) {
04764                      ErrorInfo("RpdUser: problems secure-sending rndmtag -"
04765                                " may result in corrupted rndmtag");
04766                   }
04767                } else
04768                   NetSend(0, kMESS_ANY);
04769             }
04770          } else {
04771             // We continue the authentication process in clear
04772             NetSend(0, kROOTD_AUTH);
04773          }
04774       }
04775 
04776    } else {
04777       // If we are talking to a old client protocol
04778       NetSend(0, kROOTD_AUTH);
04779    }
04780 
04781    // Get the password hash or anonymous string
04782    if (NetRecv(recvbuf, kMaxBuf, kind) < 0) {
04783       NetSend(kErrFatal, kROOTD_ERR);
04784       ErrorInfo("RpdUser: error receiving message");
04785       return auth;
04786    }
04787    if (kind != kROOTD_PASS) {
04788       NetSend(kErrFatal, kROOTD_ERR);
04789       ErrorInfo("RpdUser: received wrong message type: %d (expecting: %d)",
04790                 kind, (int) kROOTD_PASS);
04791       return auth;
04792    }
04793    if (!strncmp(recvbuf,"-1",2)) {
04794       if (gDebug > 0)
04795          ErrorInfo("RpdUser: client did not send a password - return");
04796       return auth;
04797    }
04798    // Get passwd
04799    char *passwd = 0;
04800    int lpwd = 0;
04801    if (gAnon == 0 && gClientProtocol > 8 && gCryptRequired) {
04802 
04803       // Receive encrypted pass or its hash
04804       if (RpdSecureRecv(&passwd) == -1) {
04805          ErrorInfo
04806              ("RpdUser: problems secure-receiving pass hash - %s",
04807               "may result in authentication failure");
04808       }
04809       // Length of the password buffer
04810       lpwd = strlen(passwd);
04811 
04812       // Check the random tag, if any
04813       if (strlen(ctag)) {
04814 
04815          // Check first that there is enough space for the tag
04816          int plen = lpwd;
04817          if (plen > 9 &&
04818              passwd[plen-1] == '#' && passwd[plen-10] == '#') {
04819             if (strncmp(ctag,&passwd[plen-10],10)) {
04820                // The tag does not match; failure
04821                if (gClientProtocol > 11)
04822                   NetSend(gUsrPwdErr[2][errheq], kROOTD_ERR);
04823                else
04824                   NetSend(kErrBadPasswd, kROOTD_ERR);
04825                ErrorInfo("RpdUser: rndm tag mis-match"
04826                          " (%s vs %s) - Failure",&passwd[plen-10],ctag);
04827                delete[] passwd;
04828                return auth;
04829             }
04830 
04831             // Tag ok: drop it
04832             plen -= 10;
04833             passwd[plen] = 0;
04834 
04835          } else {
04836             // The tag is not there or incomplete; failure
04837             if (gClientProtocol > 11)
04838                NetSend(gUsrPwdErr[2][errheq], kROOTD_ERR);
04839             else
04840                NetSend(kErrBadPasswd, kROOTD_ERR);
04841             ErrorInfo("RpdUser: rndm tag missing or incomplete"
04842                       " (pw length: %d) - Failure", plen);
04843             delete[] passwd;
04844             return auth;
04845          }
04846       }
04847 
04848       // If we required an hash check that we got it
04849       // (the client sends the passwd if the crypt version is different)
04850       if (gSaltRequired && lenS) {
04851          if (strncmp(passwd,salt,lenS))
04852             gSaltRequired = 0;
04853       }
04854 
04855    } else {
04856 
04857       // Receive clear or anonymous pass
04858       passwd = new char[strlen(recvbuf) + 1];
04859 
04860       // Re-invert pass
04861       int i, n = strlen(recvbuf);
04862       for (i = 0; i < n; i++)
04863          passwd[i] = ~recvbuf[i];
04864       passwd[i] = '\0';
04865 
04866       if (gDebug > 2 && gAnon)
04867          ErrorInfo("RpdUser: received anonymous pass: '%s'", passwd);
04868    }
04869 
04870    // Check the passwd and login if ok ...
04871    auth = RpdPass(passwd,errheq);
04872 
04873    // Erase memory used for password
04874    passwd = (char *)rpdmemset((volatile void *)passwd,0,lpwd);
04875    delete[] passwd;
04876 
04877    return auth;
04878 }
04879 
04880 //______________________________________________________________________________
04881 int RpdGuessClientProt(const char *buf, EMessageTypes kind)
04882 {
04883    // Try a guess of the client protocol from what she/he sent over
04884    // the net ...
04885 
04886    if (gDebug > 2)
04887       ErrorInfo("RpdGuessClientProt: Enter: buf: '%s', kind: %d", buf,
04888                 (int) kind);
04889 
04890    // Assume same version as us.
04891    int proto = 9;
04892 
04893    // Clear authentication
04894    if (kind == kROOTD_USER) {
04895       char usr[64], rest[256];
04896       int ns = sscanf(buf, "%63s %255s", usr, rest);
04897       if (ns == 1)
04898          proto = 8;
04899    }
04900    // SRP authentication
04901    if (kind == kROOTD_SRPUSER) {
04902       char usr[64], rest[256];
04903       int ns = sscanf(buf, "%63s %255s", usr, rest);
04904       if (ns == 1)
04905          proto = 8;
04906    }
04907    // Kerberos authentication
04908    if (kind == kROOTD_KRB5) {
04909       if (strlen(buf) == 0)
04910          proto = 8;
04911    }
04912 
04913    if (gDebug > 2)
04914       ErrorInfo("RpdGuessClientProt: guess for gClientProtocol is %d",
04915                 proto);
04916 
04917    // Return the guess
04918    return proto;
04919 }
04920 
04921 //______________________________________________________________________________
04922 char *RpdGetRandString(int Opt, int Len)
04923 {
04924    // Allocates and Fills a NULL terminated buffer of length Len+1 with
04925    // Len random characters.
04926    // Return pointer to the buffer (to be deleted by the caller)
04927    // Opt = 0      any non dangerous char
04928    //       1      letters and numbers  (upper and lower case)
04929    //       2      hex characters       (upper and lower case)
04930    //       3      crypt like           [a-zA-Z0-9./]
04931 
04932    int iimx[4][4] = { { 0x0, 0xffffff08, 0xafffffff, 0x2ffffffe }, // Opt = 0
04933                       { 0x0, 0x3ff0000,  0x7fffffe,  0x7fffffe },  // Opt = 1
04934                       { 0x0, 0x3ff0000,  0x7e,       0x7e },       // Opt = 2
04935                       { 0x0, 0x3ffc000,  0x7fffffe,  0x7fffffe }   // Opt = 3
04936    };
04937 
04938    const char *cOpt[4] = { "Any", "LetNum", "Hex", "Crypt" };
04939 
04940    //  Default option 0
04941    if (Opt < 0 || Opt > 3) {
04942       Opt = 0;
04943       if (gDebug > 2)
04944          ErrorInfo("RpdGetRandString: Unknown option: %d : assume 0", Opt);
04945    }
04946    if (gDebug > 2)
04947       ErrorInfo("RpdGetRandString: Enter ... Len: %d %s", Len, cOpt[Opt]);
04948 
04949    // Allocate buffer
04950    char *buf = new char[Len + 1];
04951 
04952    // Init Random machinery ...
04953    if (!gRandInit)
04954       RpdInitRand();
04955 
04956    // randomize
04957    int k = 0;
04958    int i, j, l, m, frnd;
04959    while (k < Len) {
04960       frnd = rpd_rand();
04961       for (m = 7; m < 32; m += 7) {
04962          i = 0x7F & (frnd >> m);
04963          j = i / 32;
04964          l = i - j * 32;
04965          if ((iimx[Opt][j] & (1 << l))) {
04966             buf[k] = i;
04967             k++;
04968          }
04969          if (k == Len)
04970             break;
04971       }
04972    }
04973 
04974    // NULL terminated
04975    buf[Len] = 0;
04976    if (gDebug > 2)
04977       ErrorInfo("RpdGetRandString: got '%s' ", buf);
04978 
04979    return buf;
04980 }
04981 
04982 //______________________________________________________________________________
04983 int RpdGetRSAKeys(const char *pubkey, int Opt)
04984 {
04985    // Get public key from file pubkey (Opt == 1) or string pubkey (Opt == 0).
04986 
04987    char str[kMAXPATHLEN] = { 0 };
04988    int keytype = 0;
04989 
04990    if (gDebug > 2)
04991       ErrorInfo("RpdGetRSAKeys: enter: string len: %d, opt %d ",
04992                  gPubKeyLen, Opt);
04993 
04994    if (!pubkey)
04995       return keytype;
04996 
04997    char *theKey = 0;
04998    FILE *fKey = 0;
04999    // Parse input type
05000    if (Opt == 1) {
05001 
05002       // Ok, now open it
05003       fKey = fopen(pubkey, "r");
05004       if (!fKey) {
05005          if (GetErrno() == EACCES) {
05006             struct passwd *pw = getpwuid(getuid());
05007             char *usr = 0;
05008             if (pw)
05009                usr = pw->pw_name;
05010             ErrorInfo("RpdGetRSAKeys: access to key file %s denied"
05011                       " to user: %s", pubkey, (usr ? usr : (char *)"????"));
05012          } else
05013             ErrorInfo("RpdGetRSAKeys: cannot open key file"
05014                       " %s (errno: %d)", pubkey, GetErrno());
05015          return 0;
05016       }
05017       // Check first the permissions: should be 0600
05018       struct stat st;
05019       if (fstat(fileno(fKey), &st) == -1) {
05020          ErrorInfo("RpdGetRSAKeys: cannot stat descriptor %d"
05021                    " %s (errno: %d)", fileno(fKey), GetErrno());
05022          fclose(fKey);
05023          return 0;
05024       }
05025       if (!S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) ||
05026           (st.st_mode & 0777) != (S_IRUSR | S_IWUSR)) {
05027          ErrorInfo("RpdGetRSAKeys: key file %s: wrong permissions"
05028                    " 0%o (should be 0600)", pubkey, (st.st_mode & 0777));
05029          fclose(fKey);
05030          return 0;
05031       }
05032       gPubKeyLen = fread((void *)str,1,sizeof(str),fKey);
05033       if (gDebug > 2)
05034          ErrorInfo("RpdGetRSAKeys: length of the read key: %d",gPubKeyLen);
05035 
05036       // This the key
05037       theKey = str;
05038    } else {
05039       // the key is the argument
05040       theKey = (char *)pubkey;
05041    }
05042 
05043    if (gPubKeyLen > 0) {
05044 
05045       // Skip spaces at beginning, if any
05046       int k = 0;
05047       while (theKey[k] == 32) k++;
05048 
05049       keytype = gRSAKey;
05050 
05051       // The format of keytype 1 is #<hex_n>#<hex_d>#
05052       char *pd1 = 0, *pd2 = 0, *pd3 = 0;
05053       pd1 = strstr(theKey, "#");
05054       if (pd1) pd2 = strstr(pd1 + 1, "#");
05055       if (pd2) pd3 = strstr(pd2 + 1, "#");
05056       if (keytype == 1) {
05057          if (!pd1 || !pd2 || !pd3) {
05058             if (gDebug > 0)
05059                ErrorInfo("RpdGetRSAKeys: bad format for keytype %d"
05060                          " - exit", keytype);
05061             keytype = 0;
05062          }
05063       }
05064       if (keytype == 1) {
05065 
05066          if (gDebug > 2)
05067             ErrorInfo("RpdGetRSAKeys: keytype %d ", keytype);
05068 
05069          // Get <hex_n> ...
05070          int l1 = (int) (pd2 - pd1 - 1);
05071          char *n_exp_RSA = new char[l1 + 1];
05072          strncpy(n_exp_RSA, pd1 + 1, l1);
05073          n_exp_RSA[l1] = 0;
05074          if (gDebug > 2)
05075             ErrorInfo("RpdGetRSAKeys: got %d bytes for n_exp_RSA",
05076                       strlen(n_exp_RSA));
05077          // Now <hex_d>
05078          int l2 = (int) (pd3 - pd2 - 1);
05079          char *d_exp_RSA = new char[l2 + 1];
05080          strncpy(d_exp_RSA, pd2 + 1, l2);
05081          d_exp_RSA[l2] = 0;
05082          if (gDebug > 2)
05083             ErrorInfo("RpdGetRSAKeys: got %d bytes for d_exp_RSA",
05084                       strlen(d_exp_RSA));
05085 
05086          rsa_num_sget(&gRSA_n, n_exp_RSA);
05087          rsa_num_sget(&gRSA_d, d_exp_RSA);
05088 
05089          delete[] n_exp_RSA;
05090          delete[] d_exp_RSA;
05091 
05092       } else if (keytype == 2){
05093 
05094 #ifdef R__SSL
05095          // try SSL
05096          if (gDebug > 2)
05097             ErrorInfo("RpdGetRSAKeys: keytype %d ", keytype);
05098 
05099          // Now set the key locally in BF form
05100          BF_set_key(&gBFKey, gPubKeyLen, (const unsigned char *)theKey);
05101 #else
05102          if (gDebug > 0) {
05103             ErrorInfo("RpdGetRSAKeys: not compiled with SSL support:"
05104                    " you should not have got here!");
05105          }
05106 #endif
05107       }
05108    }
05109 
05110    if (fKey)
05111       fclose(fKey);
05112 
05113    return keytype;
05114 }
05115 
05116 //______________________________________________________________________________
05117 int RpdSavePubKey(const char *PubKey, int OffSet, char *user)
05118 {
05119    // Save RSA public key into file for later use by other rootd/proofd.
05120    // Return: 0 if ok
05121    //         1 if not ok
05122    //         2 if not ok because file already exists and cannot be
05123    //           overwritten
05124 
05125    int retval = 0;
05126 
05127    if (gRSAKey == 0 || OffSet < 0)
05128       return 1;
05129 
05130    std::string pukfile = gRpdKeyRoot;
05131    pukfile.append(ItoA(OffSet));
05132 
05133    // Unlink the file first
05134    if (unlink(pukfile.c_str()) == -1) {
05135       if (GetErrno() != ENOENT)
05136          // File exists and cannot overwritten by this process
05137          return 2;
05138    }
05139 
05140    // Create file
05141    int ipuk = -1;
05142    ipuk = open(pukfile.c_str(), O_WRONLY | O_CREAT, 0600);
05143    if (ipuk == -1) {
05144       ErrorInfo("RpdSavePubKey: cannot open file %s (errno: %d)",
05145                 pukfile.c_str(),GetErrno());
05146       if (GetErrno() == ENOENT)
05147          return 2;
05148       else
05149          return 1;
05150    }
05151 
05152    // If root process set ownership of the pub key to the user
05153    if (getuid() == 0) {
05154       struct passwd *pw = getpwnam(user);
05155       if (pw) {
05156          if (fchown(ipuk,pw->pw_uid,pw->pw_gid) == -1) {
05157             ErrorInfo("RpdSavePubKey: cannot change ownership"
05158                       " of %s (errno: %d)",pukfile.c_str(),GetErrno());
05159             retval = 1;
05160          }
05161       } else {
05162          ErrorInfo("RpdSavePubKey: getpwnam failure (errno: %d)",GetErrno());
05163          retval = 1;
05164       }
05165    }
05166 
05167    // Write the key if no error occured
05168    if (retval == 0) {
05169       while (write(ipuk, PubKey, gPubKeyLen) < 0 && GetErrno() == EINTR)
05170          ResetErrno();
05171    }
05172 
05173    // close the file
05174    close(ipuk);
05175 
05176    // Over
05177    return retval;
05178 }
05179 
05180 //______________________________________________________________________________
05181 int RpdSecureSend(char *str)
05182 {
05183    // Encode null terminated str using the session private key indcated by Key
05184    // and sends it over the network.
05185    // Returns number of bytes sent.or -1 in case of error.
05186 
05187    char buftmp[kMAXSECBUF];
05188    char buflen[20];
05189 
05190    int slen = strlen(str) + 1;
05191 
05192    int ttmp = 0;
05193    int nsen = -1;
05194 
05195    if (gRSAKey == 1) {
05196       strncpy(buftmp, str, slen);
05197       buftmp[slen] = 0;
05198       ttmp = rsa_encode(buftmp, slen, gRSA_n, gRSA_d);
05199    } else if (gRSAKey == 2) {
05200 #ifdef R__SSL
05201       ttmp = strlen(str);
05202       if ((ttmp % 8) > 0)            // It should be a multiple of 8!
05203          ttmp = ((ttmp + 8)/8) * 8;
05204       unsigned char iv[8];
05205       memset((void *)&iv[0],0,8);
05206       BF_cbc_encrypt((const unsigned char *)str, (unsigned char *)buftmp,
05207                      strlen(str), &gBFKey, iv, BF_ENCRYPT);
05208 #else
05209       ErrorInfo("RpdSecureSend: Not compiled with SSL support:"
05210                 " you should not have got here! - return");
05211 #endif
05212    } else {
05213       ErrorInfo("RpdSecureSend: Unknown key option (%d) - return",
05214                 gRSAKey);
05215    }
05216 
05217    // Send the buffer now
05218    SPrintf(buflen, 20, "%d", ttmp);
05219    NetSend(buflen, kROOTD_ENCRYPT);
05220    nsen = NetSendRaw(buftmp, ttmp);
05221    if (gDebug > 4)
05222       ErrorInfo("RpdSecureSend: sent %d bytes (expected: %d) - keytype: %d",
05223                  nsen, ttmp, gRSAKey);
05224 
05225    return nsen;
05226 }
05227 
05228 //______________________________________________________________________________
05229 int RpdSecureRecv(char **str)
05230 {
05231    // Receive buffer and decode it in str using key indicated by Key type.
05232    // Return number of received bytes or -1 in case of error.
05233 
05234    char buftmp[kMAXSECBUF];
05235    char buflen[20];
05236 
05237    int nrec = -1;
05238    // We must get a pointer ...
05239    if (!str)
05240       return nrec;
05241 
05242    if (gDebug > 2)
05243       ErrorInfo("RpdSecureRecv: enter ... (key is %d)", gRSAKey);
05244 
05245    EMessageTypes kind;
05246    NetRecv(buflen, 20, kind);
05247    int len = atoi(buflen);
05248    if (gDebug > 4)
05249       ErrorInfo("RpdSecureRecv: got len '%s' %d ", buflen, len);
05250    if (!strncmp(buflen, "-1", 2))
05251       return nrec;
05252 
05253    // receive the buffer
05254    nrec = NetRecvRaw(buftmp,len);
05255 
05256    // decode it
05257    if (gRSAKey == 1) {
05258       rsa_decode(buftmp, len, gRSA_n, gRSA_d);
05259       if (gDebug > 2)
05260          ErrorInfo("RpdSecureRecv: Local: decoded string is %d bytes long",
05261                    strlen(buftmp));
05262 
05263       // Prepare output
05264       *str = new char[strlen(buftmp) + 1];
05265       strlcpy(*str, buftmp, strlen(buftmp)+1);
05266    } else if (gRSAKey == 2) {
05267 #ifdef R__SSL
05268       unsigned char iv[8];
05269       memset((void *)&iv[0],0,8);
05270       *str = new char[nrec + 1];
05271       BF_cbc_encrypt((const unsigned char *)buftmp, (unsigned char *)(*str),
05272                       nrec, &gBFKey, iv, BF_DECRYPT);
05273       (*str)[nrec] = '\0';
05274 #else
05275       ErrorInfo("RpdSecureRecv: Not compiled with SSL support:"
05276                 " you should not have got here! - return");
05277 #endif
05278    } else {
05279       ErrorInfo("RpdSecureRecv: Unknown key option (%d) - return",
05280                 gRSAKey);
05281    }
05282 
05283    return nrec;
05284 }
05285 
05286 //______________________________________________________________________________
05287 int RpdGenRSAKeys(int setrndinit)
05288 {
05289    // Generate a valid pair of private/public RSA keys to protect for
05290    // authentication password and token exchange
05291    // Returns 1 if a good key pair is not found after kMAXRSATRIES attempts
05292    // Returns 0 if a good key pair is found
05293    // If setrndinit = 1, no futher init of the random engine
05294 
05295    if (gDebug > 2)
05296       ErrorInfo("RpdGenRSAKeys: enter");
05297 
05298    // Init Random machinery ...
05299    if (!gRandInit)
05300       RpdInitRand();
05301    gRandInit = setrndinit;
05302 
05303 #ifdef R__NOCRYPT
05304    // Generate a random salt
05305    char *rsalt = RpdGetRandString(3,8);
05306    if (rsalt) {
05307       gRndmSalt = std::string(rsalt);
05308       delete[] rsalt;
05309    } else {
05310       if (gDebug > 0)
05311          ErrorInfo("RpdGenRSAKeys: could not generate random salt");
05312    }
05313 #endif
05314 
05315 #ifdef R__SSL
05316    // Generate also the SSL key
05317    if (gDebug > 2)
05318       ErrorInfo("RpdGenRSAKeys: Generate RSA SSL keys");
05319 
05320    // Init SSL ...
05321    SSL_library_init();
05322 
05323    //  ... and its error strings
05324    SSL_load_error_strings();
05325 
05326    // Load Ciphers
05327    OpenSSL_add_all_ciphers();
05328 
05329    // Number of bits for key
05330    Int_t nbits = 1024;
05331 
05332    // Public exponent
05333    Int_t pubex = 17;
05334 
05335    // Init random engine
05336    char *rbuf = RpdGetRandString(0,40);
05337    RAND_seed(rbuf,strlen(rbuf));
05338 
05339    // Generate Key
05340    gRSASSLKey = RSA_generate_key(nbits,pubex,0,0);
05341 
05342    // Bio for exporting the pub key
05343    BIO *bkey = BIO_new(BIO_s_mem());
05344 
05345    // Write public key to BIO
05346    PEM_write_bio_RSAPublicKey(bkey,gRSASSLKey);
05347 
05348    // Read key from BIO to buf
05349    Int_t sbuf = 2*RSA_size(gRSASSLKey);
05350    char *kbuf = new char[sbuf];
05351    BIO_read(bkey,(void *)kbuf,sbuf);
05352    BIO_free(bkey);
05353 
05354    // Prepare export
05355    gRSAPubExport[1].len = sbuf;
05356    gRSAPubExport[1].keys = new char[gRSAPubExport[1].len + 2];
05357    strncpy(gRSAPubExport[1].keys,kbuf,gRSAPubExport[1].len);
05358    gRSAPubExport[1].keys[gRSAPubExport[1].len-1] = '\0';
05359    delete[] kbuf;
05360    if (gDebug > 2)
05361       ErrorInfo("RpdGenRSAKeys: SSL: export pub:\n%.*s",
05362            gRSAPubExport[1].len,gRSAPubExport[1].keys);
05363 
05364    // We have at least one key
05365    gRSAInit = 1;
05366 
05367 #endif
05368 
05369    // Sometimes some bunch is not decrypted correctly
05370    // That's why we make retries to make sure that encryption/decryption
05371    // works as expected
05372    bool notOK = 1;
05373    rsa_NUMBER p1, p2, rsa_n, rsa_e, rsa_d;
05374    int l_n = 0, l_e = 0, l_d = 0;
05375 #if R__RSADEB
05376    char buf[rsa_STRLEN];
05377 #endif
05378    char buf_n[rsa_STRLEN], buf_e[rsa_STRLEN], buf_d[rsa_STRLEN];
05379 
05380    int nAttempts = 0;
05381    int thePrimeLen = kPRIMELENGTH;
05382    int thePrimeExp = kPRIMEEXP + 5;   // Prime probability = 1-0.5^thePrimeExp
05383    while (notOK && nAttempts < kMAXRSATRIES) {
05384 
05385       nAttempts++;
05386       if (gDebug > 2 && nAttempts > 1) {
05387             ErrorInfo("RpdGenRSAKeys: retry no. %d",nAttempts);
05388          srand(rpd_rand());
05389       }
05390 
05391       // Valid pair of primes
05392       p1 = rsa_genprim(thePrimeLen, thePrimeExp);
05393       p2 = rsa_genprim(thePrimeLen+1, thePrimeExp);
05394 
05395       // Retry if equal
05396       int nPrimes = 0;
05397       while (rsa_cmp(&p1, &p2) == 0 && nPrimes < kMAXRSATRIES) {
05398          nPrimes++;
05399          if (gDebug > 2)
05400             ErrorInfo("RpdGenRSAKeys: equal primes: regenerate (%d times)",nPrimes);
05401          srand(rpd_rand());
05402          p1 = rsa_genprim(thePrimeLen, thePrimeExp);
05403          p2 = rsa_genprim(thePrimeLen+1, thePrimeExp);
05404       }
05405 
05406 #if R__RSADEB
05407       if (gDebug > 2) {
05408          rsa_num_sput(&p1, buf, rsa_STRLEN);
05409          ErrorInfo("RpdGenRSAKeys: local: p1: '%s' ", buf);
05410          rsa_num_sput(&p2, buf, rsa_STRLEN);
05411          ErrorInfo("RpdGenRSAKeys: local: p2: '%s' ", buf);
05412       }
05413 #endif
05414 
05415       // Generate keys
05416       if (rsa_genrsa(p1, p2, &rsa_n, &rsa_e, &rsa_d)) {
05417          if (gDebug > 0)
05418             ErrorInfo("RpdGenRSAKeys: genrsa: attempt %d to generate"
05419                       " keys failed",nAttempts);
05420          continue;
05421       }
05422 
05423       // Determine their lengths
05424       rsa_num_sput(&rsa_n, buf_n, rsa_STRLEN);
05425       l_n = strlen(buf_n);
05426       rsa_num_sput(&rsa_e, buf_e, rsa_STRLEN);
05427       l_e = strlen(buf_e);
05428       rsa_num_sput(&rsa_d, buf_d, rsa_STRLEN);
05429       l_d = strlen(buf_d);
05430 
05431 #if R__RSADEB
05432       if (gDebug > 2) {
05433          ErrorInfo("RpdGenRSAKeys: local: n: '%s' length: %d", buf_n, l_n);
05434          ErrorInfo("RpdGenRSAKeys: local: e: '%s' length: %d", buf_e, l_e);
05435          ErrorInfo("RpdGenRSAKeys: local: d: '%s' length: %d", buf_d, l_d);
05436       }
05437 #endif
05438       if (rsa_cmp(&rsa_n, &rsa_e) <= 0)
05439          continue;
05440       if (rsa_cmp(&rsa_n, &rsa_d) <= 0)
05441          continue;
05442 
05443       // Now we try the keys
05444       char test[2 * rsa_STRLEN] = "ThisIsTheStringTest01203456-+/";
05445       Int_t lTes = 31;
05446       char *dumT = RpdGetRandString(0, lTes - 1);
05447       strncpy(test, dumT, lTes);
05448       delete[]dumT;
05449       char buf[2 * rsa_STRLEN];
05450       if (gDebug > 3)
05451          ErrorInfo("RpdGenRSAKeys: local: test string: '%s' ", test);
05452 
05453       // Private/Public
05454       strncpy(buf, test, lTes);
05455       buf[lTes] = 0;
05456 
05457       // Try encryption with private key
05458       int lout = rsa_encode(buf, lTes, rsa_n, rsa_e);
05459       if (gDebug > 3)
05460          ErrorInfo("GenRSAKeys: local: length of crypted string: %d bytes", lout);
05461 
05462       // Try decryption with public key
05463       rsa_decode(buf, lout, rsa_n, rsa_d);
05464       buf[lTes] = 0;
05465       if (gDebug > 3)
05466          ErrorInfo("RpdGenRSAKeys: local: after private/public : '%s' ", buf);
05467 
05468       if (strncmp(test, buf, lTes))
05469          continue;
05470 
05471       // Public/Private
05472       strncpy(buf, test, lTes);
05473       buf[lTes] = 0;
05474 
05475       // Try encryption with public key
05476       lout = rsa_encode(buf, lTes, rsa_n, rsa_d);
05477       if (gDebug > 3)
05478          ErrorInfo("RpdGenRSAKeys: local: length of crypted string: %d bytes ",
05479               lout);
05480 
05481       // Try decryption with private key
05482       rsa_decode(buf, lout, rsa_n, rsa_e);
05483       buf[lTes] = 0;
05484       if (gDebug > 3)
05485          ErrorInfo("RpdGenRSAKeys: local: after public/private : '%s' ", buf);
05486 
05487       if (strncmp(test, buf, lTes))
05488          continue;
05489 
05490       notOK = 0;
05491    }
05492 
05493    if (notOK) {
05494       ErrorInfo("RpdGenRSAKeys: unable to generate good RSA key pair"
05495                 " (%d attempts)- return",kMAXRSATRIES);
05496       return 1;
05497    }
05498 
05499    // Save Private key
05500    rsa_assign(&gRSAPriKey.n, &rsa_n);
05501    rsa_assign(&gRSAPriKey.e, &rsa_e);
05502 
05503    // Save Public key
05504    rsa_assign(&gRSAPubKey.n, &rsa_n);
05505    rsa_assign(&gRSAPubKey.e, &rsa_d);
05506 
05507 #if R__RSADEB
05508    if (gDebug > 2) {
05509       // Determine their lengths
05510       ErrorInfo("RpdGenRSAKeys: local: generated keys are:");
05511       ErrorInfo("RpdGenRSAKeys: local: n: '%s' length: %d", buf_n, l_n);
05512       ErrorInfo("RpdGenRSAKeys: local: e: '%s' length: %d", buf_e, l_e);
05513       ErrorInfo("RpdGenRSAKeys: local: d: '%s' length: %d", buf_d, l_d);
05514    }
05515 #endif
05516    // Export form
05517    gRSAPubExport[0].len = l_n + l_d + 4;
05518    if (gRSAPubExport[0].keys)
05519       delete[] gRSAPubExport[0].keys;
05520    gRSAPubExport[0].keys = new char[gRSAPubExport[0].len];
05521 
05522    gRSAPubExport[0].keys[0] = '#';
05523    memcpy(gRSAPubExport[0].keys + 1, buf_n, l_n);
05524    gRSAPubExport[0].keys[l_n + 1] = '#';
05525    memcpy(gRSAPubExport[0].keys + l_n + 2, buf_d, l_d);
05526    gRSAPubExport[0].keys[l_n + l_d + 2] = '#';
05527    gRSAPubExport[0].keys[l_n + l_d + 3] = 0;
05528 #if R__RSADEB
05529    if (gDebug > 2)
05530       ErrorInfo("RpdGenRSAKeys: local: export pub: '%s'",
05531                 gRSAPubExport[0].keys);
05532 #else
05533    if (gDebug > 2)
05534       ErrorInfo("RpdGenRSAKeys: local: export pub length: %d bytes",
05535                 gRSAPubExport[0].len);
05536 #endif
05537 
05538    gRSAInit = 1;
05539    return 0;
05540 }
05541 
05542 //______________________________________________________________________________
05543 int RpdRecvClientRSAKey()
05544 {
05545    // Generates local public/private RSA key pair
05546    // Send request for Client Public Key and Local public key
05547    // Receive encoded Client Key
05548    // Decode Client public key
05549    // NB: key is not saved to file here
05550 
05551    if (gRSAInit == 0) {
05552       // Generate Local RSA keys for the session
05553       if (RpdGenRSAKeys(1)) {
05554          ErrorInfo("RpdRecvClientRSAKey: unable to generate local keys");
05555          return 1;
05556       }
05557    }
05558 
05559    // Send server public key
05560    int key = gRSAKey - 1;
05561    NetSend(gRSAPubExport[key].keys, gRSAPubExport[key].len, kROOTD_RSAKEY);
05562 
05563    // Receive length of message with encode client public key
05564    EMessageTypes kind;
05565    char buflen[40];
05566    NetRecv(buflen, 20, kind);
05567    gPubKeyLen = atoi(buflen);
05568    if (gDebug > 3)
05569       ErrorInfo("RpdRecvClientRSAKey: got len '%s' %d ", buflen, gPubKeyLen);
05570 
05571    int nrec = 0;
05572 
05573    if (gRSAKey == 1) {
05574 
05575       // Receive and decode encoded public key
05576       nrec = NetRecvRaw(gPubKey, gPubKeyLen);
05577 
05578       rsa_decode(gPubKey, gPubKeyLen, gRSAPriKey.n, gRSAPriKey.e);
05579       if (gDebug > 2)
05580          ErrorInfo("RpdRecvClientRSAKey: Local: decoded string is %d bytes long ",
05581             strlen(gPubKey));
05582       gPubKeyLen = strlen(gPubKey);
05583 
05584    } else if (gRSAKey == 2) {
05585 #ifdef R__SSL
05586       int ndec = 0;
05587       int lcmax = RSA_size(gRSASSLKey);
05588       char btmp[kMAXSECBUF];
05589       int nr = gPubKeyLen;
05590       int kd = 0;
05591       while (nr > 0) {
05592          // Receive and decode encoded public key
05593          nrec += NetRecvRaw(btmp, lcmax);
05594          if ((ndec = RSA_private_decrypt(lcmax,(unsigned char *)btmp,
05595                                     (unsigned char *)&gPubKey[kd],
05596                                     gRSASSLKey,
05597                                     RSA_PKCS1_PADDING)) < 0) {
05598             char cerr[120];
05599             ERR_error_string(ERR_get_error(), cerr);
05600             ErrorInfo("RpdRecvClientRSAKey: SSL: error: '%s' ",cerr);
05601          }
05602          nr -= lcmax;
05603          kd += ndec;
05604       }
05605       gPubKeyLen = kd;
05606 #else
05607       if (gDebug > 0)
05608          ErrorInfo("RpdRecvClientRSAKey: not compiled with SSL support"
05609                    ": you should not have got here!");
05610       return 1;
05611 #endif
05612    } else {
05613       if (gDebug > 0)
05614          ErrorInfo("RpdRecvClientRSAKey: unknown key type (%d)", gRSAKey);
05615    }
05616 
05617 
05618    // Import Key and Determine key type
05619    if (RpdGetRSAKeys(gPubKey, 0) != gRSAKey) {
05620       ErrorInfo("RpdRecvClientRSAKey:"
05621                 " could not import a valid key (type %d)",gRSAKey);
05622       char *elogfile = new char[gRpdKeyRoot.length() + 11];
05623       SPrintf(elogfile, gRpdKeyRoot.length() + 11, "%.*serr.XXXXXX", (int)gRpdKeyRoot.length(), gRpdKeyRoot.c_str());
05624       mode_t oldumask = umask(0700);
05625       int ielog = mkstemp(elogfile);
05626       umask(oldumask);
05627       if (ielog != -1) {
05628          char line[kMAXPATHLEN] = {0};
05629          //
05630          SPrintf(line,kMAXPATHLEN,
05631                  " + RpdRecvClientRSAKey: error importing key\n + type: %d\n"
05632                  " + length: %d\n + key: %s\n + (%d bytes were received)",
05633                  gRSAKey, gPubKeyLen, gPubKey, nrec);
05634          while (write(ielog, line, strlen(line)) < 0 && GetErrno() == EINTR)
05635             ResetErrno();
05636          close (ielog);
05637       }
05638       delete [] elogfile;
05639       return 2;
05640    }
05641 
05642    return 0;
05643 }
05644 
05645 //______________________________________________________________________________
05646 void RpdInitRand()
05647 {
05648    // Init random machine.
05649 
05650    const char *randdev = "/dev/urandom";
05651 
05652    int fd;
05653    unsigned int seed;
05654    if ((fd = open(randdev, O_RDONLY)) != -1) {
05655       if (gDebug > 2)
05656          ErrorInfo("RpdInitRand: taking seed from %s", randdev);
05657       if (read(fd, &seed, sizeof(seed))) {;}
05658       close(fd);
05659    } else {
05660       if (gDebug > 2)
05661          ErrorInfo("RpdInitRand: %s not available: using time()", randdev);
05662       seed = time(0);   //better use times() + win32 equivalent
05663    }
05664    srand(seed);
05665 }
05666 
05667 //______________________________________________________________________________
05668 int RpdAuthenticate()
05669 {
05670    // Handle user authentication.
05671    char buf[kMAXRECVBUF];
05672    EMessageTypes kind;
05673 
05674 //#define R__DEBUG
05675 #ifdef R__DEBUG
05676    int debug = 1;
05677    while (debug)
05678       ;
05679 #endif
05680 
05681    // Reset gAuth (if we have been called this means that we need
05682    // to check at least that a valid authentication exists ...)
05683    int auth = 0;
05684 
05685    while (!auth) {
05686 
05687       // Receive next
05688       if (!gClientOld) {
05689          if (NetRecv(buf, kMAXRECVBUF, kind) < 0) {
05690             Error(gErr, -1, "RpdAuthenticate: error receiving message");
05691             return auth;
05692          }
05693       } else {
05694          strlcpy(buf,gBufOld, sizeof(buf));
05695          kind = gKindOld;
05696          gBufOld[0] = '\0';
05697          gClientOld = 0;
05698       }
05699 
05700       // If this is a rootd contacted via a TXNetFile we need to
05701       // receive again the buffer
05702       if (gService == kROOTD && kind == kROOTD_PROTOCOL) {
05703          if (NetRecv(buf, kMAXRECVBUF, kind) < 0) {
05704             Error(gErr, -1, "RpdAuthenticate: error receiving message");
05705             return auth;
05706          }
05707       }
05708 
05709       // Decode the method ...
05710       gAuthProtocol = RpdGetAuthMethod(kind);
05711 
05712       if (gDebug > 2) {
05713          if (kind != kROOTD_PASS) {
05714             ErrorInfo("RpdAuthenticate got: %d -- %s", kind, buf);
05715          } else {
05716             ErrorInfo("RpdAuthenticate got: %d ", kind);
05717          }
05718       }
05719 
05720       // Guess the client procotol if not received via Rootd/ProofdProtocol
05721       if (gClientProtocol == 0)
05722          gClientProtocol = RpdGuessClientProt(buf, kind);
05723 
05724       // If the client supports it check if we accept the method proposed;
05725       // if not send back the list of accepted methods, if any ...
05726       if (gAuthProtocol != -1 && gClientProtocol > 8) {
05727 
05728          // Check if accepted ...
05729          if (RpdCheckAuthAllow(gAuthProtocol, gOpenHost.c_str())) {
05730             if (gNumAllow>0) {
05731                if (gAuthListSent == 0) {
05732                   if (gDebug > 0)
05733                      ErrorInfo("Authenticate: %s method not"
05734                                " accepted from host: %s",
05735                                 gAuthMeth[gAuthProtocol].c_str(),
05736                                 gOpenHost.c_str());
05737                   NetSend(kErrNotAllowed, kROOTD_ERR);
05738                   RpdSendAuthList();
05739                   gAuthListSent = 1;
05740                   goto next;
05741                } else {
05742                   Error(gErr,kErrNotAllowed,"Authenticate: method not"
05743                        " in the list sent to the client");
05744                   return auth;
05745                }
05746             } else {
05747                Error(gErr,kErrConnectionRefused,"Authenticate:"
05748                        " connection refused from host %s", gOpenHost.c_str());
05749                return auth;
05750             }
05751          }
05752 
05753          // Then check if a previous authentication exists and is valid
05754          // ReUse does not apply for RFIO
05755          if (kind != kROOTD_RFIO && (auth = RpdReUseAuth(buf, kind)))
05756             goto next;
05757       }
05758 
05759       // Reset global variable
05760       auth = 0;
05761 
05762       switch (kind) {
05763          case kROOTD_USER:
05764             auth = RpdUser(buf);
05765             break;
05766          case kROOTD_SRPUSER:
05767             auth = RpdSRPUser(buf);
05768             break;
05769          case kROOTD_PASS:
05770             auth = RpdPass(buf);
05771             break;
05772          case kROOTD_KRB5:
05773             auth = RpdKrb5Auth(buf);
05774             break;
05775          case kROOTD_GLOBUS:
05776             auth = RpdGlobusAuth(buf);
05777             break;
05778          case kROOTD_SSH:
05779             auth = RpdSshAuth(buf);
05780             break;
05781          case kROOTD_RFIO:
05782             auth = RpdRfioAuth(buf);
05783             break;
05784          case kROOTD_CLEANUP:
05785             RpdAuthCleanup(buf,1);
05786             ErrorInfo("RpdAuthenticate: authentication stuff cleaned - exit");
05787             // Fallthrough next case now to free the keys
05788          case kROOTD_BYE:
05789             RpdFreeKeys();
05790             return auth;
05791             break;
05792          default:
05793             Error(gErr,-1,"RpdAuthenticate: received bad opcode %d", kind);
05794             return auth;
05795       }
05796 
05797       if (gClientProtocol > 8) {
05798 
05799          // If failure prepare or continue negotiation
05800          // Don't do this if this was a SSH notification failure
05801          // because in such a case it was already done in the
05802          // appropriate daemon child
05803          int doneg = (gAuthProtocol != -1 || kind == kROOTD_PASS) &&
05804                      (gRemPid > 0 || kind != kROOTD_SSH);
05805          if (gDebug > 2 && doneg)
05806             ErrorInfo("RpdAuthenticate: kind:%d meth:%d auth:%d gNumLeft:%d",
05807                       kind, gAuthProtocol, auth, gNumLeft);
05808 
05809          // If authentication failure, check if other methods could be tried ...
05810          if (auth == 0 && doneg) {
05811             if (gNumLeft > 0) {
05812                if (gAuthListSent == 0) {
05813                   RpdSendAuthList();
05814                   gAuthListSent = 1;
05815                } else
05816                   NetSend(-1, kROOTD_NEGOTIA);
05817             } else {
05818                NetSend(0, kROOTD_NEGOTIA);
05819                Error(gErr, -1, "RpdAuthenticate: authentication failed");
05820                return auth;
05821             }
05822          }
05823       }
05824 next:
05825       continue;
05826    }
05827 
05828    return auth;
05829 }
05830 //______________________________________________________________________________
05831 void RpdFreeKeys()
05832 {
05833    // Free space allocated for encryption keys
05834 
05835    if (gRSAPubExport[0].keys) delete[] gRSAPubExport[0].keys;
05836    if (gRSAPubExport[1].keys) delete[] gRSAPubExport[1].keys;
05837 #ifdef R__SSL
05838    RSA_free(gRSASSLKey);
05839 #endif
05840 }
05841 
05842 //______________________________________________________________________________
05843 int RpdProtocol(int ServType)
05844 {
05845    // Receives client protocol and returns daemon protocol.
05846    // Returns:  0 if ok
05847    //          -1 if any error occured
05848    //          -2 if special action (e.g. cleanup): no need to continue
05849 
05850    int rc = 0;
05851 
05852 //#define R__DEBUG
05853 #ifdef R__DEBUG
05854    int debug = 1;
05855    while (debug)
05856       ;
05857 #endif
05858 
05859    if (gDebug > 2)
05860       ErrorInfo("RpdProtocol: Enter: server type = %d", ServType);
05861 
05862    int readbuf = 1;
05863    EMessageTypes kind;
05864    char proto[kMAXRECVBUF];
05865 
05866    // For backward compatibility, for rootd we need to understand
05867    // whether we are talking to a OLD client: protocol information is
05868    // available only later on ...
05869    int lbuf[2];
05870    if (NetRecvRaw(lbuf, sizeof(lbuf)) < 0) {
05871       NetSend(kErrFatal, kROOTD_ERR);
05872       ErrorInfo("RpdProtocol: error receiving message");
05873       return -1;
05874    }
05875 
05876    // if kind is {kROOTD_PROTOCOL, kROOTD_CLEANUP, kROOTD_SSH}
05877    // receive the rest
05878    kind = (EMessageTypes) ntohl(lbuf[1]);
05879    int len = ntohl(lbuf[0]);
05880    if (gDebug > 1)
05881       ErrorInfo("RpdProtocol: kind: %d %d",kind,len);
05882    if (kind == kROOTD_PROTOCOL || kind == kROOTD_CLEANUP ||
05883        kind == kROOTD_SSH) {
05884       // Receive the rest
05885       char *buf = 0;
05886       len -= sizeof(int);
05887       if (gDebug > 1)
05888          ErrorInfo("RpdProtocol: len: %d",len);
05889       if (len) {
05890          buf = new char[len];
05891          if (NetRecvRaw(buf, len) < 0) {
05892             NetSend(kErrFatal, kROOTD_ERR);
05893             ErrorInfo("RpdProtocol: error receiving message");
05894             delete[] buf;
05895             return -1;
05896          }
05897          strlcpy(proto, buf, sizeof(proto));
05898       } else {
05899          // Empty buffer
05900          proto[0] = '\0';
05901       }
05902       if (gDebug > 1)
05903          ErrorInfo("RpdProtocol: proto buff: %s", buf ? buf : "---");
05904       // Copy buffer for later use
05905       readbuf = 0;
05906       if (buf) delete[] buf;
05907    } else if (ServType == kROOTD && kind == 0 && len == 0) {
05908       // TNetFile via TXNetFile: receive client protocol
05909       // read first next 12 bytes and discard them
05910       int llen = 12;
05911       char *buf = new char[llen];
05912       if (NetRecvRaw(buf, llen) < 0) {
05913          NetSend(kErrFatal, kROOTD_ERR);
05914          ErrorInfo("RpdProtocol: error receiving message");
05915          if (buf) delete[] buf;
05916          return -1;
05917       }
05918       if (buf) delete[] buf;
05919       // Send back the 'type'
05920       int type = htonl(8);
05921       if (NetSendRaw(&type,sizeof(type)) < 0) {
05922          NetSend(kErrFatal, kROOTD_ERR);
05923          ErrorInfo("RpdProtocol: error sending type to TXNetFile");
05924          return -1;
05925       }
05926       // Now read the client protocol
05927       llen = 4;
05928       buf = new char[llen];
05929       if (NetRecvRaw(buf,llen) < 0) {
05930          NetSend(kErrFatal, kROOTD_ERR);
05931          ErrorInfo("RpdProtocol: error receiving message");
05932          delete[] buf;
05933          return -1;
05934       }
05935       strlcpy(proto,buf, sizeof(proto));
05936       kind = kROOTD_PROTOCOL;
05937       readbuf = 0;
05938       delete[] buf;
05939    } else {
05940       // Need to open parallel sockets first
05941       int size = ntohl(lbuf[1]);
05942       // Read port
05943       int port;
05944       if (NetRecvRaw(&port, sizeof(int)) < 0) {
05945          NetSend(kErrFatal, kROOTD_ERR);
05946          ErrorInfo("RpdProtocol: error receiving message");
05947          return -1;
05948       }
05949       port = ntohl(port);
05950       if (gDebug > 0)
05951          ErrorInfo("RpdProtocol: port = %d, size = %d", port, size);
05952       if (size > 1)
05953          NetParOpen(port, size);
05954    }
05955 
05956    int done = 0;
05957    gClientOld = 0;
05958    while (!done) {
05959 
05960       // Receive next
05961       if (readbuf) {
05962          if (NetRecv(proto, kMAXRECVBUF, kind) < 0) {
05963             ErrorInfo("RpdProtocol: error receiving message");
05964             return -1;
05965          }
05966       }
05967       readbuf = 1;
05968 
05969       switch(kind) {
05970 
05971          case kROOTD_CLEANUP:
05972             RpdAuthCleanup(proto,1);
05973             ErrorInfo("RpdProtocol: authentication stuff cleaned");
05974             done = 1;
05975             rc = -2;
05976             break;
05977          case kROOTD_BYE:
05978             RpdFreeKeys();
05979             NetClose();
05980             done = 1;
05981             rc = -2;
05982             break;
05983          case kROOTD_PROTOCOL:
05984 
05985             if (strlen(proto) > 0) {
05986                gClientProtocol = atoi(proto);
05987             } else {
05988                if (ServType == kROOTD) {
05989                   // This is an old (TNetFile,TFTP) client:
05990                   // send our protocol first ...
05991                   if (NetSend(gServerProtocol, kROOTD_PROTOCOL) < 0) {
05992                      ErrorInfo("RpdProtocol: error sending kROOTD_PROTOCOL");
05993                      rc = -1;
05994                   }
05995                   // ... and receive protocol via kROOTD_PROTOCOL2
05996                   if (NetRecv(proto, kMAXRECVBUF, kind) < 0) {
05997                      ErrorInfo("RpdProtocol: error receiving message");
05998                      rc = -1;
05999                   }
06000                   if (kind != kROOTD_PROTOCOL2) {
06001                      strlcpy(gBufOld, proto, sizeof(gBufOld));
06002                      gKindOld = kind;
06003                      gClientOld = 1;
06004                      gClientProtocol = 0;
06005                   } else
06006                      gClientProtocol = atoi(proto);
06007                } else
06008                   gClientProtocol = 0;
06009             }
06010             if (!gClientOld) {
06011                // send our protocol
06012                // if we do not require authentication say it here
06013                Int_t protoanswer = gServerProtocol;
06014                if (!gRequireAuth && gClientProtocol > 10)
06015                   protoanswer += 1000;
06016                // Notify
06017                if (gDebug > 0) {
06018                   ErrorInfo("RpdProtocol: gClientProtocol = %d",
06019                             gClientProtocol);
06020                   ErrorInfo("RpdProtocol: Sending gServerProtocol = %d",
06021                             protoanswer);
06022                }
06023                if (NetSend(protoanswer, kROOTD_PROTOCOL) < 0) {
06024                   ErrorInfo("RpdProtocol: error sending kROOTD_PROTOCOL");
06025                   rc = -1;
06026                }
06027             }
06028             done = 1;
06029             break;
06030          case kROOTD_SSH:
06031             // Failure notification ...
06032             RpdSshAuth(proto);
06033             NetSend(kErrAuthNotOK, kROOTD_ERR);
06034             ErrorInfo("RpdProtocol: SSH failure notified");
06035             rc = -2;
06036             done = 1;
06037             break;
06038          default:
06039             ErrorInfo("RpdProtocol: received bad option (%d)",kind);
06040             rc = -1;
06041             done = 1;
06042             break;
06043       } // Switch
06044 
06045    } // done
06046 
06047    return rc;
06048 }
06049 
06050 //______________________________________________________________________________
06051 int RpdLogin(int ServType, int auth)
06052 {
06053    // Authentication was successful, set user environment.
06054 
06055 //   if (gDebug > 2)
06056       ErrorInfo("RpdLogin: enter: Server: %d, gUser: %s, auth: %d",
06057                 ServType, gUser, auth);
06058 
06059    // Login only if requested
06060    if (gDoLogin == 0)
06061       return -2;
06062 
06063    struct passwd *pw = getpwnam(gUser);
06064 
06065    if (!pw) {
06066       ErrorInfo("RpdLogin: user %s does not exist locally\n", gUser);
06067       return -1;
06068    }
06069 
06070    if (getuid() == 0) {
06071 
06072 #ifdef R__GLBS
06073       if (ServType == 2) {
06074          // We need to change the ownership of the shared memory segments used
06075          // for credential export to allow proofserv to destroy them
06076          struct shmid_ds shm_ds;
06077          if (gShmIdCred > 0) {
06078             if (shmctl(gShmIdCred, IPC_STAT, &shm_ds) == -1) {
06079                ErrorInfo("RpdLogin: can't get info about shared memory"
06080                          " segment %d (errno: %d)",gShmIdCred,GetErrno());
06081                return -1;
06082             }
06083             shm_ds.shm_perm.uid = pw->pw_uid;
06084             shm_ds.shm_perm.gid = pw->pw_gid;
06085             if (shmctl(gShmIdCred, IPC_SET, &shm_ds) == -1) {
06086                ErrorInfo("RpdLogin: can't change ownership of shared"
06087                          " memory segment %d (errno: %d)",
06088                          gShmIdCred,GetErrno());
06089                return -1;
06090             }
06091          }
06092       }
06093 #endif
06094       //
06095       // Anonymous users are confined to their corner
06096       if (gAnon) {
06097          // We need to do it before chroot, otherwise it does not work
06098          if (chdir(pw->pw_dir) == -1) {
06099             ErrorInfo("RpdLogin: can't change directory to %s (errno: %d)",
06100                       pw->pw_dir, errno);
06101             return -1;
06102          }
06103          if (chroot(pw->pw_dir) == -1) {
06104             ErrorInfo("RpdLogin: can't chroot to %s", pw->pw_dir);
06105             return -1;
06106          }
06107       }
06108 
06109       // set access control list from /etc/initgroup
06110       initgroups(gUser, pw->pw_gid);
06111 
06112       // set uid and gid
06113       if (setresgid(pw->pw_gid, pw->pw_gid, 0) == -1) {
06114          ErrorInfo("RpdLogin: can't setgid for user %s", gUser);
06115          return -1;
06116       }
06117       if (setresuid(pw->pw_uid, pw->pw_uid, 0) == -1) {
06118          ErrorInfo("RpdLogin: can't setuid for user %s", gUser);
06119          return -1;
06120       }
06121    }
06122 
06123    if (ServType == 2) {
06124       // set HOME env
06125       char *home = new char[8+strlen(pw->pw_dir)];
06126       SPrintf(home, 8+strlen(pw->pw_dir), "HOME=%s", pw->pw_dir);
06127       putenv(home);
06128    }
06129 
06130    // Change user's HOME, if required (for anon it is already done)
06131    if (gDoLogin == 2 && !gAnon) {
06132       if (chdir(pw->pw_dir) == -1) {
06133          ErrorInfo("RpdLogin: can't change directory to %s (errno: %d)",
06134                    pw->pw_dir, errno);
06135          return -1;
06136       }
06137    }
06138 
06139    umask(022);
06140 
06141    // Notify authentication to client ...
06142    NetSend(auth, kROOTD_AUTH);
06143    // Send also new offset if it changed ...
06144    if (auth == 2) NetSend(gOffSet, kROOTD_AUTH);
06145 
06146    if (gDebug > 0)
06147       ErrorInfo("RpdLogin: user %s logged in", gUser);
06148 
06149    return 0;
06150 }
06151 
06152 //______________________________________________________________________________
06153 int RpdInitSession(int servtype, std::string &user,
06154                    int &cproto, int &meth, int &type, std::string &ctoken)
06155 {
06156    // Perform the action needed to commence the new session:
06157    // Version called by TServerSocket.
06158    //   - set debug flag
06159    //   - check authentication table
06160    //   - Inquire protocol
06161    //   - authenticate the client
06162    // Returns logged-in user, the remote client procotol cproto,
06163    // the authentication protocol (ROOT internal) number is returned
06164    // in meth, type indicates the kind of authentication:
06165    //       0 = new authentication
06166    //       1 = existing authentication
06167    //       2 = existing authentication with updated offset
06168    // and the crypted-token in ctoken (used later for cleaning).
06169    // Called just after opening the connection
06170 
06171    std::string pwd;
06172    int auth = RpdInitSession(servtype,user,cproto,meth,pwd);
06173    if (auth == 1)
06174       if (gExistingAuth)
06175          type = 1;
06176       else
06177          type = 0;
06178    else if (auth == 2)
06179       type = 2;
06180    ctoken = gCryptToken;
06181 
06182    return auth;
06183 }
06184 //______________________________________________________________________________
06185 int RpdInitSession(int servtype, std::string &user,
06186                    int &cproto, int &anon, std::string &passwd)
06187 {
06188    // Perform the action needed to commence the new session:
06189    //   - set debug flag
06190    //   - check authentication table
06191    //   - Inquire protocol
06192    //   - authenticate the client
06193    //   - login the client
06194    // Returns 1 for a PROOF master server, 0 otherwise
06195    // Returns logged-in user, the remote client procotol cproto, the
06196    // client kind of user anon and, if anonymous user, the client passwd.
06197    // If TServerSocket (servtype==kSOCKD), the protocol number is returned
06198    // in anon.
06199    // Called just after opening the connection
06200 
06201    if (gDebug > 2)
06202       ErrorInfo("RpdInitSession: %s", gServName[servtype].c_str());
06203 
06204    int retval = 0;
06205 
06206    // CleanUp authentication table, if needed or required ...
06207    RpdInitAuth();
06208 
06209    // Get Host name
06210    NetGetRemoteHost(gOpenHost);
06211 
06212    if (servtype == kPROOFD) {
06213 
06214       // find out if we are supposed to be a master or a slave server
06215       char  msg[80];
06216       if (NetRecv(msg, sizeof(msg)) < 0) {
06217          ErrorInfo("RpdInitSession: Cannot receive master/slave status");
06218          return -1;
06219       }
06220 
06221       retval = !strcmp(msg, "master") ? 1 : 0;
06222 
06223       if (gDebug > 0)
06224          ErrorInfo("RpdInitSession: PROOF master/slave = %s", msg);
06225    }
06226 
06227    // Get protocol first
06228    // Failure typically indicate special actions like cleanup
06229    // which do not need additional work
06230    // The calling program will then decide what to do
06231    int rcp = RpdProtocol(servtype);
06232    if (rcp != 0) {
06233       if (rcp == -1)
06234          ErrorInfo("RpdInitSession: error getting remote protocol");
06235       else if (rcp != -2)
06236          ErrorInfo("RpdInitSession: unknown error from RpdProtocol");
06237       return rcp;
06238    }
06239 
06240    // Check if authentication is required
06241    // Old clients do not support no authentication mode
06242    bool runAuth = (gClientProtocol < 11 || gRequireAuth) ? 1 : 0;
06243 
06244    // user authentication (does not return in case of failure)
06245    int auth = 0;
06246    if (runAuth) {
06247       auth = RpdAuthenticate();
06248       if (auth == 0) {
06249          ErrorInfo("RpdInitSession: unsuccessful authentication attempt");
06250          return -1;
06251       }
06252    } else {
06253       auth = RpdNoAuth(servtype);
06254    }
06255 
06256    // Login the user (if in rootd/proofd environment)
06257    if (gDoLogin > 0) {
06258       if (RpdLogin(servtype,auth) != 0) {
06259          ErrorInfo("RpdInitSession: unsuccessful login attempt");
06260          // Notify failure to client ...
06261          NetSend(0, kROOTD_AUTH);
06262          return -1;
06263       }
06264    } else {
06265       // Notify authentication to client ...
06266       NetSend(auth, kROOTD_AUTH);
06267       // Send also new offset if it changed ...
06268       if (auth == 2)
06269          NetSend(gOffSet, kROOTD_AUTH);
06270       if (gDebug > 0)
06271          ErrorInfo("RpdInitSession: User '%s' authenticated", gUser);
06272       retval = auth;
06273    }
06274 
06275    // Output vars
06276    user = std::string(gUser);
06277    cproto = gClientProtocol;
06278    if (servtype == kSOCKD)
06279       anon = gSec;
06280    else
06281       anon = gAnon;
06282    if (gAnon)
06283       passwd = std::string(gPasswd);
06284 
06285    return retval;
06286 }
06287 
06288 //______________________________________________________________________________
06289 int RpdInitSession(int servtype, std::string &user, int &rid)
06290 {
06291    // Perform the action needed to commence the new session:
06292    //   - set debug flag
06293    //   - check authentication table
06294    //   - Inquire protocol
06295    //   - authenticate the client
06296    //   - login the client
06297    // Returns 1 for a PROOF master server, 0 otherwise
06298    // Returns logged-in user and remote process id in rid
06299    // Called just after opening the connection
06300 
06301    int dum1 = 0, dum2 = 0;
06302    std::string dum3;
06303    rid = gRemPid;
06304    return RpdInitSession(servtype,user,dum1,dum2,dum3);
06305 
06306 }
06307 
06308 
06309 //______________________________________________________________________________
06310 int RpdNoAuth(int servtype)
06311 {
06312    // Perform entrance formalities in case of no authentication
06313    // mode, i.e. get target user and check if authorized
06314    // Don't return if something goes wrong
06315 
06316    if (gDebug > 1)
06317       ErrorInfo("RpdNoAuth: no authentication required");
06318 
06319    // Special value for this case
06320    int auth = 0;
06321 
06322    // Receive target username
06323    if (servtype == kROOTD || servtype == kPROOFD) {
06324 
06325       char buf[kMAXPATHLEN];
06326       EMessageTypes kind;
06327       if (NetRecv(buf, kMAXPATHLEN, kind) < 0) {
06328          NetSend(kErrBadMess, kROOTD_ERR);
06329          ErrorInfo("RpdNoAuth: error receiving target user");
06330          goto quit;
06331       }
06332 
06333       if (kind == kROOTD_BYE)
06334          goto quit;
06335 
06336       if (kind != kROOTD_USER) {
06337          NetSend(kErrBadOp, kROOTD_ERR);
06338          ErrorInfo("RpdNoAuth: protocol error:"
06339           " received msg type: %d, expecting: %d", kind, kROOTD_USER);
06340          goto quit;
06341       }
06342 
06343       // Decode buffer
06344       char ruser[kMAXUSERLEN], user[kMAXUSERLEN];
06345       int nw = sscanf(buf,"%64s %64s",ruser,user);
06346       if (nw <= 0 || !strcmp(ruser,"-1")) {
06347          NetSend(kErrBadMess, kROOTD_ERR);
06348          ErrorInfo("RpdNoAuth: received uncorrect information: %s", buf);
06349          goto quit;
06350       }
06351       // If target user not send, assume user == ruser
06352       if (nw == 1)
06353          snprintf(user,kMAXUSERLEN,"%s",ruser);
06354 
06355       struct passwd *pw = 0;
06356       if ((pw = getpwnam(user)) == 0) {
06357          NetSend(kErrNoUser, kROOTD_ERR);
06358          ErrorInfo("RpdNoAuth: user %s unknown", user);
06359          goto quit;
06360       }
06361 
06362       // If server is not started as root, require user to be the same
06363       // as the one who started rootd
06364       uid_t uid = getuid();
06365       if (uid && uid != pw->pw_uid) {
06366          NetSend(kErrBadUser, kROOTD_ERR);
06367          ErrorInfo("RpdNoAuth: user not same as effective user of rootd");
06368          goto quit;
06369       }
06370 
06371       if (gDebug > 2)
06372          ErrorInfo("RpdNoAuth: remote user: %s, target user: %s",ruser,user);
06373 
06374       SPrintf(gUser, 63, "%s", user);
06375    }
06376 
06377    auth = 4;
06378 
06379    quit:
06380    return auth;
06381 }
06382 
06383 //______________________________________________________________________________
06384 int RpdSetUid(int uid)
06385 {
06386    // Change current user id to uid (and gid).
06387 
06388    if (gDebug > 2)
06389       ErrorInfo("RpdSetUid: enter ...uid: %d", uid);
06390 
06391    struct passwd *pw = getpwuid(uid);
06392 
06393    if (!pw) {
06394       ErrorInfo("RpdSetUid: uid %d does not exist locally", uid);
06395       return -1;
06396    } else if (chdir(pw->pw_dir) == -1) {
06397       ErrorInfo("RpdSetUid: can't change directory to %s", pw->pw_dir);
06398       return -1;
06399    }
06400 
06401    if (getuid() == 0) {
06402 
06403       // set access control list from /etc/initgroup
06404       initgroups(pw->pw_name, pw->pw_gid);
06405 
06406       // set uid and gid
06407       if (setresgid(pw->pw_gid, pw->pw_gid, 0) == -1) {
06408          ErrorInfo("RpdSetUid: can't setgid for uid %d", uid);
06409          return -1;
06410       }
06411       if (setresuid(pw->pw_uid, pw->pw_uid, 0) == -1) {
06412          ErrorInfo("RpdSetUid: can't setuid for uid %d", uid);
06413          return -1;
06414       }
06415    }
06416 
06417    if (gDebug > 0)
06418       ErrorInfo("RpdSetUid: uid set (%d,%s)", uid, pw->pw_name);
06419 
06420    return 0;
06421 }
06422 
06423 //_____________________________________________________________________________
06424 void RpdInit(EService serv, int pid, int sproto, unsigned int options,
06425              int rumsk, int sshp, const char *tmpd, const char *asrpp, int login)
06426 {
06427    // Change defaults job control options.
06428 
06429    gService        = serv;
06430    gParentId       = pid;
06431    gServerProtocol = sproto;
06432    gReUseAllow     = rumsk;
06433    gSshdPort       = sshp;
06434    gDoLogin        = login;
06435 
06436    // Parse options
06437    gCheckHostsEquiv= (bool)((options & kDMN_HOSTEQ) != 0);
06438    gRequireAuth    = (bool)((options & kDMN_RQAUTH) != 0);
06439    gSysLog         = (bool)((options & kDMN_SYSLOG) != 0);
06440 
06441    if (tmpd && strlen(tmpd)) {
06442       gTmpDir      = tmpd;
06443       gRpdAuthTab  = gTmpDir + gAuthTab;
06444       gRpdKeyRoot  = gTmpDir + gKeyRoot;
06445    }
06446    // Auth Tab and public key files are exclusive to this family
06447    gRpdAuthTab.append(".");
06448    gRpdAuthTab.append(ItoA(getuid()));
06449    gRpdKeyRoot.append(ItoA(getuid()));
06450    gRpdKeyRoot.append("_");
06451 
06452    if (asrpp && strlen(asrpp))
06453       gAltSRPPass  = asrpp;
06454 
06455 #ifdef R__GLBS
06456    // Init globus
06457    if (RpdGlobusInit() != 0)
06458       ErrorInfo("RpdInit: failure initializing globus authentication");
06459 #endif
06460 
06461    if (gDebug > 0) {
06462       ErrorInfo("RpdInit: gService= %s, gSysLog= %d, gSshdPort= %d",
06463                  gServName[gService].c_str(), gSysLog, gSshdPort);
06464       ErrorInfo("RpdInit: gParentId= %d", gParentId);
06465       ErrorInfo("RpdInit: gRequireAuth= %d, gCheckHostEquiv= %d",
06466                  gRequireAuth, gCheckHostsEquiv);
06467       ErrorInfo("RpdInit: gReUseAllow= 0x%x", gReUseAllow);
06468       ErrorInfo("RpdInit: gServerProtocol= %d", gServerProtocol);
06469       ErrorInfo("RpdInit: gDoLogin= %d", gDoLogin);
06470       if (tmpd)
06471          ErrorInfo("RpdInit: gTmpDir= %s", gTmpDir.c_str());
06472       if (asrpp)
06473          ErrorInfo("RpdInit: gAltSRPPass= %s", gAltSRPPass.c_str());
06474 #ifdef R__GLBS
06475       ErrorInfo("RpdInit: gHaveGlobus: %d", (int) gHaveGlobus);
06476 #endif
06477    }
06478 }
06479 
06480 
06481 //______________________________________________________________________________
06482 int SPrintf(char *buf, size_t size, const char *va_(fmt), ...)
06483 {
06484    // Acts like snprintf with some printout in case of error if required
06485    // Returns number of  characters printed (excluding the trailing `\0').
06486    // Returns 0 is buf or size are not defined or inconsistent.
06487    // Returns -1 if the buffer is truncated.
06488 
06489    // Check buf
06490    if (!buf) {
06491       if (gDebug > 0)
06492          ErrorInfo("SPrintf: buffer not allocated: do nothing");
06493       return 0;
06494    }
06495 
06496    // Check size
06497    if (size < 1) {
06498       if (gDebug > 0)
06499          ErrorInfo("SPrintf: cannot determine buffer size (%d): do nothing",size);
06500       return 0;
06501    }
06502 
06503    // Now fill buf
06504    va_list ap;
06505    va_start(ap,va_(fmt));
06506    int np = vsnprintf(buf, size, fmt, ap);
06507    va_end(ap);
06508 
06509    if (np == -1 && gDebug > 0)
06510       ErrorInfo("SPrintf: buffer truncated (%s)",buf);
06511 
06512    return np;
06513 }
06514 
06515 
06516 //______________________________________________________________________________
06517 char *ItoA(int i)
06518 {
06519    // Return pointer to a static string containing the string
06520    // version of integer 'i', up to a max of kMAXCHR (=30)
06521    // characters; returns "-1" if more chars are needed.
06522    const int kMAXCHR = 30;
06523    static char str[kMAXCHR];
06524 
06525    // This is the number of characters we need
06526    int nchr = (int)log10(double(i)) + 1;
06527    if (nchr > kMAXCHR)
06528       strlcpy(str,"-1", sizeof(str));
06529    else
06530       snprintf(str,30,"%d",i);
06531 
06532    return str;
06533 }
06534 
06535 //______________________________________________________________________________
06536 void RpdSetErrorHandler(ErrorHandler_t err, ErrorHandler_t sys, ErrorHandler_t fatal)
06537 {
06538    // Set global pointers to error handler functions
06539 
06540    gErr      = err;
06541    gErrSys   = sys;
06542    gErrFatal = fatal;
06543 }
06544 
06545 #ifdef R__GLBS
06546 //______________________________________________________________________________
06547 int RpdGetShmIdCred()
06548 {
06549    // Returns shared memory id
06550 
06551    return gShmIdCred;
06552 }
06553 #endif
06554 
06555 
06556 //______________________________________________________________________________
06557 int RpdRetrieveSpecialPass(const char *usr, const char *fpw, char *pass, int lpwmax)
06558 {
06559    // Retrieve specific ROOT password from $HOME/fpw, if any.
06560    // To avoid problems with NFS-root-squashing, if 'root' changes temporarly the
06561    // uid/gid to those of the target user (usr).
06562    // If OK, returns pass length and fill 'pass' with the password, null-terminated.
06563    // ('pass' is allocated externally to contain max lpwmax bytes).
06564    // If the file does not exists, return 0 and an empty pass.
06565    // If any problems with the file occurs, return a negative
06566    // code, -2 indicating wrong file permissions.
06567    // If any problem with changing ugid's occurs, prints a warning trying anyhow
06568    // to read the password hash.
06569 
06570    int rc = -1;
06571    int len = 0, n = 0, fid = -1;
06572 
06573    // Check inputs
06574    if (!usr || !pass) {
06575       if (gDebug > 0)
06576          ErrorInfo("RpdRetrieveSpecialPass: invalid arguments:"
06577                    " us:%p, sp:%p", usr, pass);
06578       return rc;
06579    }
06580 
06581    struct passwd *pw = getpwnam(usr);
06582    if (!pw) {
06583       if (gDebug > 0)
06584          ErrorInfo("RpdRetrieveSpecialPass: user '%s' does not exist", usr);
06585       return rc;
06586    }
06587 
06588    // target and actual uid
06589    int uid = pw->pw_uid;
06590    int ouid = getuid();
06591 
06592    // Temporary change to target user ID to avoid NFS squashing problems
06593    if (ouid == 0) {
06594 
06595       // set access control list from /etc/initgroup
06596       if (initgroups(pw->pw_name, pw->pw_gid) == -1)
06597          ErrorInfo("RpdRetrieveSpecialPass: can't initgroups for uid %d"
06598                    " (errno: %d)", uid, GetErrno());
06599       // set uid and gid
06600       if (setresgid(pw->pw_gid, pw->pw_gid, 0) == -1)
06601          ErrorInfo("RpdRetrieveSpecialPass: can't setgid for gid %d"
06602                    " (errno: %d)", pw->pw_gid, GetErrno());
06603       if (setresuid(pw->pw_uid, pw->pw_uid, 0) == -1)
06604          ErrorInfo("RpdRetrieveSpecialPass: can't setuid for uid %d"
06605                    " (errno: %d)", uid, GetErrno());
06606    }
06607 
06608    // The file now
06609    char rootdpass[kMAXPATHLEN];
06610    SPrintf(rootdpass, kMAXPATHLEN, "%s/%s", pw->pw_dir, fpw);
06611 
06612    if (gDebug > 0)
06613       ErrorInfo
06614          ("RpdRetrieveSpecialPass: checking file %s for user %s",rootdpass,
06615            pw->pw_name);
06616 
06617 
06618    if ((fid = open(rootdpass, O_RDONLY)) == -1) {
06619       ErrorInfo("RpdRetrieveSpecialPass: cannot open password file"
06620                 " %s (errno: %d)", rootdpass, GetErrno());
06621       rc = -1;
06622       goto back;
06623    }
06624    // Check first the permissions: should be 0600
06625    struct stat st;
06626    if (fstat(fid, &st) == -1) {
06627       ErrorInfo("RpdRetrieveSpecialPass: cannot stat descriptor %d"
06628                   " %s (errno: %d)", fid, GetErrno());
06629       rc = -1;
06630       goto back;
06631    }
06632    if (!S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) ||
06633        (st.st_mode & (S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH)) != 0) {
06634       ErrorInfo("RpdRetrieveSpecialPass: pass file %s: wrong permissions"
06635                 " 0%o (should be 0600)", rootdpass, (st.st_mode & 0777));
06636       ErrorInfo("RpdRetrieveSpecialPass: %d %d",
06637                 S_ISREG(st.st_mode),S_ISDIR(st.st_mode));
06638       rc = -2;
06639       goto back;
06640    }
06641 
06642    if ((n = read(fid, pass, lpwmax - 1)) <= 0) {
06643       close(fid);
06644       ErrorInfo("RpdRetrieveSpecialPass: cannot read password file"
06645                 " %s (errno: %d)", rootdpass, GetErrno());
06646       rc = -1;
06647       goto back;
06648    }
06649    close(fid);
06650 
06651    // Get rid of special trailing chars
06652    len = n;
06653    while (len-- && (pass[len] == '\n' || pass[len] == 32))
06654       pass[len] = 0;
06655 
06656    // Null-terminate
06657    pass[++len] = 0;
06658    rc = len;
06659 
06660    back:
06661    // Change back uid's
06662    if (ouid == 0) {
06663       // set uid and gid
06664       if (setresgid(0, 0, 0) == -1)
06665          ErrorInfo("RpdRetrieveSpecialPass: can't re-setgid for gid 0"
06666                    " (errno: %d)", GetErrno());
06667       if (setresuid(0, 0, 0) == -1)
06668          ErrorInfo("RpdRetrieveSpecialPass: can't re-setuid for uid 0"
06669                    " (errno: %d)", GetErrno());
06670    }
06671 
06672    // We are done
06673    return rc;
06674 }
06675 
06676 } // namespace ROOT

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