// @(#)root/net:$Id$
// Author: G. Ganis   19/03/2003

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

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TSecContext                                                          //
//                                                                      //
// Contains details about an established security context               //
// Used by THostAuth                                                    //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "RConfigure.h"

#include <stdlib.h>

#include "TSecContext.h"
#include "TSocket.h"
#include "TUrl.h"
#include "TROOT.h"
#include "TError.h"
#include "TVirtualMutex.h"

ClassImp(TSecContext)
ClassImp(TSecContextCleanup)

//______________________________________________________________________________
TSecContext::TSecContext(const char *user, const char *host, Int_t meth,
                         Int_t offset, const char *id,
                         const char *token, TDatime expdate, void *ctx)
            : TObject()
{
   // Ctor for SecContext object.
   R__ASSERT(gROOT);

   fContext = ctx;
   fCleanup = new TList;
   fExpDate = expdate;
   if (offset > -1) {
      if (fExpDate < TDatime()) {
         // This means expdate was not initialized
         // We set it to default, ie 1 day from now
         fExpDate.Set(TDatime().GetDate() + 1, TDatime().GetTime());
      }
   }
   fHost    = host;
   fID      = id;
   fMethod  = meth;
   fMethodName = "";
   fOffSet  = offset;
   fToken   = token;
   fUser    = user;

   // Keep official list updated with active TSecContexts
   if (fOffSet > -1) {
      R__LOCKGUARD2(gROOTMutex);
      gROOT->GetListOfSecContexts()->Add(this);
   }
}

//______________________________________________________________________________
TSecContext::TSecContext(const char *url, Int_t meth, Int_t offset,
                         const char *token, const char *id,
                         TDatime expdate, void *ctx)
            : TObject()
{
   // Ctor for SecContext object.
   // User and host from url = user@host .
   R__ASSERT(gROOT);

   fContext = ctx;
   fCleanup = new TList;
   fExpDate = expdate;
   if (offset > -1) {
      if (fExpDate < TDatime()) {
         // This means expdate was not initialized
         // We set it to default, ie 1 day from now
         fExpDate.Set(TDatime().GetDate() + 1, TDatime().GetTime());
      }
   }
   fHost    = TUrl(url).GetHost();
   fID      = id;
   fMethod  = meth;
   fMethodName = "";
   fOffSet  = offset;
   fToken   = token;
   fUser    = TUrl(url).GetUser();

   // Keep official list updated with active TSecContexts
   if (fOffSet > -1) {
      R__LOCKGUARD2(gROOTMutex);
      gROOT->GetListOfSecContexts()->Add(this);
   }
}

//______________________________________________________________________________
TSecContext::TSecContext(const TSecContext& sc) :
  TObject(sc),
  fContext(sc.fContext),
  fCleanup(sc.fCleanup),
  fExpDate(sc.fExpDate),
  fHost(sc.fHost),
  fID(sc.fID),
  fMethod(sc.fMethod),
  fMethodName(sc.fMethodName),
  fOffSet(sc.fOffSet),
  fToken(sc.fToken),
  fUser(sc.fUser)
{
   //copy constructor
}

//______________________________________________________________________________
TSecContext& TSecContext::operator=(const TSecContext& sc)
{
   //assignement operator
   if(this!=&sc) {
      TObject::operator=(sc);
      fContext=sc.fContext;
      fCleanup=sc.fCleanup;
      fExpDate=sc.fExpDate;
      fHost=sc.fHost;
      fID=sc.fID;
      fMethod=sc.fMethod;
      fMethodName=sc.fMethodName;
      fOffSet=sc.fOffSet;
      fToken=sc.fToken;
      fUser=sc.fUser;
   }
   return *this;
}

//______________________________________________________________________________
TSecContext::~TSecContext()
{
   // Dtor: delete (deActivate, local/remote cleanup, list removal)
   // all what is still active

   Cleanup();
}
//______________________________________________________________________________
void TSecContext::Cleanup()
{
   // Cleanup what is still active

   if (IsActive()) {
      CleanupSecContext(kTRUE);
      DeActivate("R");
      // All have been remotely Deactivated
      TIter nxtl(gROOT->GetListOfSecContexts());
      TSecContext *nscl;
      while ((nscl = (TSecContext *)nxtl())) {
         if (nscl != this && !strcmp(nscl->GetHost(), fHost.Data())) {
            // Need to set ofs=-1 to avoid sending another
            // cleanup request
            nscl->DeActivate("");
         }
      }
   }

   // Delete the cleanup list
   if (fCleanup) {
      fCleanup->Delete();
      delete fCleanup;
      fCleanup = 0;
   }
}

//______________________________________________________________________________
void TSecContext::DeActivate(Option_t *Opt)
{
   // Set OffSet to -1 and expiring Date to default
   // Remove from the list
   // If Opt contains "C" or "c", ask for remote cleanup
   // If Opt contains "R" or "r", remove from the list
   // Default Opt="CR"

   // Ask remote cleanup of this context
   Bool_t clean = (strstr(Opt,"C") || strstr(Opt,"c"));
   if (clean && fOffSet > -1)
      CleanupSecContext(kFALSE);

   Bool_t remove = (strstr(Opt,"R") || strstr(Opt,"r"));
   if (remove && fOffSet > -1){
      R__LOCKGUARD2(gROOTMutex);
      // Remove from the global list
      gROOT->GetListOfSecContexts()->Remove(this);
   }

   // Set inactive
   fOffSet  = -1;
   fExpDate = kROOTTZERO;
}

//______________________________________________________________________________
void TSecContext::AddForCleanup(Int_t port, Int_t proto, Int_t type)
{
   // Create a new TSecContextCleanup
   // Internally is added to the list

   TSecContextCleanup *tscc = new TSecContextCleanup(port, proto, type);
   fCleanup->Add(tscc);

}

//______________________________________________________________________________
Bool_t TSecContext::IsA(const char *methname)
{
   // Checks if this security context is for method named 'methname'
   // Case sensitive.

   return Bool_t(!strcmp(methname, GetMethodName()));
}

//______________________________________________________________________________
Bool_t TSecContext::IsActive() const
{
   // Check remote OffSet and expiring Date

   if (fOffSet > -1 && fExpDate > TDatime())
      return kTRUE;
   // Invalid
   return kFALSE;
}

//______________________________________________________________________________
void TSecContext::Print(Option_t *opt) const
{
   // If opt is "F" (default) print object content.
   // If opt is "<number>" print in special form for calls within THostAuth
   // with cardinality <number>
   // If opt is "S" prints short in-line form for calls within TFTP,
   // TSlave, TProof ...

   char aOrd[10] = {0};
   char aSpc[10] = {0};

   // Check if option is numeric
   Int_t ord = -1, i = 0;
   for (; i < (Int_t)strlen(opt); i++) {
      if (opt[i] < 48 || opt[i] > 57) {
         ord = -2;
         break;
      }
   }
   // If numeric get the cardinality and prepare the strings
   if (ord == -1)
      ord = atoi(opt);

   // If asked to print ordinal number, preapre the string
   if (ord > -1) {
      snprintf(aOrd,10,"%d)",ord);
      // and take care of alignment
      Int_t len=strlen(aOrd);
      while (len--)
         strlcat(aSpc," ",10);
   }

   if (!strncasecmp(opt,"F",1)) {
      Info("Print",
           "+------------------------------------------------------+");
      Info("Print",
           "+ Host:%s Method:%d (%s) User:'%s'",
            GetHost(), fMethod, GetMethodName(),
            fUser.Data());
      Info("Print",
           "+         OffSet:%d, id:%s", fOffSet, fID.Data());
      if (fOffSet > -1)
         Info("Print",
           "+         Expiration time: %s",fExpDate.AsString());
      Info("Print",
           "+------------------------------------------------------+");
   } else if (!strncasecmp(opt,"S",1)) {
      if (fOffSet > -1) {
         Printf("Security context:     Method: %d (%s) expiring on %s",
                fMethod, GetMethodName(),
                fExpDate.AsString());
      } else {
         Printf("Security context:     Method: %d (%s) not reusable",
                fMethod, GetMethodName());
      }
   } else {
      // special printing form for THostAuth
      Info("PrintEstblshed","+ %s h:%s met:%d (%s) us:'%s'",
            aOrd, GetHost(), fMethod, GetMethodName(),
            fUser.Data());
      Info("PrintEstblshed","+ %s offset:%d id:%s", aSpc, fOffSet, fID.Data());
      if (fOffSet > -1)
         Info("PrintEstblshed","+ %s expiring: %s",aSpc,fExpDate.AsString());
   }
}

//______________________________________________________________________________
const char *TSecContext::AsString(TString &out)
{
   // Returns short string with relevant information about this
   // security context

   if (fOffSet > -1) {
      char expdate[32];
      out = Form("Method: %d (%s) expiring on %s",
                 fMethod, GetMethodName(), fExpDate.AsString(expdate));
   } else {
      if (fOffSet == -1)
         out = Form("Method: %d (%s) not reusable", fMethod, GetMethodName());
      else if (fOffSet == -3)
         out = Form("Method: %d (%s) authorized by /etc/hosts.equiv or $HOME/.rhosts",
                    fMethod, GetMethodName());
      else if (fOffSet == -4)
         out = Form("No authentication required remotely");
   }
   return out.Data();
}

//______________________________________________________________________________
Bool_t TSecContext::CleanupSecContext(Bool_t)
{
   // Ask remote client to cleanup security context 'ctx'
   // If 'all', all sec context with the same host as ctx
   // are cleaned.

   AbstractMethod("CleanupSecContext");
   return kFALSE;
}
 TSecContext.cxx:1
 TSecContext.cxx:2
 TSecContext.cxx:3
 TSecContext.cxx:4
 TSecContext.cxx:5
 TSecContext.cxx:6
 TSecContext.cxx:7
 TSecContext.cxx:8
 TSecContext.cxx:9
 TSecContext.cxx:10
 TSecContext.cxx:11
 TSecContext.cxx:12
 TSecContext.cxx:13
 TSecContext.cxx:14
 TSecContext.cxx:15
 TSecContext.cxx:16
 TSecContext.cxx:17
 TSecContext.cxx:18
 TSecContext.cxx:19
 TSecContext.cxx:20
 TSecContext.cxx:21
 TSecContext.cxx:22
 TSecContext.cxx:23
 TSecContext.cxx:24
 TSecContext.cxx:25
 TSecContext.cxx:26
 TSecContext.cxx:27
 TSecContext.cxx:28
 TSecContext.cxx:29
 TSecContext.cxx:30
 TSecContext.cxx:31
 TSecContext.cxx:32
 TSecContext.cxx:33
 TSecContext.cxx:34
 TSecContext.cxx:35
 TSecContext.cxx:36
 TSecContext.cxx:37
 TSecContext.cxx:38
 TSecContext.cxx:39
 TSecContext.cxx:40
 TSecContext.cxx:41
 TSecContext.cxx:42
 TSecContext.cxx:43
 TSecContext.cxx:44
 TSecContext.cxx:45
 TSecContext.cxx:46
 TSecContext.cxx:47
 TSecContext.cxx:48
 TSecContext.cxx:49
 TSecContext.cxx:50
 TSecContext.cxx:51
 TSecContext.cxx:52
 TSecContext.cxx:53
 TSecContext.cxx:54
 TSecContext.cxx:55
 TSecContext.cxx:56
 TSecContext.cxx:57
 TSecContext.cxx:58
 TSecContext.cxx:59
 TSecContext.cxx:60
 TSecContext.cxx:61
 TSecContext.cxx:62
 TSecContext.cxx:63
 TSecContext.cxx:64
 TSecContext.cxx:65
 TSecContext.cxx:66
 TSecContext.cxx:67
 TSecContext.cxx:68
 TSecContext.cxx:69
 TSecContext.cxx:70
 TSecContext.cxx:71
 TSecContext.cxx:72
 TSecContext.cxx:73
 TSecContext.cxx:74
 TSecContext.cxx:75
 TSecContext.cxx:76
 TSecContext.cxx:77
 TSecContext.cxx:78
 TSecContext.cxx:79
 TSecContext.cxx:80
 TSecContext.cxx:81
 TSecContext.cxx:82
 TSecContext.cxx:83
 TSecContext.cxx:84
 TSecContext.cxx:85
 TSecContext.cxx:86
 TSecContext.cxx:87
 TSecContext.cxx:88
 TSecContext.cxx:89
 TSecContext.cxx:90
 TSecContext.cxx:91
 TSecContext.cxx:92
 TSecContext.cxx:93
 TSecContext.cxx:94
 TSecContext.cxx:95
 TSecContext.cxx:96
 TSecContext.cxx:97
 TSecContext.cxx:98
 TSecContext.cxx:99
 TSecContext.cxx:100
 TSecContext.cxx:101
 TSecContext.cxx:102
 TSecContext.cxx:103
 TSecContext.cxx:104
 TSecContext.cxx:105
 TSecContext.cxx:106
 TSecContext.cxx:107
 TSecContext.cxx:108
 TSecContext.cxx:109
 TSecContext.cxx:110
 TSecContext.cxx:111
 TSecContext.cxx:112
 TSecContext.cxx:113
 TSecContext.cxx:114
 TSecContext.cxx:115
 TSecContext.cxx:116
 TSecContext.cxx:117
 TSecContext.cxx:118
 TSecContext.cxx:119
 TSecContext.cxx:120
 TSecContext.cxx:121
 TSecContext.cxx:122
 TSecContext.cxx:123
 TSecContext.cxx:124
 TSecContext.cxx:125
 TSecContext.cxx:126
 TSecContext.cxx:127
 TSecContext.cxx:128
 TSecContext.cxx:129
 TSecContext.cxx:130
 TSecContext.cxx:131
 TSecContext.cxx:132
 TSecContext.cxx:133
 TSecContext.cxx:134
 TSecContext.cxx:135
 TSecContext.cxx:136
 TSecContext.cxx:137
 TSecContext.cxx:138
 TSecContext.cxx:139
 TSecContext.cxx:140
 TSecContext.cxx:141
 TSecContext.cxx:142
 TSecContext.cxx:143
 TSecContext.cxx:144
 TSecContext.cxx:145
 TSecContext.cxx:146
 TSecContext.cxx:147
 TSecContext.cxx:148
 TSecContext.cxx:149
 TSecContext.cxx:150
 TSecContext.cxx:151
 TSecContext.cxx:152
 TSecContext.cxx:153
 TSecContext.cxx:154
 TSecContext.cxx:155
 TSecContext.cxx:156
 TSecContext.cxx:157
 TSecContext.cxx:158
 TSecContext.cxx:159
 TSecContext.cxx:160
 TSecContext.cxx:161
 TSecContext.cxx:162
 TSecContext.cxx:163
 TSecContext.cxx:164
 TSecContext.cxx:165
 TSecContext.cxx:166
 TSecContext.cxx:167
 TSecContext.cxx:168
 TSecContext.cxx:169
 TSecContext.cxx:170
 TSecContext.cxx:171
 TSecContext.cxx:172
 TSecContext.cxx:173
 TSecContext.cxx:174
 TSecContext.cxx:175
 TSecContext.cxx:176
 TSecContext.cxx:177
 TSecContext.cxx:178
 TSecContext.cxx:179
 TSecContext.cxx:180
 TSecContext.cxx:181
 TSecContext.cxx:182
 TSecContext.cxx:183
 TSecContext.cxx:184
 TSecContext.cxx:185
 TSecContext.cxx:186
 TSecContext.cxx:187
 TSecContext.cxx:188
 TSecContext.cxx:189
 TSecContext.cxx:190
 TSecContext.cxx:191
 TSecContext.cxx:192
 TSecContext.cxx:193
 TSecContext.cxx:194
 TSecContext.cxx:195
 TSecContext.cxx:196
 TSecContext.cxx:197
 TSecContext.cxx:198
 TSecContext.cxx:199
 TSecContext.cxx:200
 TSecContext.cxx:201
 TSecContext.cxx:202
 TSecContext.cxx:203
 TSecContext.cxx:204
 TSecContext.cxx:205
 TSecContext.cxx:206
 TSecContext.cxx:207
 TSecContext.cxx:208
 TSecContext.cxx:209
 TSecContext.cxx:210
 TSecContext.cxx:211
 TSecContext.cxx:212
 TSecContext.cxx:213
 TSecContext.cxx:214
 TSecContext.cxx:215
 TSecContext.cxx:216
 TSecContext.cxx:217
 TSecContext.cxx:218
 TSecContext.cxx:219
 TSecContext.cxx:220
 TSecContext.cxx:221
 TSecContext.cxx:222
 TSecContext.cxx:223
 TSecContext.cxx:224
 TSecContext.cxx:225
 TSecContext.cxx:226
 TSecContext.cxx:227
 TSecContext.cxx:228
 TSecContext.cxx:229
 TSecContext.cxx:230
 TSecContext.cxx:231
 TSecContext.cxx:232
 TSecContext.cxx:233
 TSecContext.cxx:234
 TSecContext.cxx:235
 TSecContext.cxx:236
 TSecContext.cxx:237
 TSecContext.cxx:238
 TSecContext.cxx:239
 TSecContext.cxx:240
 TSecContext.cxx:241
 TSecContext.cxx:242
 TSecContext.cxx:243
 TSecContext.cxx:244
 TSecContext.cxx:245
 TSecContext.cxx:246
 TSecContext.cxx:247
 TSecContext.cxx:248
 TSecContext.cxx:249
 TSecContext.cxx:250
 TSecContext.cxx:251
 TSecContext.cxx:252
 TSecContext.cxx:253
 TSecContext.cxx:254
 TSecContext.cxx:255
 TSecContext.cxx:256
 TSecContext.cxx:257
 TSecContext.cxx:258
 TSecContext.cxx:259
 TSecContext.cxx:260
 TSecContext.cxx:261
 TSecContext.cxx:262
 TSecContext.cxx:263
 TSecContext.cxx:264
 TSecContext.cxx:265
 TSecContext.cxx:266
 TSecContext.cxx:267
 TSecContext.cxx:268
 TSecContext.cxx:269
 TSecContext.cxx:270
 TSecContext.cxx:271
 TSecContext.cxx:272
 TSecContext.cxx:273
 TSecContext.cxx:274
 TSecContext.cxx:275
 TSecContext.cxx:276
 TSecContext.cxx:277
 TSecContext.cxx:278
 TSecContext.cxx:279
 TSecContext.cxx:280
 TSecContext.cxx:281
 TSecContext.cxx:282
 TSecContext.cxx:283
 TSecContext.cxx:284
 TSecContext.cxx:285
 TSecContext.cxx:286
 TSecContext.cxx:287
 TSecContext.cxx:288
 TSecContext.cxx:289
 TSecContext.cxx:290
 TSecContext.cxx:291
 TSecContext.cxx:292
 TSecContext.cxx:293
 TSecContext.cxx:294
 TSecContext.cxx:295
 TSecContext.cxx:296
 TSecContext.cxx:297
 TSecContext.cxx:298
 TSecContext.cxx:299
 TSecContext.cxx:300
 TSecContext.cxx:301
 TSecContext.cxx:302
 TSecContext.cxx:303
 TSecContext.cxx:304
 TSecContext.cxx:305
 TSecContext.cxx:306
 TSecContext.cxx:307
 TSecContext.cxx:308
 TSecContext.cxx:309
 TSecContext.cxx:310
 TSecContext.cxx:311
 TSecContext.cxx:312
 TSecContext.cxx:313
 TSecContext.cxx:314
 TSecContext.cxx:315
 TSecContext.cxx:316
 TSecContext.cxx:317
 TSecContext.cxx:318
 TSecContext.cxx:319
 TSecContext.cxx:320
 TSecContext.cxx:321
 TSecContext.cxx:322
 TSecContext.cxx:323
 TSecContext.cxx:324
 TSecContext.cxx:325
 TSecContext.cxx:326
 TSecContext.cxx:327
 TSecContext.cxx:328
 TSecContext.cxx:329
 TSecContext.cxx:330
 TSecContext.cxx:331
 TSecContext.cxx:332