// @(#)root/auth:$Id$
// Author: Gerardo Ganis   08/07/05

/*************************************************************************
 * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TRootAuth                                                            //
//                                                                      //
// TVirtualAuth implementation based on the old client authentication   //
// code.                                                                //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TAuthenticate.h"
#include "TEnv.h"
#include "TError.h"
#include "THostAuth.h"
#include "TRootAuth.h"
#include "TRootSecContext.h"
#include "TSocket.h"
#include "TSystem.h"
#include "TUrl.h"

//______________________________________________________________________________
TSecContext *TRootAuth::Authenticate(TSocket *s, const char *host,
                                     const char *user, Option_t *opts)
{
   // Runs authentication on socket s.
   // Invoked when dynamic loading is needed.
   // Returns 1 on success, 0 on failure.
   TSecContext *ctx = 0;
   Int_t rc = 0;

   Int_t rproto =  s->GetRemoteProtocol() % 1000;
   if (s->GetServType() == (Int_t)TSocket::kROOTD) {
      if (rproto > 6 && rproto < 10) {
         // Middle aged versions expect client protocol now
         s->Send(Form("%d", TSocket::GetClientProtocol()), kROOTD_PROTOCOL2);
         Int_t kind = 0;
         if (s->Recv(rproto, kind) < 0) {
            Error("Authenticate", "receiving remote protocol");
            return ctx;
         }
         s->SetRemoteProtocol(rproto);
      }
   }

   // Find out if we are a PROOF master
   Bool_t isPROOF = (s->GetServType() == (Int_t)TSocket::kPROOFD);
   Bool_t isMASTER = kFALSE;
   if (isPROOF) {
      // Master by default
      isMASTER = kTRUE;
      // Parse option
      TString opt(TUrl(s->GetUrl()).GetOptions());
      if (!strncasecmp(opt.Data()+1, "C", 1)) {
         isMASTER = kFALSE;
      }
   }

   // Find out whether we are a proof serv
   Bool_t isPROOFserv = (opts[0] == 'P') ? kTRUE : kFALSE;

   // Build the protocol string for TAuthenticate
   TString proto = TUrl(s->GetUrl()).GetProtocol();
   if (proto == "") {
      proto = "root";
   } else if (proto.Contains("sockd") || proto.Contains("rootd") ||
              proto.Contains("proofd")) {
      proto.ReplaceAll("d",1,"",0);
   }
   proto += Form(":%d",rproto);

   // Init authentication
   TAuthenticate *auth =
      new TAuthenticate(s, host, proto, user);

   // If PROOF client and trasmission of the SRP password is
   // requested make sure that ReUse is switched on to get and
   // send also the Public Key
   // Masters do this automatically upon reception of valid info
   // (see TSlave.cxx)
   if (isMASTER && !isPROOFserv) {
      if (gEnv->GetValue("Proofd.SendSRPPwd",0)) {
         Int_t kSRP = TAuthenticate::kSRP;
         TString detsSRP(auth->GetHostAuth()->GetDetails(kSRP));
         Int_t pos = detsSRP.Index("ru:0");
         if (pos > -1) {
            detsSRP.ReplaceAll("ru:0",4,"ru:1",4);
            auth->GetHostAuth()->SetDetails(kSRP,detsSRP);
         } else {
            TSubString ss = detsSRP.SubString("ru:no",TString::kIgnoreCase);
            if (!ss.IsNull()) {
               detsSRP.ReplaceAll(ss.Data(),5,"ru:1",4);
               auth->GetHostAuth()->SetDetails(kSRP,detsSRP);
            }
         }
      }
   }

   // No control on credential forwarding in case of SSH authentication;
   // switched it off on PROOF servers, unless the user knows what they
   // are doing
   if (isPROOFserv) {
      if (!(gEnv->GetValue("ProofServ.UseSSH",0)))
         auth->GetHostAuth()->RemoveMethod(TAuthenticate::kSSH);
   }

   // Attempt authentication
   if (!auth->Authenticate()) {
      // Close the socket if unsuccessful
      if (auth->HasTimedOut() > 0)
         Error("Authenticate",
               "timeout expired for %s@%s", auth->GetUser(), host);
      else
         Error("Authenticate",
               "authentication failed for %s@%s", auth->GetUser(), host);
      // This is to terminate properly remote proofd in case of failure
      if (isPROOF)
         s->Send(Form("%d %s", gSystem->GetPid(), host), kROOTD_CLEANUP);
   } else {
      // Set return flag;
      rc = 1;
      // Search pointer to relevant TSecContext
      ctx = auth->GetSecContext();
      s->SetSecContext(ctx);
   }
   // Cleanup
   delete auth;

   // If we are talking to a recent proofd send over a buffer with the
   // remaining authentication related stuff
   if (rc && isPROOF && rproto > 11) {
      Bool_t client = !isPROOFserv;
      if (TAuthenticate::ProofAuthSetup(s, client) !=0 ) {
         Error("Authenticate", "PROOF: failed to finalize setup");
      }
   }

   // We are done
   return ctx;
}

//______________________________________________________________________________
Int_t TRootAuth::ClientVersion()
{
   // Return client version;

   return TSocket::GetClientProtocol();
}

//______________________________________________________________________________
void TRootAuth::ErrorMsg(const char *where, Int_t ecode)
{
   // Print error string corresponding to ecode, prepending location

   TAuthenticate::AuthError(where, ecode);
}
 TRootAuth.cxx:1
 TRootAuth.cxx:2
 TRootAuth.cxx:3
 TRootAuth.cxx:4
 TRootAuth.cxx:5
 TRootAuth.cxx:6
 TRootAuth.cxx:7
 TRootAuth.cxx:8
 TRootAuth.cxx:9
 TRootAuth.cxx:10
 TRootAuth.cxx:11
 TRootAuth.cxx:12
 TRootAuth.cxx:13
 TRootAuth.cxx:14
 TRootAuth.cxx:15
 TRootAuth.cxx:16
 TRootAuth.cxx:17
 TRootAuth.cxx:18
 TRootAuth.cxx:19
 TRootAuth.cxx:20
 TRootAuth.cxx:21
 TRootAuth.cxx:22
 TRootAuth.cxx:23
 TRootAuth.cxx:24
 TRootAuth.cxx:25
 TRootAuth.cxx:26
 TRootAuth.cxx:27
 TRootAuth.cxx:28
 TRootAuth.cxx:29
 TRootAuth.cxx:30
 TRootAuth.cxx:31
 TRootAuth.cxx:32
 TRootAuth.cxx:33
 TRootAuth.cxx:34
 TRootAuth.cxx:35
 TRootAuth.cxx:36
 TRootAuth.cxx:37
 TRootAuth.cxx:38
 TRootAuth.cxx:39
 TRootAuth.cxx:40
 TRootAuth.cxx:41
 TRootAuth.cxx:42
 TRootAuth.cxx:43
 TRootAuth.cxx:44
 TRootAuth.cxx:45
 TRootAuth.cxx:46
 TRootAuth.cxx:47
 TRootAuth.cxx:48
 TRootAuth.cxx:49
 TRootAuth.cxx:50
 TRootAuth.cxx:51
 TRootAuth.cxx:52
 TRootAuth.cxx:53
 TRootAuth.cxx:54
 TRootAuth.cxx:55
 TRootAuth.cxx:56
 TRootAuth.cxx:57
 TRootAuth.cxx:58
 TRootAuth.cxx:59
 TRootAuth.cxx:60
 TRootAuth.cxx:61
 TRootAuth.cxx:62
 TRootAuth.cxx:63
 TRootAuth.cxx:64
 TRootAuth.cxx:65
 TRootAuth.cxx:66
 TRootAuth.cxx:67
 TRootAuth.cxx:68
 TRootAuth.cxx:69
 TRootAuth.cxx:70
 TRootAuth.cxx:71
 TRootAuth.cxx:72
 TRootAuth.cxx:73
 TRootAuth.cxx:74
 TRootAuth.cxx:75
 TRootAuth.cxx:76
 TRootAuth.cxx:77
 TRootAuth.cxx:78
 TRootAuth.cxx:79
 TRootAuth.cxx:80
 TRootAuth.cxx:81
 TRootAuth.cxx:82
 TRootAuth.cxx:83
 TRootAuth.cxx:84
 TRootAuth.cxx:85
 TRootAuth.cxx:86
 TRootAuth.cxx:87
 TRootAuth.cxx:88
 TRootAuth.cxx:89
 TRootAuth.cxx:90
 TRootAuth.cxx:91
 TRootAuth.cxx:92
 TRootAuth.cxx:93
 TRootAuth.cxx:94
 TRootAuth.cxx:95
 TRootAuth.cxx:96
 TRootAuth.cxx:97
 TRootAuth.cxx:98
 TRootAuth.cxx:99
 TRootAuth.cxx:100
 TRootAuth.cxx:101
 TRootAuth.cxx:102
 TRootAuth.cxx:103
 TRootAuth.cxx:104
 TRootAuth.cxx:105
 TRootAuth.cxx:106
 TRootAuth.cxx:107
 TRootAuth.cxx:108
 TRootAuth.cxx:109
 TRootAuth.cxx:110
 TRootAuth.cxx:111
 TRootAuth.cxx:112
 TRootAuth.cxx:113
 TRootAuth.cxx:114
 TRootAuth.cxx:115
 TRootAuth.cxx:116
 TRootAuth.cxx:117
 TRootAuth.cxx:118
 TRootAuth.cxx:119
 TRootAuth.cxx:120
 TRootAuth.cxx:121
 TRootAuth.cxx:122
 TRootAuth.cxx:123
 TRootAuth.cxx:124
 TRootAuth.cxx:125
 TRootAuth.cxx:126
 TRootAuth.cxx:127
 TRootAuth.cxx:128
 TRootAuth.cxx:129
 TRootAuth.cxx:130
 TRootAuth.cxx:131
 TRootAuth.cxx:132
 TRootAuth.cxx:133
 TRootAuth.cxx:134
 TRootAuth.cxx:135
 TRootAuth.cxx:136
 TRootAuth.cxx:137
 TRootAuth.cxx:138
 TRootAuth.cxx:139
 TRootAuth.cxx:140
 TRootAuth.cxx:141
 TRootAuth.cxx:142
 TRootAuth.cxx:143
 TRootAuth.cxx:144
 TRootAuth.cxx:145
 TRootAuth.cxx:146
 TRootAuth.cxx:147
 TRootAuth.cxx:148
 TRootAuth.cxx:149
 TRootAuth.cxx:150
 TRootAuth.cxx:151
 TRootAuth.cxx:152
 TRootAuth.cxx:153
 TRootAuth.cxx:154
 TRootAuth.cxx:155
 TRootAuth.cxx:156
 TRootAuth.cxx:157
 TRootAuth.cxx:158
 TRootAuth.cxx:159
 TRootAuth.cxx:160
 TRootAuth.cxx:161
 TRootAuth.cxx:162
 TRootAuth.cxx:163
 TRootAuth.cxx:164
 TRootAuth.cxx:165