ROOT  6.06/08
Reference Guide
TAuthenticate.cxx
Go to the documentation of this file.
1 // @(#)root/auth:$Id: f2cfa663e232707e1201467b5805ff1d13575326 $
2 // Author: Fons Rademakers 26/11/2000
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 //////////////////////////////////////////////////////////////////////////
13 // //
14 // TAuthenticate //
15 // //
16 // An authentication module for ROOT based network services, like rootd //
17 // and proofd. //
18 // //
19 //////////////////////////////////////////////////////////////////////////
20 
21 #include "RConfigure.h"
22 
23 #include "TAuthenticate.h"
24 #include "TApplication.h"
25 #include "THostAuth.h"
26 #include "TRootSecContext.h"
27 #include "TPluginManager.h"
28 #include "TNetFile.h"
29 #include "TPSocket.h"
30 #include "TMessage.h"
31 #include "TSystem.h"
32 #include "TError.h"
33 #include "Getline.h"
34 #include "TROOT.h"
35 #include "TEnv.h"
36 #include "TList.h"
37 #include "NetErrors.h"
38 #include "TRegexp.h"
39 #include "TVirtualMutex.h"
40 #include "TTimer.h"
41 #include "TBase64.h"
42 
43 #ifndef R__LYNXOS
44 #include <sys/stat.h>
45 #endif
46 #include <errno.h>
47 #include <sys/types.h>
48 #include <time.h>
49 #if !defined(R__WIN32) && !defined(R__MACOSX) && !defined(R__FBSD) && \
50  !defined(R__OBSD)
51 #include <crypt.h>
52 #endif
53 #ifdef WIN32
54 # include <io.h>
55 #endif /* WIN32 */
56 #if defined(R__LINUX) || defined(R__FBSD) || defined(R__OBSD)
57 # include <unistd.h>
58 #endif
59 #include <stdlib.h>
60 #ifndef WIN32
61 # include <sys/time.h>
62 #endif /* WIN32 */
63 
64 #if defined(R__MACOSX)
65 extern "C" char *crypt(const char *, const char *);
66 #endif
67 
68 #ifdef R__GLBS
69 # include <sys/ipc.h>
70 # include <sys/shm.h>
71 #endif
72 
73 #ifdef R__SSL
74 // SSL specific headers
75 # include <openssl/bio.h>
76 # include <openssl/err.h>
77 # include <openssl/pem.h>
78 # include <openssl/rand.h>
79 # include <openssl/rsa.h>
80 # include <openssl/ssl.h>
81 #endif
82 
83 // Statics initialization
84 TList *TAuthenticate::fgAuthInfo = 0;
85 TString TAuthenticate::fgAuthMeth[] = { "UsrPwd", "SRP", "Krb5",
86  "Globus", "SSH", "UidGid" };
93 TDatime TAuthenticate::fgLastAuthrc; // Time of last reading of fgRootAuthrc
95 TPluginHandler *TAuthenticate::fgPasswdDialog = (TPluginHandler *)(-1);
97 TList *TAuthenticate::fgProofAuthInfo = 0;
99 Bool_t TAuthenticate::fgReadHomeAuthrc = kTRUE; // on/off search for $HOME/.rootauthrc
100 TString TAuthenticate::fgRootAuthrc; // Path to last rootauthrc-like file read
101 Int_t TAuthenticate::fgRSAKey = -1; // Default RSA key type to be used
102 Int_t TAuthenticate::fgRSAInit = 0;
104 rsa_KEY_export TAuthenticate::fgRSAPubExport[2] = {{0,0},{0,0}};
106 #ifdef R__SSL
107 BF_KEY TAuthenticate::fgBFKey;
108 #endif
113 Int_t TAuthenticate::fgLastError = -1;
114 Int_t TAuthenticate::fgAuthTO = -2; // Timeout value
115 
116 // ID of the main thread as unique identifier
117 Int_t TAuthenticate::fgProcessID = -1;
118 
119 TVirtualMutex *gAuthenticateMutex = 0;
120 
121 // Standard version of Sec Context match checking
122 Int_t StdCheckSecCtx(const char *, TRootSecContext *);
123 
124 
126 
127 ////////////////////////////////////////////////////////////////////////////////
128 /// rand() implementation using /udev/random or /dev/random, if available
129 
130 static int auth_rand()
131 {
132 #ifndef WIN32
133  int frnd = open("/dev/urandom", O_RDONLY);
134  if (frnd < 0) frnd = open("/dev/random", O_RDONLY);
135  int r;
136  if (frnd >= 0) {
137  ssize_t rs = read(frnd, (void *) &r, sizeof(int));
138  close(frnd);
139  if (r < 0) r = -r;
140  if (rs == sizeof(int)) return r;
141  }
142  Printf("+++ERROR+++ : auth_rand: neither /dev/urandom nor /dev/random are available or readable!");
143  struct timeval tv;
144  if (gettimeofday(&tv,0) == 0) {
145  int t1, t2;
146  memcpy((void *)&t1, (void *)&tv.tv_sec, sizeof(int));
147  memcpy((void *)&t2, (void *)&tv.tv_usec, sizeof(int));
148  r = t1 + t2;
149  if (r < 0) r = -r;
150  return r;
151  }
152  return -1;
153 #else
154  // No special random device available: use rand()
155  return rand();
156 #endif
157 }
158 
159 ////////////////////////////////////////////////////////////////////////////////
160 /// Create authentication object.
161 
162 TAuthenticate::TAuthenticate(TSocket *sock, const char *remote,
163  const char *proto, const char *user)
164 {
165  if (gDebug > 2 && gAuthenticateMutex)
166  Info("Authenticate", "locking mutex (pid: %d)",gSystem->GetPid());
167  R__LOCKGUARD2(gAuthenticateMutex);
168 
169  // In PROOF decode the buffer sent by the client, if any
170  if (gROOT->IsProofServ())
171  ProofAuthSetup();
172 
173  // Use the ID of the starting thread as unique identifier
174  if (fgProcessID < 0)
176 
177  if (fgAuthTO == -2)
178  fgAuthTO = gEnv->GetValue("Auth.Timeout",-1);
179 
180  fSocket = sock;
181  fRemote = remote;
182  fHostAuth = 0;
183  fVersion = 5; // The latest, by default
184  fSecContext = 0;
185 
186  if (gDebug > 2)
187  Info("TAuthenticate", "Enter: local host: %s, user is: %s (proto: %s)",
188  gSystem->HostName(), user, proto);
189 
190  // Set protocol string.
191  // Check if version should be different ...
192  char *pdd;
193  Int_t servtype = TSocket::kSOCKD;
194  if (proto && strlen(proto) > 0) {
195  char *sproto = StrDup(proto);
196  if ((pdd = strstr(sproto, ":")) != 0) {
197  int rproto = atoi(pdd + 1);
198  *pdd = '\0';
199  if (strstr(sproto, "root") != 0) {
200  if (rproto < 12 ) {
201  fVersion = 4;
202  if (rproto < 11 ) {
203  fVersion = 3;
204  if (rproto < 9 ) {
205  fVersion = 2;
206  if (rproto < 8) {
207  fVersion = 1;
208  if (rproto < 6)
209  fVersion = 0;
210  }
211  }
212  }
213  }
214  servtype = TSocket::kROOTD;
215  }
216  if (strstr(sproto, "proof") != 0) {
217  if (rproto < 11) {
218  fVersion = 4;
219  if (rproto < 10) {
220  fVersion = 3;
221  if (rproto < 8) {
222  fVersion = 2;
223  if (rproto < 7)
224  fVersion = 1;
225  }
226  }
227  }
228  servtype = TSocket::kPROOFD;
229  }
230  if (gDebug > 3)
231  Info("TAuthenticate",
232  "service: %s (remote protocol: %d): fVersion: %d", sproto,
233  rproto, fVersion);
234  }
235  fProtocol = sproto;
236  delete [] sproto;
237  }
238 
239  // Check or get user name
240  fUser = "";
241  TString checkUser;
242  if (user && strlen(user) > 0) {
243  fUser = user;
244  checkUser = user;
245  } else {
247  if (u)
248  checkUser = u->fUser;
249  delete u;
250  }
251  fPasswd = "";
252  fPwHash = kFALSE;
253  fSRPPwd = kFALSE;
254 
255  // Type of RSA key
256  if (fgRSAKey < 0) {
257  fgRSAKey = 0; // Default key
258 #ifdef R__SSL
259  // Another choice possible: check user preferences
260  if (gEnv->GetValue("RSA.KeyType",0) == 1)
261  fgRSAKey = 1;
262 #endif
263  }
264  // This is the key actually used: we propose the default
265  // to the server, and behave according to its reply
266  fRSAKey = fgRSAKey;
267  if (gDebug > 3)
268  Info("TAuthenticate","RSA key: default type %d", fgRSAKey);
269 
270  // RSA key generation (one per session)
271  if (!fgRSAInit) {
272  GenRSAKeys();
273  fgRSAInit = 1;
274  }
275 
276  // Check and save the host FQDN ...
277  TString fqdn;
279  if (addr.IsValid())
280  fqdn = addr.GetHostName();
281  TString fqdnsrv;
282  fqdnsrv.Form("%s:%d",fqdn.Data(),servtype);
283 
284  // Read directives from files; re-read if files have changed
286 
287  if (gDebug > 3) {
288  Info("TAuthenticate",
289  "number of HostAuth Instantiations in memory: %d",
290  GetAuthInfo()->GetSize());
291  TAuthenticate::Show("H");
292  TAuthenticate::Show("P");
293  }
294 
295  // Check the list of auth info for already loaded info about this host
296  fHostAuth = GetHostAuth(fqdnsrv, checkUser);
297 
298  // If for whatever (and unlikely) reason nothing has been found
299  // we look for the old envs defaulting to method 0 (UsrPwd)
300  // if they are missing or meaningless
301  if (!fHostAuth) {
302 
303  TString tmp;
304  if (fProtocol.Contains("proof")) {
305  tmp = TString(gEnv->GetValue("Proofd.Authentication", "0"));
306  } else if (fProtocol.Contains("root")) {
307  tmp = TString(gEnv->GetValue("Rootd.Authentication", "0"));
308  }
309  char am[kMAXSEC][10];
310  Int_t nw = sscanf(tmp.Data(), "%5s %5s %5s %5s %5s %5s",
311  am[0], am[1], am[2], am[3], am[4], am[5]);
312 
313  Int_t i = 0, nm = 0, me[kMAXSEC];
314  for( ; i < nw; i++) {
315  Int_t met = -1;
316  if (strlen(am[i]) > 1) {
317  met = GetAuthMethodIdx(am[i]);
318  } else {
319  met = atoi(am[i]);
320  }
321  if (met > -1 && met < kMAXSEC) {
322  me[nm++] = met;
323  }
324  }
325 
326  // Create THostAuth
327  if (nm)
328  fHostAuth = new THostAuth(fRemote,fUser,nm,me,0);
329  else
330  fHostAuth = new THostAuth(fRemote,fUser,0,(const char *)0);
331  }
332 
333  //
334  // If generic THostAuth (i.e. with wild card or user == any)
335  // make a personalized memory copy of this THostAuth
336  if (strchr(fHostAuth->GetHost(),'*') || strchr(fHostAuth->GetHost(),'*') ||
337  fHostAuth->GetServer() == -1 ) {
338  fHostAuth = new THostAuth(*fHostAuth);
339  fHostAuth->SetHost(fqdn);
340  fHostAuth->SetUser(checkUser);
341  fHostAuth->SetServer(servtype);
342  }
343 
344  // If a specific method has been requested via the protocol
345  // set it as first
346  Int_t sec = -1;
347  TString tmp = fProtocol;
348  tmp.ReplaceAll("root",4,"",0);
349  tmp.ReplaceAll("proof",5,"",0);
350  tmp.ReplaceAll("sock",4,"",0);
351  if (!strncmp(tmp.Data(),"up",2))
352  sec = 0;
353  else if (!strncmp(tmp.Data(),"s",1))
354  sec = 1;
355  else if (!strncmp(tmp.Data(),"k",1))
356  sec = 2;
357  else if (!strncmp(tmp.Data(),"g",1))
358  sec = 3;
359  else if (!strncmp(tmp.Data(),"h",1))
360  sec = 4;
361  else if (!strncmp(tmp.Data(),"ug",2))
362  sec = 5;
363  if (sec > -1 && sec < kMAXSEC) {
364  if (fHostAuth->HasMethod(sec)) {
365  fHostAuth->SetFirst(sec);
366  } else {
367  char *dtmp = GetDefaultDetails(sec, 1, checkUser);
368  TString det(dtmp);
369  fHostAuth->AddFirst(sec, det);
370  if (dtmp)
371  delete [] dtmp;
372  }
373  }
374 
375  // This is what we have in memory
376  if (gDebug > 3) {
377  TIter next(fHostAuth->Established());
378  TRootSecContext *ctx;
379  while ((ctx = (TRootSecContext *) next()))
380  ctx->Print("0");
381  }
382 }
383 
384 ////////////////////////////////////////////////////////////////////////////////
385 /// Called in connection with a timer timeout
386 
388 {
389  Info("CatchTimeOut", "%d sec timeout expired (protocol: %s)",
391 
392  fTimeOut = 1;
393  if (fSocket)
394  fSocket->Close("force");
395 
396  return;
397 }
398 
399 ////////////////////////////////////////////////////////////////////////////////
400 /// Authenticate to remote rootd or proofd server. Return kTRUE if
401 /// authentication succeeded.
402 
404 {
405  if (gDebug > 2 && gAuthenticateMutex)
406  Info("Authenticate", "locking mutex (pid: %d)",gSystem->GetPid());
407  R__LOCKGUARD2(gAuthenticateMutex);
408 
409  Bool_t rc = kFALSE;
410  Int_t st = -1;
411  Int_t remMeth = 0, rMth[kMAXSEC], tMth[kMAXSEC] = {0};
412  Int_t meth = 0;
413  char noSupport[80] = { 0 };
414  char triedMeth[80] = { 0 };
415  Int_t ntry = 0;
416 
417  TString user, passwd;
418  Bool_t pwhash;
419 
420  if (gDebug > 2)
421  Info("Authenticate", "enter: fUser: %s", fUser.Data());
422 
423  //
424  // Setup timeout timer, if required
425  TTimer *alarm = 0;
426  if (fgAuthTO > 0) {
427  alarm = new TTimer(0, kFALSE);
428  alarm->SetInterruptSyscalls();
429  // The method CatchTimeOut will be called at timeout
430  alarm->Connect("Timeout()", "TAuthenticate", this, "CatchTimeOut()");
431  }
432 
433 negotia:
434  st = -1;
435  tMth[meth] = 1;
436  ntry++;
437  if (gDebug > 2)
438  Info("Authenticate", "try #: %d", ntry);
439 
440  user = "";
441  passwd = "";
442  pwhash = kFALSE;
443 
444  // Security level from the list (if not in cleanup mode ...)
447  if (gDebug > 2)
448  Info("Authenticate",
449  "trying authentication: method:%d, default details:%s",
450  fSecurity, fDetails.Data());
451 
452  // Keep track of tried methods in a list
453  if (strlen(triedMeth) > 0)
454  snprintf(triedMeth, 80, "%s %s", triedMeth, fgAuthMeth[fSecurity].Data());
455  else
456  snprintf(triedMeth, 80, "%s", fgAuthMeth[fSecurity].Data());
457 
458  // Set environments
459  SetEnvironment();
460 
461  st = -1;
462 
463  //
464  // Reset timeout variables and start timer
465  fTimeOut = 0;
466  if (fgAuthTO > 0 && alarm) {
467  alarm->Start(fgAuthTO*1000, kTRUE);
468  }
469 
470  // Auth calls depend of fSec
471  if (fSecurity == kClear) {
472 
473  rc = kFALSE;
474 
475  // UsrPwd Authentication
476  user = fgDefaultUser;
477  if (user != "")
478  CheckNetrc(user, passwd, pwhash, kFALSE);
479  if (passwd == "") {
480  if (fgPromptUser) {
481  char *u = PromptUser(fRemote);
482  user = u;
483  delete[] u;
484  }
485  rc = GetUserPasswd(user, passwd, pwhash, kFALSE);
486  }
487  fUser = user;
488  fPasswd = passwd;
489 
490  if (!rc) {
491 
492  if (fUser != "root")
493  st = ClearAuth(user, passwd, pwhash);
494  } else {
495  Error("Authenticate",
496  "unable to get user name for UsrPwd authentication");
497  }
498 
499  } else if (fSecurity == kSRP) {
500 
501  rc = kFALSE;
502 
503  // SRP Authentication
504  user = fgDefaultUser;
505  if (user != "")
506  CheckNetrc(user, passwd, pwhash, kTRUE);
507  if (passwd == "") {
508  if (fgPromptUser) {
509  char *p = PromptUser(fRemote);
510  user = p;
511  delete [] p;
512  }
513  rc = GetUserPasswd(user, passwd, pwhash, kTRUE);
514  }
515  fUser = user;
516  fPasswd = passwd;
517 
518  if (!fgSecAuthHook) {
519 
520  char *p;
521  TString lib = "libSRPAuth";
522  if ((p = gSystem->DynamicPathName(lib, kTRUE))) {
523  delete [] p;
524  gSystem->Load(lib);
525  }
526  }
527  if (!rc && fgSecAuthHook) {
528 
529  st = (*fgSecAuthHook) (this, user, passwd, fRemote, fDetails,
530  fVersion);
531  } else {
532  if (!fgSecAuthHook)
533  Error("Authenticate",
534  "no support for SRP authentication available");
535  if (rc)
536  Error("Authenticate",
537  "unable to get user name for SRP authentication");
538  }
539  // Fill present user info ...
540  if (st == 1) {
541  fPwHash = kFALSE;
542  fSRPPwd = kTRUE;
543  }
544 
545  } else if (fSecurity == kKrb5) {
546 
547  if (fVersion > 0) {
548 
549  // Kerberos 5 Authentication
550  if (!fgKrb5AuthHook) {
551  char *p;
552  TString lib = "libKrb5Auth";
553  if ((p = gSystem->DynamicPathName(lib, kTRUE))) {
554  delete [] p;
555  gSystem->Load(lib);
556  }
557  }
558  if (fgKrb5AuthHook) {
560  st = (*fgKrb5AuthHook) (this, fUser, fDetails, fVersion);
561  } else {
562  Error("Authenticate",
563  "support for kerberos5 auth locally unavailable");
564  }
565  } else {
566  if (gDebug > 0)
567  Info("Authenticate",
568  "remote daemon does not support Kerberos authentication");
569  if (strlen(noSupport) > 0)
570  snprintf(noSupport, 80, "%s/Krb5", noSupport);
571  else
572  snprintf(noSupport, 80, "Krb5");
573  }
574 
575  } else if (fSecurity == kGlobus) {
576  if (fVersion > 1) {
577 
578  // Globus Authentication
579  if (!fgGlobusAuthHook) {
580  char *p;
581  TString lib = "libGlobusAuth";
582  if ((p = gSystem->DynamicPathName(lib, kTRUE))) {
583  delete [] p;
584  gSystem->Load(lib);
585  }
586  }
587  if (fgGlobusAuthHook) {
588  st = (*fgGlobusAuthHook) (this, fUser, fDetails);
589  } else {
590  Error("Authenticate",
591  "no support for Globus authentication available");
592  }
593  } else {
594  if (gDebug > 0)
595  Info("Authenticate",
596  "remote daemon does not support Globus authentication");
597  if (strlen(noSupport) > 0)
598  snprintf(noSupport, 80, "%s/Globus", noSupport);
599  else
600  snprintf(noSupport, 80, "Globus");
601  }
602 
603 
604  } else if (fSecurity == kSSH) {
605 
606  if (fVersion > 1) {
607 
608  // SSH Authentication
609  st = SshAuth(fUser);
610 
611  } else {
612  if (gDebug > 0)
613  Info("Authenticate",
614  "remote daemon does not support SSH authentication");
615  if (strlen(noSupport) > 0)
616  snprintf(noSupport, 80, "%s/SSH", noSupport);
617  else
618  snprintf(noSupport, 80, "SSH");
619  }
620 
621  } else if (fSecurity == kRfio) {
622 
623  if (fVersion > 1) {
624 
625  // UidGid Authentication
626  st = RfioAuth(fUser);
627 
628  } else {
629  if (gDebug > 0)
630  Info("Authenticate",
631  "remote daemon does not support UidGid authentication");
632  if (strlen(noSupport) > 0)
633  snprintf(noSupport, 80, "%s/UidGid", noSupport);
634  else
635  snprintf(noSupport, 80, "UidGid");
636  }
637  }
638  //
639  // Stop timer
640  if (alarm) alarm->Stop();
641 
642  // Flag timeout condition
643  st = (fTimeOut > 0) ? -3 : st;
644 
645  //
646  // Analyse the result now ...
647  // Type of action after the analysis:
648  // 0 = return, 1 = negotiation, 2 = send kROOTD_BYE + 3,
649  // 3 = print failure and return
650  Int_t action = 0;
651  Int_t nmet = fHostAuth->NumMethods();
652  Int_t remloc = nmet - ntry;
653  if (gDebug > 0)
654  Info("Authenticate","remloc: %d, ntry: %d, meth: %d, fSecurity: %d",
655  remloc, ntry, meth, fSecurity);
656  Int_t kind, stat;
657  switch (st) {
658 
659  case 1:
660  //
661  // Success
662  fHostAuth->CountSuccess((Int_t)fSecurity);
663  if (gDebug > 2)
664  fSecContext->Print();
665  if (fSecContext->IsActive())
668  rc = kTRUE;
669  break;
670 
671  case 0:
672  //
673  // Failure
674  fHostAuth->CountFailure((Int_t)fSecurity);
675  if (fVersion < 2) {
676  //
677  // Negotiation not supported by old daemons ...
678  if (gDebug > 2)
679  Info("Authenticate",
680  "negotiation not supported remotely: try next method, if any");
681  if (meth < nmet - 1) {
682  meth++;
683  action = 1;
684  } else {
685  action = 2;
686  }
687  rc = kFALSE;
688  break;
689  }
690  //
691  // Attempt negotiation ...
692  if (fSocket->Recv(stat, kind) < 0) {
693  action = 0;
694  rc = kFALSE;
695  }
696  if (gDebug > 2)
697  Info("Authenticate",
698  "after failed attempt: kind= %d, stat= %d", kind, stat);
699  if (kind == kROOTD_ERR) {
700  action = 2;
701  rc = kFALSE;
702  } else if (kind == kROOTD_NEGOTIA) {
703  if (stat > 0) {
704  int len = 3 * stat;
705  char *answer = new char[len];
706  int nrec = fSocket->Recv(answer, len, kind); // returns user
707  if (nrec < 0) {
708  action = 0;
709  rc = kFALSE;
710  break;
711  }
712  if (kind != kMESS_STRING)
713  Warning("Authenticate",
714  "strings with accepted methods not received (%d:%d)",
715  kind, nrec);
716  remMeth =
717  sscanf(answer, "%d %d %d %d %d %d", &rMth[0], &rMth[1],
718  &rMth[2], &rMth[3], &rMth[4], &rMth[5]);
719  if (gDebug > 0 && remloc > 0)
720  Info("Authenticate",
721  "remotely allowed methods not yet tried: %s",
722  answer);
723  delete[] answer;
724  } else if (stat == 0) {
725  Info("Authenticate",
726  "no more methods accepted remotely to be tried");
727  action = 3;
728  rc = kFALSE;
729  break;
730  }
731  // If no more local methods, return
732  if (remloc < 1) {
733  action = 2;
734  rc = kFALSE;
735  break;
736  }
737  // Look if a non-tried method matches
738  int i, j;
739  char locav[40] = { 0 };
740  Bool_t methfound = kFALSE;
741  for (i = 0; i < remMeth; i++) {
742  for (j = 0; j < nmet; j++) {
743  if (fHostAuth->GetMethod(j) == rMth[i] && tMth[j] == 0) {
744  meth = j;
745  action = 1;
746  methfound = kTRUE;
747  break;
748  }
749  if (i == 0)
750  snprintf(locav, 40, "%s %d", locav, fHostAuth->GetMethod(j));
751  }
752  if (methfound) break;
753  }
754  if (methfound) break;
755  //
756  // No method left to be tried: notify and exit
757  if (gDebug > 0)
758  Warning("Authenticate",
759  "no match with those locally available: %s", locav);
760  action = 2;
761  rc = kFALSE;
762  break;
763  } else { // unknown message code at this stage
764  action = 3;
765  rc = kFALSE;
766  break;
767  }
768  break;
769 
770  case -1:
771  //
772  // Method not supported
773  fHostAuth->CountFailure((Int_t)fSecurity);
774  if (gDebug > 2)
775  Info("Authenticate",
776  "method not even started: insufficient or wrong info: %s",
777  "try with next method, if any");
778  fHostAuth->RemoveMethod(fSecurity);
779  nmet--;
780  if (nmet > 0) {
781  action = 1;
782  } else
783  action = 2;
784 
785  break;
786 
787  case -2:
788  //
789  // Remote host does not accepts connections from local host
790  fHostAuth->CountFailure((Int_t)fSecurity);
791  if (fVersion <= 2)
792  if (gDebug > 2)
793  Warning("Authenticate",
794  "status code -2 not expected from old daemons");
795  rc = kFALSE;
796  break;
797 
798  case -3:
799  //
800  // Timeout: we set the method as last one, should the caller
801  // decide to retry, if it will attempt first something else.
802  // (We can not retry directly, because the server will not be
803  // synchronized ...)
804  fHostAuth->CountFailure((Int_t)fSecurity);
805  if (gDebug > 2)
806  Info("Authenticate", "got a timeout");
807  fHostAuth->SetLast(fSecurity);
808  if (meth < nmet - 1) {
809  fTimeOut = 2;
810  } else
811  fTimeOut = 1;
812  rc = kFALSE;
813  break;
814 
815  default:
816  fHostAuth->CountFailure((Int_t)fSecurity);
817  if (gDebug > 2)
818  Info("Authenticate", "unknown status code: %d - assume failure",st);
819  rc = kFALSE;
820  action = 0;
821  break;
822  }
823 
824  switch (action) {
825  case 1:
826  goto negotia;
827  // No break but we go away anyhow
828  case 2:
829  fSocket->Send("0", kROOTD_BYE);
830  // fallthrough
831  case 3:
832  if (strlen(noSupport) > 0)
833  Info("Authenticate", "attempted methods %s are not supported"
834  " by remote server version", noSupport);
835  Info("Authenticate",
836  "failure: list of attempted methods: %s", triedMeth);
837  AuthError("Authenticate",-1);
838  rc = kFALSE;
839  break;
840  default:
841  break;
842  }
843 
844  // Cleanup timer
845  if (alarm)
846  SafeDelete(alarm);
847 
848  return rc;
849 
850 }
851 
852 ////////////////////////////////////////////////////////////////////////////////
853 /// Set default authentication environment. The values are inferred
854 /// from fSecurity and fDetails.
855 
857 {
858  R__LOCKGUARD2(gAuthenticateMutex);
859 
860  if (gDebug > 2)
861  Info("SetEnvironment",
862  "setting environment: fSecurity:%d, fDetails:%s", fSecurity,
863  fDetails.Data());
864 
865  // Defaults
867  if (fSecurity == kKrb5 ||
868  (fSecurity == kGlobus && gROOT->IsProofServ()))
870  else
871  fgAuthReUse = kTRUE;
873 
874  // Decode fDetails, is non empty ...
875  if (fDetails != "") {
876  char usdef[kMAXPATHLEN] = { 0 };
877  char pt[5] = { 0 }, ru[5] = { 0 };
878  Int_t hh = 0, mm = 0;
879  char us[kMAXPATHLEN] = {0}, cp[kMAXPATHLEN] = {0}, pp[kMAXPATHLEN] = {0};
880  char cd[kMAXPATHLEN] = {0}, cf[kMAXPATHLEN] = {0}, kf[kMAXPATHLEN] = {0}, ad[kMAXPATHLEN] = {0};
881  const char *ptr;
882 
883  TString usrPromptDef = TString(GetAuthMethod(fSecurity)) + ".LoginPrompt";
884  if ((ptr = strstr(fDetails, "pt:")) != 0) {
885  sscanf(ptr + 3, "%4s %8191s", pt, usdef);
886  } else {
887  if (!strncasecmp(gEnv->GetValue(usrPromptDef,""),"no",2) ||
888  !strncmp(gEnv->GetValue(usrPromptDef,""),"0",1))
889  strncpy(pt,"0",1);
890  else
891  strncpy(pt,"1",1);
892  }
893  TString usrReUseDef = TString(GetAuthMethod(fSecurity)) + ".ReUse";
894  if ((ptr = strstr(fDetails, "ru:")) != 0) {
895  sscanf(ptr + 3, "%4s %8191s", ru, usdef);
896  } else {
897  if (!strncasecmp(gEnv->GetValue(usrReUseDef,""),"no",2) ||
898  !strncmp(gEnv->GetValue(usrReUseDef,""),"0",1))
899  strncpy(ru,"0",1);
900  else
901  strncpy(ru,"1",1);
902  }
903  TString usrValidDef = TString(GetAuthMethod(fSecurity)) + ".Valid";
904  TString hours(gEnv->GetValue(usrValidDef,"24:00"));
905  Int_t pd = 0;
906  if ((pd = hours.Index(":")) > -1) {
907  TString minutes = hours;
908  hours.Resize(pd);
909  minutes.Replace(0,pd+1,"");
910  hh = atoi(hours.Data());
911  mm = atoi(minutes.Data());
912  } else {
913  hh = atoi(hours.Data());
914  mm = 0;
915  }
916 
917  // Now action depends on method ...
918  if (fSecurity == kGlobus) {
919  if ((ptr = strstr(fDetails, "cd:")) != 0)
920  sscanf(ptr, "%8191s %8191s", cd, usdef);
921  if ((ptr = strstr(fDetails, "cf:")) != 0)
922  sscanf(ptr, "%8191s %8191s", cf, usdef);
923  if ((ptr = strstr(fDetails, "kf:")) != 0)
924  sscanf(ptr, "%8191s %8191s", kf, usdef);
925  if ((ptr = strstr(fDetails, "ad:")) != 0)
926  sscanf(ptr, "%8191s %8191s", ad, usdef);
927  if (gDebug > 2) {
928  Info("SetEnvironment",
929  "details:%s, pt:%s, ru:%s, cd:%s, cf:%s, kf:%s, ad:%s",
930  fDetails.Data(), pt, ru, cd, cf, kf, ad);
931  }
932  } else if (fSecurity == kClear) {
933  if ((ptr = strstr(fDetails, "us:")) != 0)
934  sscanf(ptr + 3, "%8191s %8191s", us, usdef);
935  if ((ptr = strstr(fDetails, "cp:")) != 0)
936  sscanf(ptr + 3, "%8191s %8191s", cp, usdef);
937  if (gDebug > 2)
938  Info("SetEnvironment", "details:%s, pt:%s, ru:%s, us:%s cp:%s",
939  fDetails.Data(), pt, ru, us, cp);
940  } else if (fSecurity == kKrb5) {
941  if ((ptr = strstr(fDetails, "us:")) != 0)
942  sscanf(ptr + 3, "%8191s %8191s", us, usdef);
943  if ((ptr = strstr(fDetails, "pp:")) != 0)
944  sscanf(ptr + 3, "%8191s %8191s", pp, usdef);
945  if (gDebug > 2)
946  Info("SetEnvironment", "details:%s, pt:%s, ru:%s, us:%s pp:%s",
947  fDetails.Data(), pt, ru, us, pp);
948  } else {
949  if ((ptr = strstr(fDetails, "us:")) != 0)
950  sscanf(ptr + 3, "%8191s %8191s", us, usdef);
951  if (gDebug > 2)
952  Info("SetEnvironment", "details:%s, pt:%s, ru:%s, us:%s",
953  fDetails.Data(), pt, ru, us);
954  }
955 
956  // Set Prompt flag
957  if (!strncasecmp(pt, "yes",3) || !strncmp(pt, "1", 1))
959 
960  // Set ReUse flag
961  if (fSecurity == kKrb5) {
963  if (!strncasecmp(ru, "yes",3) || !strncmp(ru, "1",1))
964  fgAuthReUse = kTRUE;
965  } else {
966  if (fSecurity != kGlobus || !(gROOT->IsProofServ())) {
967  fgAuthReUse = kTRUE;
968  if (!strncasecmp(ru, "no",2) || !strncmp(ru, "0",1))
970  }
971  }
972 
973  // Set Expiring date
974  fgExpDate = TDatime();
975  fgExpDate.Set(fgExpDate.Convert() + hh*3600 + mm*60);
976 
977  // UnSet Crypt flag for UsrPwd, if requested
978  if (fSecurity == kClear) {
980  if (!strncmp(cp, "no", 2) || !strncmp(cp, "0", 1))
982  }
983  // Build UserDefaults
984  usdef[0] = '\0';
985  if (fSecurity == kGlobus) {
986  if (strlen(cd) > 0) { snprintf(usdef,8192," %s",cd); }
987  if (strlen(cf) > 0) { snprintf(usdef,8192,"%s %s",usdef, cf); }
988  if (strlen(kf) > 0) { snprintf(usdef,8192,"%s %s",usdef, kf); }
989  if (strlen(ad) > 0) { snprintf(usdef,8192,"%s %s",usdef, ad); }
990  } else {
991  if (fSecurity == kKrb5) {
992  // Collect info about principal, if any
993  if (strlen(pp) > 0) {
994  fgKrb5Principal = TString(pp);
995  } else {
996  // Allow specification via 'us:' key
997  if (strlen(us) > 0 && strstr(us,"@"))
998  fgKrb5Principal = TString(us);
999  }
1000  // command line user specification (fUser) gets highest priority
1001  if (fUser.Length()) {
1002  snprintf(usdef, kMAXPATHLEN, "%s", fUser.Data());
1003  } else {
1004  if (strlen(us) > 0 && !strstr(us,"@"))
1005  snprintf(usdef, kMAXPATHLEN, "%s", us);
1006  }
1007  } else {
1008  // give highest priority to command-line specification
1009  if (fUser == "") {
1010  if (strlen(us) > 0) snprintf(usdef, kMAXPATHLEN, "%s", us);
1011  } else
1012  snprintf(usdef, kMAXPATHLEN, "%s", fUser.Data());
1013  }
1014  }
1015  if (strlen(usdef) > 0) {
1016  fgDefaultUser = usdef;
1017  } else {
1018  if (fgUser != "") {
1019  fgDefaultUser = fgUser;
1020  } else {
1022  if (u)
1023  fgDefaultUser = u->fUser;
1024  delete u;
1025  }
1026  }
1027  if (fgDefaultUser == "anonymous" || fgDefaultUser == "rootd" ||
1028  fgUser != "" || fUser != "") {
1029  // when set by user don't prompt for it anymore
1030  fgPromptUser = kFALSE;
1031  }
1032 
1033  if (gDebug > 2)
1034  Info("SetEnvironment", "usdef:%s", fgDefaultUser.Data());
1035  }
1036 }
1037 
1038 ////////////////////////////////////////////////////////////////////////////////
1039 /// Try to get user name and passwd from several sources.
1040 
1042  Bool_t &pwhash, Bool_t srppwd)
1043 {
1044  if (gDebug > 3)
1045  Info("GetUserPasswd", "Enter: User: '%s' Hash:%d SRP:%d",
1046  user.Data(),(Int_t)pwhash,(Int_t)srppwd);
1047 
1048  // Get user and passwd set via static functions SetUser and SetPasswd.
1049  if (user == "") {
1050  if (fgUser != "")
1051  user = fgUser;
1052  if (passwd == "" && fgPasswd != "" && srppwd == fgSRPPwd) {
1053  passwd = fgPasswd;
1054  pwhash = fgPwHash;
1055  }
1056  } else {
1057  if (fgUser != "" && user == fgUser) {
1058  if (passwd == "" && fgPasswd != "" && srppwd == fgSRPPwd) {
1059  passwd = fgPasswd;
1060  pwhash = fgPwHash;
1061  }
1062  }
1063  }
1064  if (gDebug > 3)
1065  Info("GetUserPasswd", "In memory: User: '%s' Hash:%d",
1066  user.Data(),(Int_t)pwhash);
1067 
1068  // Check system info for user if still not defined
1069  if (user == "") {
1071  if (u)
1072  user = u->fUser;
1073  delete u;
1074  if (gDebug > 3)
1075  Info("GetUserPasswd", "In memory: User: '%s' Hash:%d",
1076  user.Data(),(Int_t)pwhash);
1077  }
1078 
1079  // Check ~/.rootnetrc and ~/.netrc files if user was not set via
1080  // the static SetUser() method.
1081  if (user == "" || passwd == "") {
1082  if (gDebug > 3)
1083  Info("GetUserPasswd", "Checking .netrc family ...");
1084  CheckNetrc(user, passwd, pwhash, srppwd);
1085  }
1086  if (gDebug > 3)
1087  Info("GetUserPasswd", "From .netrc family: User: '%s' Hash:%d",
1088  user.Data(),(Int_t)pwhash);
1089 
1090  // If user also not set via ~/.rootnetrc or ~/.netrc ask user.
1091  if (user == "") {
1092  char *p = PromptUser(fRemote);
1093  user = p;
1094  delete [] p;
1095  if (user == "") {
1096  Error("GetUserPasswd", "user name not set");
1097  return 1;
1098  }
1099  }
1100 
1101  return 0;
1102 }
1103 
1104 ////////////////////////////////////////////////////////////////////////////////
1105 /// Try to get user name and passwd from the ~/.rootnetrc or
1106 /// ~/.netrc files. For more info see the version with 4 arguments.
1107 /// This version is maintained for backward compatability reasons.
1108 
1110 {
1111  Bool_t hash, srppwd;
1112 
1113  // Set srppwd flag
1114  srppwd = (fSecurity == kSRP) ? kTRUE : kFALSE;
1115 
1116  return CheckNetrc(user, passwd, hash, srppwd);
1117 }
1118 
1119 ////////////////////////////////////////////////////////////////////////////////
1120 /// Try to get user name and passwd from the ~/.rootnetrc or
1121 /// ~/.netrc files. First ~/.rootnetrc is tried, after that ~/.netrc.
1122 /// These files will only be used when their access masks are 0600.
1123 /// Returns kTRUE if user and passwd were found for the machine
1124 /// specified in the URL. If kFALSE, user and passwd are "".
1125 /// If srppwd == kTRUE then a SRP ('secure') pwd is searched for in
1126 /// the files.
1127 /// The boolean pwhash is set to kTRUE if the returned passwd is to
1128 /// be understood as password hash, i.e. if the 'password-hash' keyword
1129 /// is found in the 'machine' lines; not implemented for 'secure'
1130 /// and the .netrc file.
1131 /// The format of these files are:
1132 ///
1133 /// # this is a comment line
1134 /// machine <machine fqdn> login <user> password <passwd>
1135 /// machine <machine fqdn> login <user> password-hash <passwd>
1136 ///
1137 /// and in addition ~/.rootnetrc also supports:
1138 ///
1139 /// secure <machine fqdn> login <user> password <passwd>
1140 ///
1141 /// <machine fqdn> may be a domain name or contain the wild card '*'.
1142 ///
1143 /// for the secure protocols. All lines must start in the first column.
1144 
1146  Bool_t &pwhash, Bool_t srppwd)
1147 {
1148  Bool_t result = kFALSE;
1149  Bool_t first = kTRUE;
1150  TString remote = fRemote;
1151 
1152  passwd = "";
1153  pwhash = kFALSE;
1154 
1155  char *net =
1156  gSystem->ConcatFileName(gSystem->HomeDirectory(), ".rootnetrc");
1157 
1158  // Determine FQDN of the host ...
1160  if (addr.IsValid())
1161  remote = addr.GetHostName();
1162 
1163 again:
1164  // Only use file when its access rights are 0600
1165  FileStat_t buf;
1166  if (gSystem->GetPathInfo(net, buf) == 0) {
1167 #ifdef WIN32
1168  // Since Win32 does not have proper protections use file always
1169  if (R_ISREG(buf.fMode) && !R_ISDIR(buf.fMode)) {
1170 #else
1171  if (R_ISREG(buf.fMode) && !R_ISDIR(buf.fMode) &&
1172  (buf.fMode & 0777) == (kS_IRUSR | kS_IWUSR)) {
1173 #endif
1174  FILE *fd = fopen(net, "r");
1175  char line[256];
1176  while (fgets(line, sizeof(line), fd) != 0) {
1177  if (line[0] == '#')
1178  continue;
1179  char word[6][64];
1180  int nword = sscanf(line, "%63s %63s %63s %63s %63s %63s",
1181  word[0], word[1], word[2], word[3], word[4], word[5]);
1182  if (nword != 6)
1183  continue;
1184  if (srppwd && strcmp(word[0], "secure"))
1185  continue;
1186  if (!srppwd && strcmp(word[0], "machine"))
1187  continue;
1188  if (strcmp(word[2], "login"))
1189  continue;
1190  if (srppwd && strcmp(word[4], "password"))
1191  continue;
1192  if (!srppwd &&
1193  strcmp(word[4], "password") && strcmp(word[4], "password-hash"))
1194  continue;
1195 
1196  // Treat the host name found in file as a regular expression
1197  // with '*' as a wild card
1198  TString href(word[1]);
1199  href.ReplaceAll("*",".*");
1200  TRegexp rg(href);
1201  if (remote.Index(rg) != kNPOS) {
1202  if (user == "") {
1203  user = word[3];
1204  passwd = word[5];
1205  if (!strcmp(word[4], "password-hash"))
1206  pwhash = kTRUE;
1207  result = kTRUE;
1208  break;
1209  } else {
1210  if (!strcmp(word[3], user.Data())) {
1211  passwd = word[5];
1212  if (!strcmp(word[4], "password-hash"))
1213  pwhash = kTRUE;
1214  result = kTRUE;
1215  break;
1216  }
1217  }
1218  }
1219  }
1220  fclose(fd);
1221  } else
1222  Warning("CheckNetrc",
1223  "file %s exists but has not 0600 permission", net);
1224  }
1225  delete [] net;
1226 
1227  if (first && !srppwd && !result) {
1228  net = gSystem->ConcatFileName(gSystem->HomeDirectory(), ".netrc");
1229  first = kFALSE;
1230  goto again;
1231  }
1232 
1233  return result;
1234  }
1235 
1236 ////////////////////////////////////////////////////////////////////////////////
1237 /// Static method returning the global user.
1238 
1240 {
1241  return fgUser;
1242 }
1243 
1244 ////////////////////////////////////////////////////////////////////////////////
1245 /// Static method returning the global password hash flag.
1246 
1248 {
1249  return fgPwHash;
1250 }
1251 
1252 ////////////////////////////////////////////////////////////////////////////////
1253 /// Static method returning the global SRP password flag.
1254 
1256 {
1257  return fgSRPPwd;
1258 }
1259 
1260 ////////////////////////////////////////////////////////////////////////////////
1261 /// Static method returning default expiring date for new validity contexts
1262 
1264 {
1265  return fgExpDate;
1266 }
1267 
1268 ////////////////////////////////////////////////////////////////////////////////
1269 /// Static method returning the default user information.
1270 
1272 {
1273  return fgDefaultUser;
1274 }
1275 
1276 ////////////////////////////////////////////////////////////////////////////////
1277 /// Static method returning the principal to be used to init Krb5 tickets.
1278 
1280 {
1281  return fgKrb5Principal;
1282 }
1283 
1284 ////////////////////////////////////////////////////////////////////////////////
1285 /// Static method returning the authentication reuse settings.
1286 
1288 {
1289  return fgAuthReUse;
1290 }
1291 
1292 ////////////////////////////////////////////////////////////////////////////////
1293 /// Static method returning the prompt user settings.
1294 
1296 {
1297  return fgPromptUser;
1298 }
1299 
1300 ////////////////////////////////////////////////////////////////////////////////
1301 /// Static method returning the method corresponding to idx.
1302 
1304 {
1305  R__LOCKGUARD2(gAuthenticateMutex);
1306 
1307  if (idx < 0 || idx > kMAXSEC-1) {
1308  ::Error("Authenticate::GetAuthMethod", "idx out of bounds (%d)", idx);
1309  idx = 0;
1310  }
1311  return fgAuthMeth[idx];
1312 }
1313 
1314 ////////////////////////////////////////////////////////////////////////////////
1315 /// Static method returning the method index (which can be used to find
1316 /// the method in GetAuthMethod()). Returns -1 in case meth is not found.
1317 
1319 {
1320  R__LOCKGUARD2(gAuthenticateMutex);
1321 
1322  if (meth && meth[0]) {
1323  for (Int_t i = 0; i < kMAXSEC; i++) {
1324  if (!fgAuthMeth[i].CompareTo(meth, TString::kIgnoreCase))
1325  return i;
1326  }
1327  }
1328 
1329  return -1;
1330 }
1331 
1332 ////////////////////////////////////////////////////////////////////////////////
1333 /// Static method to prompt for the user name to be used for authentication
1334 /// to rootd or proofd. User is asked to type user name.
1335 /// Returns user name (which must be deleted by caller) or 0.
1336 /// If non-interactive run (eg ProofServ) returns default user.
1337 
1338 char *TAuthenticate::PromptUser(const char *remote)
1339 {
1340  R__LOCKGUARD2(gAuthenticateMutex);
1341 
1342  const char *user;
1343  if (fgDefaultUser != "")
1344  user = fgDefaultUser;
1345  else
1346  user = gSystem->Getenv("USER");
1347 #ifdef R__WIN32
1348  if (!user)
1349  user = gSystem->Getenv("USERNAME");
1350 #endif
1351  if (isatty(0) == 0 || isatty(1) == 0) {
1352  ::Warning("TAuthenticate::PromptUser",
1353  "not tty: cannot prompt for user, returning default");
1354  if (strlen(user))
1355  return StrDup(user);
1356  else
1357  return StrDup("None");
1358  }
1359 
1360  const char *usrIn = Getline(Form("Name (%s:%s): ", remote, user));
1361  if (usrIn[0]) {
1362  TString usr(usrIn);
1363  usr.Remove(usr.Length() - 1); // get rid of \n
1364  if (!usr.IsNull())
1365  return StrDup(usr);
1366  else
1367  return StrDup(user);
1368  }
1369  return 0;
1370 }
1371 
1372 ////////////////////////////////////////////////////////////////////////////////
1373 /// Static method to prompt for the user's passwd to be used for
1374 /// authentication to rootd or proofd. Uses non-echoing command line
1375 /// to get passwd. Returns passwd (which must de deleted by caller) or 0.
1376 /// If non-interactive run (eg ProofServ) returns -1
1377 
1378 char *TAuthenticate::PromptPasswd(const char *prompt)
1379 {
1380  if (isatty(0) == 0 || isatty(1) == 0) {
1381  ::Warning("TAuthenticate::PromptPasswd",
1382  "not tty: cannot prompt for passwd, returning -1");
1383  static char noint[4] = {"-1"};
1384  return StrDup(noint);
1385  }
1386 
1387  char buf[128];
1388  const char *pw = buf;
1389  // Get the plugin for the passwd dialog box, if needed
1390  if (!gROOT->IsBatch() && (fgPasswdDialog == (TPluginHandler *)(-1)) &&
1391  gEnv->GetValue("Auth.UsePasswdDialogBox", 1) == 1) {
1392  if ((fgPasswdDialog =
1393  gROOT->GetPluginManager()->FindHandler("TGPasswdDialog"))) {
1394  if (fgPasswdDialog->LoadPlugin() == -1) {
1395  fgPasswdDialog = 0;
1396  ::Warning("TAuthenticate",
1397  "could not load plugin for the password dialog box");
1398  }
1399  }
1400  }
1401  if (fgPasswdDialog && (fgPasswdDialog != (TPluginHandler *)(-1))) {
1402 
1403  // Use graphic dialog
1404  fgPasswdDialog->ExecPlugin(3, prompt, buf, 128);
1405 
1406  // Wait until the user is done
1407  while (gROOT->IsInterrupted())
1409 
1410  } else {
1411  Gl_config("noecho", 1);
1412  pw = Getline(prompt);
1413  Gl_config("noecho", 0);
1414  }
1415 
1416  // Final checks
1417  if (pw[0]) {
1418  TString spw(pw);
1419  if (spw.EndsWith("\n"))
1420  spw.Remove(spw.Length() - 1); // get rid of \n
1421  char *rpw = StrDup(spw);
1422  return rpw;
1423  }
1424  return 0;
1425 }
1426 
1427 ////////////////////////////////////////////////////////////////////////////////
1428 /// Static method returning the globus authorization hook.
1429 
1431 {
1432  return fgGlobusAuthHook;
1433 }
1434 
1435 ////////////////////////////////////////////////////////////////////////////////
1436 /// Static method returning the RSA public keys.
1437 
1439 {
1440  key = (key >= 0 && key <= 1) ? key : 0;
1441  return fgRSAPubExport[key].keys;
1442 }
1443 
1444 ////////////////////////////////////////////////////////////////////////////////
1445 /// Static method returning the RSA initialization flag.
1446 
1448 {
1449  return fgRSAInit;
1450 }
1451 
1452 ////////////////////////////////////////////////////////////////////////////////
1453 /// Static method setting the default type of RSA key.
1454 
1456 {
1457  if (key >= 0 && key <= 1)
1458  fgRSAKey = key;
1459 }
1460 
1461 ////////////////////////////////////////////////////////////////////////////////
1462 /// Static method setting RSA initialization flag.
1463 
1465 {
1466  fgRSAInit = init;
1467 }
1468 
1469 ////////////////////////////////////////////////////////////////////////////////
1470 /// Static method returning the list with authentication details.
1471 
1473 {
1474  R__LOCKGUARD2(gAuthenticateMutex);
1475 
1476  if (!fgAuthInfo)
1477  fgAuthInfo = new TList;
1478  return fgAuthInfo;
1479 }
1480 
1481 ////////////////////////////////////////////////////////////////////////////////
1482 /// Static method returning the list with authentication directives
1483 /// to be sent to proof.
1484 
1486 {
1487  R__LOCKGUARD2(gAuthenticateMutex);
1488 
1489  if (!fgProofAuthInfo)
1490  fgProofAuthInfo = new TList;
1491  return fgProofAuthInfo;
1492 }
1493 
1494 ////////////////////////////////////////////////////////////////////////////////
1495 /// Print error string depending on error code.
1496 
1497 void TAuthenticate::AuthError(const char *where, Int_t err)
1498 {
1499  R__LOCKGUARD2(gAuthenticateMutex);
1500 
1501  // Make sure it is in range
1502  err = (err < kErrError) ? ((err > -1) ? err : -1) : kErrError;
1503 
1504  Int_t erc = err;
1505  Bool_t forceprint = kFALSE;
1506  TString lasterr = "";
1507  if (err == -1) {
1508  forceprint = kTRUE;
1509  erc = fgLastError;
1510  lasterr = "(last error only; re-run with gDebug > 0 for more details)";
1511  }
1512 
1513  if (erc > -1)
1514  if (gDebug > 0 || forceprint) {
1515  if (gRootdErrStr[erc])
1516  ::Error(Form("TAuthenticate::%s", where), "%s %s",
1517  gRootdErrStr[erc], lasterr.Data());
1518  else
1519  ::Error(Form("TAuthenticate::%s", where),
1520  "unknown error code: server must be running a newer ROOT version %s",
1521  lasterr.Data());
1522  }
1523 
1524  // Update last error code
1525  fgLastError = err;
1526 }
1527 
1528 ////////////////////////////////////////////////////////////////////////////////
1529 /// Set global user name to be used for authentication to rootd or proofd.
1530 
1531 void TAuthenticate::SetGlobalUser(const char *user)
1532 {
1533  R__LOCKGUARD2(gAuthenticateMutex);
1534 
1535  if (fgUser != "")
1536  fgUser = "";
1537 
1538  if (user && user[0])
1539  fgUser = user;
1540 }
1541 
1542 ////////////////////////////////////////////////////////////////////////////////
1543 /// Set global passwd to be used for authentication to rootd or proofd.
1544 
1545 void TAuthenticate::SetGlobalPasswd(const char *passwd)
1546 {
1547  R__LOCKGUARD2(gAuthenticateMutex);
1548 
1549  if (fgPasswd != "")
1550  fgPasswd = "";
1551 
1552  if (passwd && passwd[0])
1553  fgPasswd = passwd;
1554 }
1555 
1556 ////////////////////////////////////////////////////////////////////////////////
1557 /// Set global passwd hash flag to be used for authentication to rootd or proofd.
1558 
1560 {
1561  fgPwHash = pwhash;
1562 }
1563 
1564 ////////////////////////////////////////////////////////////////////////////////
1565 /// Set global SRP passwd flag to be used for authentication to rootd or proofd.
1566 
1568 {
1569  fgSRPPwd = srppwd;
1570 }
1571 
1572 ////////////////////////////////////////////////////////////////////////////////
1573 /// Set flag controlling the reading of $HOME/.rootauthrc.
1574 /// In PROOF the administrator may want to switch off private settings.
1575 /// Always true, may only be set false via option to proofd.
1576 
1578 {
1579  fgReadHomeAuthrc = readhomeauthrc;
1580 }
1581 
1582 ////////////////////////////////////////////////////////////////////////////////
1583 /// Set default expiring date for new validity contexts
1584 
1586 {
1587  fgExpDate = expdate;
1588 }
1589 
1590 ////////////////////////////////////////////////////////////////////////////////
1591 /// Set default user name.
1592 
1593 void TAuthenticate::SetDefaultUser(const char *defaultuser)
1594 {
1595  if (fgDefaultUser != "")
1596  fgDefaultUser = "";
1597 
1598  if (defaultuser && defaultuser[0])
1599  fgDefaultUser = defaultuser;
1600 }
1601 
1602 ////////////////////////////////////////////////////////////////////////////////
1603 /// Set timeout (active if > 0)
1604 
1606 {
1607  fgAuthTO = (to <= 0) ? -1 : to;
1608 }
1609 
1610 ////////////////////////////////////////////////////////////////////////////////
1611 /// Set global AuthReUse flag
1612 
1614 {
1615  fgAuthReUse = authreuse;
1616 }
1617 
1618 ////////////////////////////////////////////////////////////////////////////////
1619 /// Set global PromptUser flag
1620 
1622 {
1623  fgPromptUser = promptuser;
1624 }
1625 
1626 ////////////////////////////////////////////////////////////////////////////////
1627 /// Set secure authorization function. Automatically called when libSRPAuth
1628 /// is loaded.
1629 
1631 {
1632  fgSecAuthHook = func;
1633 }
1634 
1635 ////////////////////////////////////////////////////////////////////////////////
1636 /// Set kerberos5 authorization function. Automatically called when
1637 /// libKrb5Auth is loaded.
1638 
1640 {
1641  fgKrb5AuthHook = func;
1642 }
1643 
1644 ////////////////////////////////////////////////////////////////////////////////
1645 /// Set Globus authorization function. Automatically called when
1646 /// libGlobusAuth is loaded.
1647 
1649 {
1651 }
1652 
1653 ////////////////////////////////////////////////////////////////////////////////
1654 /// SSH error parsing: returns
1655 /// 0 : no error or fatal
1656 /// 1 : should retry (eg 'connection closed by remote host')
1657 
1658 Int_t TAuthenticate::SshError(const char *errorfile)
1659 {
1660  Int_t error = 0;
1661 
1662  if (!gSystem->AccessPathName(errorfile, kReadPermission)) {
1663  FILE *ferr = fopen(errorfile,"r");
1664  if (ferr) {
1665  // Get list of errors for which one should retry
1666  char *serr = StrDup(gEnv->GetValue("SSH.ErrorRetry", ""));
1667  // Prepare for parsing getting rid of '"'s
1668  Int_t lerr = strlen(serr);
1669  char *pc = (char *)memchr(serr,'"',lerr);
1670  while (pc) {
1671  *pc = '\0';
1672  pc = (char *)memchr(pc+1,'"',strlen(pc+1));
1673  }
1674  // Now read the file
1675  char line[kMAXPATHLEN];
1676  while (fgets(line,sizeof(line),ferr)) {
1677  // Get rid of trailing '\n'
1678  if (line[strlen(line)-1] == '\n')
1679  line[strlen(line)-1] = '\0';
1680  if (gDebug > 2)
1681  Info("SshError","read line: %s",line);
1682  pc = serr;
1683  while (pc < serr + lerr) {
1684  if (pc[0] == '\0' || pc[0] == ' ')
1685  pc++;
1686  else {
1687  if (gDebug > 2)
1688  Info("SshError","checking error: '%s'",pc);
1689  if (strstr(line,pc))
1690  error = 1;
1691  pc += strlen(pc);
1692  }
1693  }
1694  }
1695  // Close file
1696  fclose(ferr);
1697  // Free allocated memory
1698  if (serr) delete [] serr;
1699  }
1700  }
1701  return error;
1702 }
1703 
1704 ////////////////////////////////////////////////////////////////////////////////
1705 /// SSH client authentication code.
1706 
1708 {
1709  // No control on credential forwarding in case of SSH authentication;
1710  // switched it off on PROOF servers, unless the user knows what they
1711  // are doing
1712 
1713  if (gROOT->IsProofServ()) {
1714  if (!(gEnv->GetValue("ProofServ.UseSSH",0))) {
1715  if (gDebug > 0)
1716  Info("SshAuth", "SSH protocol is switched OFF by default"
1717  " for PROOF servers: use 'ProofServ.UseSSH 1'"
1718  " to enable it (see system.rootrc)");
1719  return -1;
1720  }
1721  }
1722 
1723  Int_t sshproto = 1;
1724  if (fVersion < 4)
1725  sshproto = 0;
1726 
1727  // Find out which command we should be using
1728  char cmdref[2][5] = {"ssh", "scp"};
1729  char scmd[5] = "";
1730  TString sshExe;
1731  Bool_t notfound = kTRUE;
1732 
1733  while (notfound && sshproto > -1) {
1734 
1735  strlcpy(scmd,cmdref[sshproto],5);
1736 
1737  // Check First if a 'scmd' executable exists ...
1738  char *sSshExe = gSystem->Which(gSystem->Getenv("PATH"),
1739  scmd, kExecutePermission);
1740  sshExe = sSshExe;
1741  delete [] sSshExe;
1742  if (!sshExe) {
1743  if (gDebug > 2)
1744  Info("SshAuth", "%s not found in $PATH", scmd);
1745 
1746  // Still allow for client definition of the ssh location ...
1747  if (strcmp(gEnv->GetValue("SSH.ExecDir", "-1"), "-1")) {
1748  if (gDebug > 2)
1749  Info("SshAuth", "searching user defined path ...");
1750  sshExe.Form("%s/%s", (char *)gEnv->GetValue("SSH.ExecDir", ""), scmd);
1751  if (gSystem->AccessPathName(sshExe, kExecutePermission)) {
1752  if (gDebug > 2)
1753  Info("SshAuth", "%s not executable", sshExe.Data());
1754  } else
1755  notfound = kFALSE;
1756  }
1757  } else
1758  notfound = kFALSE;
1759  if (notfound) sshproto--;
1760  }
1761 
1762  // Check if the command was found
1763  if (notfound)
1764  return -1;
1765 
1766  if (gDebug > 2)
1767  Info("SshAuth", "%s is %s (sshproto: %d)", scmd, sshExe.Data(), sshproto);
1768 
1769  // SSH-like authentication code.
1770  // Returns 0 in case authentication failed
1771  // 1 in case of success
1772  // -1 in case of the remote node does not seem to support
1773  // SSH-like Authentication
1774  // -2 in case of the remote node does not seem to allow
1775  // connections from this node
1776 
1777  char secName[kMAXPATHLEN] = { 0 };
1778 
1779  // Determine user name ...
1780  user = GetSshUser(user);
1781 
1782  // Check ReUse
1783  Int_t reuse = (int)fgAuthReUse;
1784  fDetails = TString::Format("pt:%d ru:%d us:",(int)fgPromptUser,(int)fgAuthReUse)
1785  + user;
1786 
1787  // Create options string
1788  int opt = reuse * kAUTH_REUSE_MSK + fRSAKey * kAUTH_RSATY_MSK;
1789  TString options;
1790  options.Form("%d none %ld %s %d", opt,
1791  (Long_t)user.Length(),user.Data(),sshproto);
1792 
1793  // Check established authentications
1794  Int_t kind = kROOTD_SSH;
1795  Int_t retval = reuse;
1796  Int_t rc = 0;
1797  if ((rc = AuthExists(user, (Int_t) TAuthenticate::kSSH, options,
1798  &kind, &retval, &StdCheckSecCtx)) == 1) {
1799  // A valid authentication exists: we are done ...
1800  return 1;
1801  }
1802  if (rc == -2) {
1803  return rc;
1804  }
1805  if (retval == kErrNotAllowed && kind == kROOTD_ERR) {
1806  return 0;
1807  }
1808  // Check return flags
1809  if (kind != kROOTD_SSH) {
1810  return 0; // something went wrong
1811  }
1812  if (retval == 0) {
1813  return 0; // no remote support for SSH
1814  }
1815  if (retval == -2) {
1816  return 0; // user unkmown to remote host
1817  }
1818 
1819  // Wait for the server to communicate remote pid and location
1820  // of command to execute
1821  char cmdinfo[kMAXPATHLEN] = { 0 };
1822  Int_t reclen = (retval+1 > kMAXPATHLEN) ? kMAXPATHLEN : retval+1 ;
1823  if (fSocket->Recv(cmdinfo, reclen, kind) < 0) {
1824  return 0;
1825  }
1826  if (kind != kROOTD_SSH) {
1827  return 0; // something went wrong
1828  }
1829  if (gDebug > 3) {
1830  Info("SshAuth", "received from server command info: %s", cmdinfo);
1831  }
1832 
1833  int rport = -1;
1834  TString ci(cmdinfo), tkn;
1835  Ssiz_t from = 0;
1836  while (ci.Tokenize(tkn, from, " ")) {
1837  if (from > 0) cmdinfo[from-1] = '\0';
1838  if (tkn.BeginsWith("p:")) {
1839  tkn.ReplaceAll("p:", "");
1840  if (tkn.IsDigit()) rport = tkn.Atoi();
1841 #ifdef R__SSL
1842  } else if (tkn.BeginsWith("k:")) {
1843  tkn.ReplaceAll("k:", "");
1844  if (tkn.IsDigit() && tkn.Atoi() == 1) fRSAKey = 1;
1845 #endif
1846  }
1847  }
1848 
1849  // If we are a non-interactive session we cannot reply
1850  TString noPrompt = "";
1851  if (isatty(0) == 0 || isatty(1) == 0) {
1852  noPrompt = TString("-o 'PasswordAuthentication no' ");
1853  noPrompt += TString("-o 'StrictHostKeyChecking no' ");
1854  if (gDebug > 3)
1855  Info("SshAuth", "using noprompt options: %s", noPrompt.Data());
1856  }
1857 
1858  // Remote settings
1859  Int_t srvtyp = fSocket->GetServType();
1860  Int_t rproto = fSocket->GetRemoteProtocol();
1861 
1862  // Send authentication request to remote sshd
1863  // Create command
1864  int ssh_rc = 1;
1865  Int_t ntry = gEnv->GetValue("SSH.MaxRetry",100);
1866  TString fileErr = "";
1867  if (sshproto == 0) {
1868  // Prepare local file first in the home directory
1869  fileErr = "rootsshtmp_";
1870  FILE *floc = gSystem->TempFileName(fileErr,gSystem->HomeDirectory());
1871  if (floc == 0) {
1872  // Try the temp directory
1873  fileErr = "rootsshtmp_";
1874  if ((floc = gSystem->TempFileName(fileErr)))
1875  fclose(floc);
1876  }
1877  fileErr.Append(".error");
1878  TString sshcmd;
1879  sshcmd.Form("%s -x -l %s %s", sshExe.Data(), user.Data(), noPrompt.Data());
1880  if (rport != -1)
1881  sshcmd += TString::Format(" -p %d",rport);
1882  sshcmd += TString::Format(" %s %s",fRemote.Data(), cmdinfo);
1883  sshcmd += TString::Format(" 1> /dev/null 2> %s",fileErr.Data());
1884 
1885  // Execute command
1886  Int_t again = 1;
1887  while (ssh_rc && again && ntry--) {
1888  ssh_rc = gSystem->Exec(sshcmd);
1889  if (ssh_rc) {
1890  again = SshError(fileErr);
1891  if (gDebug > 3)
1892  Info("SshAuth", "%d: sleeping: rc: %d, again:%d, ntry: %d",
1893  fgProcessID, ssh_rc, again, ntry);
1894  if (again)
1895  gSystem->Sleep(1);
1896  }
1897  }
1898  } else {
1899  // Whether we need to add info about user@host in the command
1900  // Recent rootd/proofd set this correctly so that it works also
1901  // via SSH tunnel
1902  Bool_t addhost = ((srvtyp == TSocket::kROOTD && rproto < 15) ||
1903  (srvtyp == TSocket::kPROOFD && rproto < 13)||
1904  (srvtyp == TSocket::kSOCKD && rproto < 1)) ? 1 : 0;
1905 
1906  // Prepare local file first in the home directory
1907  TString fileLoc = "rootsshtmp_";
1908  FILE *floc = gSystem->TempFileName(fileLoc,gSystem->HomeDirectory());
1909  if (floc == 0) {
1910  // Try the temp directory
1911  fileLoc = "rootsshtmp_";
1912  floc = gSystem->TempFileName(fileLoc);
1913  }
1914 
1915  if (floc != 0) {
1916  // Close file and change permissions before filling it
1917  fclose(floc);
1918  if (chmod(fileLoc, 0600) == -1) {
1919  Info("SshAuth", "fchmod error: %d", errno);
1920  ssh_rc = 2;
1921  } else {
1922  floc = fopen(fileLoc, "w");
1923  if (reuse == 1) {
1924  // Send our public key
1925  if (fVersion > 4) {
1926  fprintf(floc,"k: %d\n",fRSAKey+1);
1927  fwrite(fgRSAPubExport[fRSAKey].keys,1,
1928  fgRSAPubExport[fRSAKey].len,floc);
1929  } else {
1930  fprintf(floc,"k: %s\n",fgRSAPubExport[0].keys);
1931  }
1932  } else
1933  // Just a notification
1934  fprintf(floc,"k: -1\n");
1935  fclose(floc);
1936  ssh_rc = 0;
1937  }
1938  if (!ssh_rc) {
1939  fileErr = TString(fileLoc).Append(".error");
1940  TString sshcmd;
1941  sshcmd.Form("%s -p %s", sshExe.Data(), noPrompt.Data());
1942  if (rport != -1)
1943  sshcmd += TString::Format(" -P %d",rport);
1944  sshcmd += TString::Format(" %s",fileLoc.Data());
1945  if (addhost) {
1946  sshcmd += TString::Format(" %s@%s:%s 1> /dev/null",
1947  user.Data(),fRemote.Data(),cmdinfo);
1948  } else {
1949  sshcmd += TString::Format("%s 1> /dev/null", cmdinfo);
1950  }
1951  sshcmd += TString::Format(" 2> %s",fileErr.Data());
1952  // Execute command
1953  ssh_rc = 1;
1954  Int_t again = 1;
1955  while (ssh_rc && again && ntry--) {
1956  ssh_rc = gSystem->Exec(sshcmd);
1957  if (ssh_rc) {
1958  again = SshError(fileErr);
1959  if (gDebug > 3)
1960  Info("SshAuth", "%d: sleeping: rc: %d, again:%d, ntry: %d",
1961  fgProcessID, ssh_rc, again, ntry);
1962  if (again)
1963  // Wait 1 sec before retry
1964  gSystem->Sleep(1000);
1965  }
1966  }
1967  }
1968  } else {
1969  // Problems creating temporary file: return ...
1970  ssh_rc = 1;
1971  }
1972  // Remove the file after use ...
1973  if (!gSystem->AccessPathName(fileLoc,kFileExists)) {
1974  gSystem->Unlink(fileLoc);
1975  }
1976  }
1977  // Remove the file after use ...
1978  if (!gSystem->AccessPathName(fileErr,kFileExists)) {
1979  gSystem->Unlink(fileErr);
1980  }
1981  if (gDebug > 3)
1982  Info("SshAuth", "%d: system return code: %d (%d)",
1983  fgProcessID, ssh_rc, ntry+1);
1984 
1985  if (ssh_rc && sshproto == 0) {
1986 
1987  srvtyp = fSocket->GetServType();
1988  rproto = fSocket->GetRemoteProtocol();
1989  Int_t level = 2;
1990  if ((srvtyp == TSocket::kROOTD && rproto < 10) ||
1991  (srvtyp == TSocket::kPROOFD && rproto < 9))
1992  level = 1;
1993  if ((srvtyp == TSocket::kROOTD && rproto < 8) ||
1994  (srvtyp == TSocket::kPROOFD && rproto < 7))
1995  level = 0;
1996  if (level) {
1997  Int_t port = fSocket->GetPort();
1998  TSocket *newsock = 0;
1999  TString url;
2000  url.Form("sockd://%s",fRemote.Data());
2001  if (srvtyp == TSocket::kROOTD) {
2002  // Parallel socket requested by 'rootd'
2003  url.ReplaceAll("sockd",5,"rootd",5);
2004  newsock = new TPSocket(url.Data(),port,1,-1);
2005  } else {
2006  if (srvtyp == TSocket::kPROOFD)
2007  url.ReplaceAll("sockd",5,"proofd",6);
2008  newsock = new TSocket(fRemote.Data(),port,-1);
2009  if (srvtyp == TSocket::kPROOFD)
2010  newsock->Send("failure notification");
2011  }
2012  // prepare info to send
2013  char cd1[1024], pipe[1024], dum[1024];
2014  Int_t id3;
2015  sscanf(cmdinfo, "%1023s %d %1023s %1023s", cd1, &id3, pipe, dum);
2016  snprintf(secName, kMAXPATHLEN, "%d -1 0 %s %d %s %d",
2017  -fgProcessID, pipe,
2018  (int)strlen(user), user.Data(), TSocket::GetClientProtocol());
2019  newsock->Send(secName, kROOTD_SSH);
2020  if (level > 1) {
2021  // Improved diagnostics
2022  // Receive diagnostics message
2023  if (newsock->Recv(retval, kind) >= 0) {
2024  char *buf = new char[retval+1];
2025  if (newsock->Recv(buf, retval+1, kind) >= 0) {
2026  if (strncmp(buf,"OK",2)) {
2027  Info("SshAuth", "from remote host %s:", fRemote.Data());
2028  Info("SshAuth", ">> nothing listening on port %s %s",buf,
2029  "(supposed to be associated to sshd)");
2030  Info("SshAuth", ">> contact the daemon administrator at %s",
2031  fRemote.Data());
2032  } else {
2033  if (gDebug > 0) {
2034  Info("SshAuth", "from remote host %s:", fRemote.Data());
2035  Info("SshAuth", ">> something listening on the port"
2036  " supposed to be associated to sshd.");
2037  Info("SshAuth", ">> You have probably mistyped your"
2038  " password. Or you tried to hack the"
2039  " system.");
2040  Info("SshAuth", ">> If the problem persists you may"
2041  " consider contacting the daemon");
2042  Info("SshAuth", ">> administrator at %s.",fRemote.Data());
2043  }
2044  }
2045  }
2046  delete [] buf;
2047  }
2048  }
2049  SafeDelete(newsock);
2050  // Receive error message
2051  if (fSocket->Recv(retval, kind) >= 0) { // for consistency
2052  if (kind == kROOTD_ERR)
2053  AuthError("SshAuth", retval);
2054  }
2055  }
2056  return 0;
2057  } else if (ssh_rc && sshproto > 0) {
2058  // Communicate failure
2059  if (fSocket->Send("0", kROOTD_SSH) < 0)
2060  Info("SshAuth", "error communicating failure");
2061  return 0;
2062  }
2063 
2064  // Communicate success
2065  if (sshproto > 0) {
2066  if (fSocket->Send("1", kROOTD_SSH) < 0)
2067  Info("SshAuth", "error communicating success");
2068  }
2069 
2070  Int_t nrec = 0;
2071  // Receive key request info and type of key (if ok, error otherwise)
2072  if ((nrec = fSocket->Recv(retval, kind)) < 0) // returns user
2073  return 0;
2074  if (gDebug > 3)
2075  Info("SshAuth", "got message %d, flag: %d", kind, retval);
2076 
2077  // Check if an error occured
2078  if (kind == kROOTD_ERR) {
2079  AuthError("SshAuth", retval);
2080  return 0;
2081  }
2082 
2083  if (reuse == 1 && sshproto == 0) {
2084 
2085  // Save type of key
2086  if (kind != kROOTD_RSAKEY || retval < 1 || retval > 2) {
2087  Error("SshAuth",
2088  "problems recvn RSA key flag: got message %d, flag: %d",
2089  kind, retval);
2090  return 0;
2091  }
2092 
2093  fRSAKey = retval - 1;
2094 
2095  // Send the key securely
2096  if (SendRSAPublicKey(fSocket,fRSAKey) < 0)
2097  return 0;
2098 
2099  // Receive username used for login
2100  if ((nrec = fSocket->Recv(retval, kind)) < 0) // returns user
2101  return 0;
2102  if (gDebug > 3)
2103  Info("SshAuth", "got message %d, flag: %d", kind, retval);
2104  }
2105 
2106  if (kind != kROOTD_SSH || retval < 1) {
2107  Warning("SshAuth",
2108  "problems recvn (user,offset) length (%d:%d bytes:%d)", kind,
2109  retval, nrec);
2110  return 0;
2111  }
2112 
2113  char answer[256];
2114  reclen = (retval+1 > 256) ? 256 : retval+1;
2115  if ((nrec = fSocket->Recv(answer, reclen, kind)) < 0) // returns user
2116  return 0;
2117  if (kind != kMESS_STRING)
2118  Warning("SshAuth", "username and offset not received (%d:%d)", kind,
2119  nrec);
2120 
2121  // Parse answer
2122  char lUser[128];
2123  int offset = -1;
2124  sscanf(answer, "%127s %d", lUser, &offset);
2125  if (gDebug > 3)
2126  Info("SshAuth", "received from server: user: %s, offset: %d", lUser,
2127  offset);
2128 
2129  // Receive token
2130  char *token = 0;
2131  if (reuse == 1 && offset > -1) {
2132  if (SecureRecv(fSocket, 1, fRSAKey, &token) == -1) {
2133  Warning("SshAuth", "problems secure-receiving token -"
2134  " may result in corrupted token");
2135  delete [] token;
2136  return 0;
2137  }
2138  if (gDebug > 3)
2139  Info("SshAuth", "received from server: token: '%s' ", token);
2140  } else {
2141  token = StrDup("");
2142  }
2143 
2144  // Create SecContext object
2145  fSecContext = fHostAuth->CreateSecContext((const char *)lUser, fRemote,
2146  (Int_t)kSSH, offset, fDetails,
2147  (const char *)token, fgExpDate, 0, fRSAKey);
2148 
2149  // Release allocated memory ...
2150  if (token) delete [] token;
2151 
2152  // Get and Analyse the reply
2153  if (fSocket->Recv(retval, kind) < 0)
2154  return 0;
2155  if (gDebug > 3)
2156  Info("SshAuth", "received from server: kind: %d, retval: %d", kind,
2157  retval);
2158 
2159  if (kind != kROOTD_AUTH) {
2160  return 0;
2161  } else {
2162  return retval;
2163  }
2164 }
2165 
2166 ////////////////////////////////////////////////////////////////////////////////
2167 /// Method returning the user to be used for the ssh login.
2168 /// Looks first at SSH.Login and finally at env USER.
2169 /// If SSH.LoginPrompt is set to 'yes' it prompts for the 'login name'
2170 
2171 const char *TAuthenticate::GetSshUser(TString user) const
2172 {
2173  R__LOCKGUARD2(gAuthenticateMutex);
2174 
2175  static TString usr = "";
2176 
2177  if (user == "") {
2178  if (fgPromptUser) {
2179  char *p = PromptUser(fRemote);
2180  usr = p;
2181  delete [] p;
2182  } else {
2183  usr = fgDefaultUser;
2184  if (usr == "") {
2185  char *p = PromptUser(fRemote);
2186  usr = p;
2187  delete [] p;
2188  }
2189  }
2190  } else {
2191  usr = user;
2192  }
2193 
2194  return usr;
2195 }
2196 
2197 ////////////////////////////////////////////////////////////////////////////////
2198 /// Check if 'host' matches 'href':
2199 /// this means either equal or "containing" it, even with wild cards *
2200 /// in the first field (in the case 'href' is a name, ie not IP address)
2201 /// Returns kTRUE if the two matches.
2202 
2203 Bool_t TAuthenticate::CheckHost(const char *host, const char *href)
2204 {
2205  R__LOCKGUARD2(gAuthenticateMutex);
2206 
2207  Bool_t retval = kTRUE;
2208 
2209  // Both strings should have been defined
2210  if (!host || !href)
2211  return kFALSE;
2212 
2213  // 'href' == '*' indicates any 'host' ...
2214  if (!strcmp(href,"*"))
2215  return kTRUE;
2216 
2217  // If 'href' contains at a letter or an hyphen it is assumed to be
2218  // a host name. Otherwise a name.
2219  // Check also for wild cards
2220  Bool_t name = kFALSE;
2221  TRegexp rename("[+a-zA-Z]");
2222  Int_t len;
2223  if (rename.Index(href,&len) != -1 || strstr(href,"-"))
2224  name = kTRUE;
2225 
2226  // Check also for wild cards
2227  Bool_t wild = kFALSE;
2228  if (strstr(href,"*"))
2229  wild = kTRUE;
2230 
2231  // Now build the regular expression for final checking
2232  TRegexp rehost(href,wild);
2233 
2234  // host to check
2235  TString theHost(host);
2236  if (!name) {
2237  TInetAddress addr = gSystem->GetHostByName(host);
2238  theHost = addr.GetHostAddress();
2239  if (gDebug > 2)
2240  ::Info("TAuthenticate::CheckHost", "checking host IP: %s", theHost.Data());
2241  }
2242 
2243  // Check 'host' against 'rehost'
2244  Ssiz_t pos = rehost.Index(theHost,&len);
2245  if (pos == -1)
2246  retval = kFALSE;
2247 
2248  // If IP and no wilds, it should match either
2249  // the beginning or the end of the string
2250  if (!wild) {
2251  if (pos > 0 && pos != (Ssiz_t)(theHost.Length()-strlen(href)))
2252  retval = kFALSE;
2253  }
2254 
2255  return retval;
2256 }
2257 
2258 ////////////////////////////////////////////////////////////////////////////////
2259 /// UidGid client authentication code.
2260 /// Returns 0 in case authentication failed
2261 /// 1 in case of success
2262 /// <0 in case of system error
2263 
2265 {
2266  if (gDebug > 2)
2267  Info("RfioAuth", "enter ... username %s", username.Data());
2268 
2269  // Get user info ... ...
2271  if (pw) {
2272 
2273  // These are the details to be saved in case of success ...
2274  username = pw->fUser;
2275  fDetails = TString("pt:0 ru:0 us:") + username;
2276 
2277  // Check that we are not root and that the requested user is ourselves
2278  if (pw->fUid != 0) {
2279 
2281 
2282  // Get effective user & group ID associated with the current process...
2283  Int_t uid = pw->fUid;
2284  Int_t gid = grp ? grp->fGid : pw->fGid;
2285 
2286  delete grp;
2287 
2288  // Send request ....
2289  TString sstr = TString::Format("%d %d", uid, gid);
2290  if (gDebug > 3)
2291  Info("RfioAuth", "sending ... %s", sstr.Data());
2292  Int_t ns = 0;
2293  if ((ns = fSocket->Send(sstr.Data(), kROOTD_RFIO)) < 0)
2294  return 0;
2295  if (gDebug > 3)
2296  Info("RfioAuth", "sent ... %d bytes (expected > %d)", ns,
2297  sstr.Length());
2298 
2299  // Get answer
2300  Int_t stat, kind;
2301  if (fSocket->Recv(stat, kind) < 0)
2302  return 0;
2303  if (gDebug > 3)
2304  Info("RfioAuth", "after kROOTD_RFIO: kind= %d, stat= %d", kind,
2305  stat);
2306 
2307  // Query result ...
2308  if (kind == kROOTD_AUTH && stat >= 1) {
2309  // Create inactive SecContext object for use in TSocket
2310  fSecContext =
2311  fHostAuth->CreateSecContext((const char *)pw->fUser,
2312  fRemote, kRfio, -stat, fDetails, 0);
2313  delete pw;
2314  return 1;
2315  } else {
2316  TString server = "sockd";
2317  if (fProtocol.Contains("root"))
2318  server = "rootd";
2319  if (fProtocol.Contains("proof"))
2320  server = "proofd";
2321 
2322  // Authentication failed
2323  if (stat == kErrConnectionRefused) {
2324  if (gDebug > 0)
2325  Error("RfioAuth",
2326  "%s@%s does not accept connections from %s%s",
2327  server.Data(),fRemote.Data(),
2328  fUser.Data(),gSystem->HostName());
2329  delete pw;
2330  return -2;
2331  } else if (stat == kErrNotAllowed) {
2332  if (gDebug > 0)
2333  Error("RfioAuth",
2334  "%s@%s does not accept %s authentication from %s@%s",
2335  server.Data(),fRemote.Data(),
2336  TAuthenticate::fgAuthMeth[5].Data(),
2337  fUser.Data(),gSystem->HostName());
2338  } else {
2339  AuthError("RfioAuth", stat);
2340  }
2341  delete pw;
2342  return 0;
2343  }
2344  } else {
2345  Warning("RfioAuth", "UidGid login as \"root\" not allowed");
2346  return -1;
2347  }
2348  }
2349  return -1;
2350 }
2351 
2352 ////////////////////////////////////////////////////////////////////////////////
2353 /// UsrPwd client authentication code.
2354 /// Returns 0 in case authentication failed
2355 /// 1 in case of success
2356 
2358 {
2359  R__LOCKGUARD2(gAuthenticateMutex);
2360 
2361  if (gDebug > 2)
2362  Info("ClearAuth", "enter: user: %s (passwd hashed?: %d)",
2363  user.Data(),(Int_t)pwdhash);
2364 
2365  Int_t reuse = fgAuthReUse;
2366  Int_t prompt = fgPromptUser;
2367  Int_t cryptopt = fgUsrPwdCrypt;
2368  Int_t needsalt = 1;
2369  if (pwdhash)
2370  needsalt = 0;
2371  fDetails = TString::Format("pt:%d ru:%d cp:%d us:",
2373  if (gDebug > 2)
2374  Info("ClearAuth", "ru:%d pt:%d cp:%d ns:%d rk:%d",
2376 #ifdef R__WIN32
2377  needsalt = 0;
2378 #endif
2379  Int_t stat, kind;
2380 
2381  if (fVersion > 1) {
2382 
2383  //
2384  // New protocol
2385  //
2386  Int_t anon = 0;
2387  TString salt = "";
2388  TString pashash = "";
2389 
2390  // Get effective user (fro remote checks in $HOME/.rhosts)
2392  TString effUser;
2393  if (pw) {
2394  effUser = TString(pw->fUser);
2395  delete pw;
2396  } else
2397  effUser = user;
2398 
2399  // Create options string
2400  int opt = (reuse * kAUTH_REUSE_MSK) + (cryptopt * kAUTH_CRYPT_MSK) +
2401  (needsalt * kAUTH_SSALT_MSK) + (fRSAKey * kAUTH_RSATY_MSK);
2402  TString options;
2403  options.Form("%d %ld %s %ld %s", opt,
2404  (Long_t)user.Length(), user.Data(),
2405  (Long_t)effUser.Length(), effUser.Data());
2406 
2407  // Check established authentications
2408  kind = kROOTD_USER;
2409  stat = reuse;
2410  Int_t rc = 0;
2411  if ((rc = AuthExists(user, (Int_t) TAuthenticate::kClear, options,
2412  &kind, &stat, &StdCheckSecCtx)) == 1) {
2413  // A valid authentication exists: we are done ...
2414  return 1;
2415  }
2416  if (rc == -2) {
2417  return rc;
2418  }
2419  if (stat == kErrNotAllowed && kind == kROOTD_ERR) {
2420  return 0;
2421  }
2422 
2423  if (kind == kROOTD_AUTH && stat == -1) {
2424  if (gDebug > 3)
2425  Info("ClearAuth", "anonymous user");
2426  anon = 1;
2427  cryptopt = 0;
2428  reuse = 0;
2429  needsalt = 0;
2430  }
2431 
2432  // The random tag in hex representation
2433  // Protection against reply attacks
2434  char ctag[11] = {0};
2435  if (anon == 0 && cryptopt == 1) {
2436 
2437  // Check that we got the right thing ..
2438  if (kind != kROOTD_RSAKEY || stat < 1 || stat > 2 ) {
2439  // Check for errors
2440  if (kind != kROOTD_ERR) {
2441  Warning("ClearAuth",
2442  "problems recvn RSA key flag: got message %d, flag: %d",
2443  kind, stat);
2444  }
2445  return 0;
2446  }
2447  if (gDebug > 3)
2448  Info("ClearAuth", "get key request ...");
2449 
2450  // Save type of key
2451  fRSAKey = stat - 1;
2452 
2453  // Send the key securely
2454  if (SendRSAPublicKey(fSocket,fRSAKey) < 0)
2455  return 0;
2456 
2457  int slen = 0;
2458  if (needsalt) {
2459  // Receive password salt
2460  char *tmpsalt = 0;
2461  if ((slen = SecureRecv(fSocket, 1, fRSAKey, &tmpsalt)) == -1) {
2462  Warning("ClearAuth", "problems secure-receiving salt -"
2463  " may result in corrupted salt");
2464  Warning("ClearAuth", "switch off reuse for this session");
2465  needsalt = 0;
2466  return 0;
2467  }
2468  if (slen) {
2469  // Extract random tag, if there
2470  if (slen > 9) {
2471  int ltmp = slen;
2472  while (ltmp && tmpsalt[ltmp-1] != '#') ltmp--;
2473  if (ltmp) {
2474  if (tmpsalt[ltmp-1] == '#' &&
2475  tmpsalt[ltmp-10] == '#') {
2476  strlcpy(ctag,&tmpsalt[ltmp-10],11);
2477  // We drop the random tag
2478  ltmp -= 10;
2479  tmpsalt[ltmp] = 0;
2480  // Update salt length
2481  slen -= 10;
2482  }
2483  }
2484  if (!tmpsalt[0]) {
2485  // No salt left
2486  needsalt = 0;
2487  slen = 0;
2488  }
2489  }
2490  if (slen)
2491  salt = TString(tmpsalt);
2492  delete [] tmpsalt;
2493  }
2494  if (gDebug > 2)
2495  Info("ClearAuth", "got salt: '%s' (len: %d)", salt.Data(), slen);
2496  } else {
2497  if (gDebug > 2)
2498  Info("ClearAuth", "Salt not required");
2499  char *tmptag = 0;
2500  if (SecureRecv(fSocket, 1, fRSAKey, &tmptag) == -1) {
2501  Warning("ClearAuth", "problems secure-receiving rndmtag -"
2502  " may result in corrupted rndmtag");
2503  }
2504  if (tmptag) {
2505  strlcpy(ctag, tmptag, 11);
2506  delete [] tmptag;
2507  }
2508  }
2509  // We may not have got a salt (if the server may not access it
2510  // or if it needs the full password, like for AFS ...)
2511  if (!slen)
2512  needsalt = 0;
2513  }
2514  // Now get the password either from prompt or from memory, if saved already
2515  if (anon == 1) {
2516 
2517  if (fgPasswd.Contains("@")) {
2518  // Anonymous like login with user chosen passwd ...
2519  passwd = fgPasswd;
2520  } else {
2521  // Anonymous like login with automatic passwd generation ...
2522  TString localuser;
2523  pw = gSystem->GetUserInfo();
2524  if (pw) {
2525  char *u = StrDup(pw->fUser);
2526  localuser = u;
2527  delete[] u;
2528  }
2529  delete pw;
2530  static TString localFQDN;
2531  if (localFQDN == "") {
2533  if (addr.IsValid())
2534  localFQDN = addr.GetHostName();
2535  }
2536  passwd.Form("%s@%s", localuser.Data(), localFQDN.Data());
2537  if (gDebug > 2)
2538  Info("ClearAuth",
2539  "automatically generated anonymous passwd: %s",
2540  passwd.Data());
2541  }
2542 
2543  } else {
2544 
2545  if (prompt == 1 || pashash.Length() == 0) {
2546 
2547  if (passwd == "") {
2548  TString xp;
2549  xp.Form("%s@%s password: ", user.Data(),fRemote.Data());
2550  char *pwd = PromptPasswd(xp);
2551  passwd = TString(pwd);
2552  delete [] pwd;
2553  if (passwd == "") {
2554  Error("ClearAuth", "password not set");
2555  fSocket->Send("-1", kROOTD_PASS); // Needs this for consistency
2556  return 0;
2557  }
2558  }
2559  if (needsalt && !pwdhash) {
2560 #ifndef R__WIN32
2561  pashash = TString(crypt(passwd, salt));
2562  if (!pashash.BeginsWith(salt)) {
2563  // not the right version of the crypt function:
2564  // do not send hash
2565  pashash = passwd;
2566  }
2567 #else
2568  pashash = passwd;
2569 #endif
2570  } else {
2571  pashash = passwd;
2572  }
2573  }
2574 
2575  }
2576 
2577  // Store password for later use
2578  fgUser = fUser;
2579  fgPwHash = kFALSE;
2580  fPwHash = kFALSE;
2581  fgPasswd = passwd;
2582  fPasswd = passwd;
2583  fSRPPwd = kFALSE;
2584  fgSRPPwd = kFALSE;
2585 
2586  // Send it to server
2587  if (anon == 0 && cryptopt == 1) {
2588 
2589  // Needs to send this for consistency
2590  if (fSocket->Send("\0", kROOTD_PASS) < 0)
2591  return 0;
2592 
2593  // Add the random tag received from the server
2594  // (if any); makes packets non re-usable
2595  if (strlen(ctag))
2596  pashash += ctag;
2597 
2598  if (SecureSend(fSocket, 1, fRSAKey, pashash.Data()) == -1) {
2599  Warning("ClearAuth", "problems secure-sending pass hash"
2600  " - may result in authentication failure");
2601  return 0;
2602  }
2603  } else {
2604 
2605  // Standard technique: invert passwd
2606  if (passwd != "") {
2607  for (int i = 0; i < passwd.Length(); i++) {
2608  char inv = ~passwd(i);
2609  passwd.Replace(i, 1, inv);
2610  }
2611  }
2612  if (fSocket->Send(passwd.Data(), kROOTD_PASS) < 0)
2613  return 0;
2614  }
2615 
2616  Int_t nrec = 0;
2617  // Receive username used for login
2618  if ((nrec = fSocket->Recv(stat, kind)) < 0 ) // returns user
2619  return 0;
2620  if (gDebug > 3)
2621  Info("ClearAuth", "after kROOTD_PASS: kind= %d, stat= %d", kind,
2622  stat);
2623 
2624  // Check for errors
2625  if (kind == kROOTD_ERR) {
2626  AuthError("ClearAuth", stat);
2627  fgPasswd = "";
2628  return 0;
2629  }
2630 
2631  if (kind != kROOTD_PASS || stat < 1)
2632  Warning("ClearAuth",
2633  "problems recvn (user,offset) length (%d:%d bytes:%d)",
2634  kind, stat, nrec);
2635 
2636  // Get user and offset
2637  char answer[256];
2638  int reclen = (stat+1 > 256) ? 256 : stat+1;
2639  if ((nrec = fSocket->Recv(answer, reclen, kind)) < 0)
2640  return 0;
2641  if (kind != kMESS_STRING)
2642  Warning("ClearAuth",
2643  "username and offset not received (%d:%d)", kind,
2644  nrec);
2645 
2646  // Parse answer
2647  char lUser[128];
2648  Int_t offset = -1;
2649  sscanf(answer, "%127s %d", lUser, &offset);
2650  if (gDebug > 3)
2651  Info("ClearAuth",
2652  "received from server: user: %s, offset: %d (%s)", lUser,
2653  offset, answer);
2654 
2655  // Return username
2656  user = lUser;
2657 
2658  char *token = 0;
2659  if (reuse == 1 && offset > -1) {
2660  // Receive token
2661  if (cryptopt == 1) {
2662  if (SecureRecv(fSocket, 1, fRSAKey, &token) == -1) {
2663  Warning("ClearAuth",
2664  "problems secure-receiving token -"
2665  " may result in corrupted token");
2666  return 0;
2667  }
2668  } else {
2669  Int_t tlen = 9;
2670  token = new char[tlen];
2671  if (fSocket->Recv(token, tlen, kind) < 0) {
2672  delete [] token;
2673  return 0;
2674  }
2675  if (kind != kMESS_STRING)
2676  Warning("ClearAuth", "token not received (%d:%d)", kind,
2677  nrec);
2678  // Invert token
2679  for (int i = 0; i < (int) strlen(token); i++) {
2680  token[i] = ~token[i];
2681  }
2682 
2683  }
2684  if (gDebug > 3)
2685  Info("ClearAuth", "received from server: token: '%s' ",
2686  token);
2687  }
2688  TPwdCtx *pwdctx = new TPwdCtx(fPasswd,fPwHash);
2689  // Create SecContext object
2690  fSecContext = fHostAuth->CreateSecContext((const char *)lUser, fRemote,
2691  kClear, offset, fDetails, (const char *)token,
2692  fgExpDate, (void *)pwdctx, fRSAKey);
2693 
2694  // Release allocated memory ...
2695  if (token)
2696  delete [] token;
2697 
2698  // This from remote login
2699  if (fSocket->Recv(stat, kind) < 0)
2700  return 0;
2701 
2702 
2703  if (kind == kROOTD_AUTH && stat >= 1) {
2704  if (stat == 5 && fSocket->GetServType() == TSocket::kPROOFD)
2705  // AFS: we cannot reuse the token because remotely the
2706  // daemon token must be re-initialized; for PROOF, we
2707  // just flag the entry as AFS; this allows to skip reusing
2708  // but to keep the session key for password forwarding
2709  fSecContext->SetID("AFS authentication");
2710  return 1;
2711  } else {
2712  fgPasswd = "";
2713  if (kind == kROOTD_ERR)
2714  AuthError("ClearAuth", stat);
2715  return 0;
2716  }
2717 
2718  } else {
2719 
2720  // Old Protocol
2721 
2722  // Send username
2723  if (fSocket->Send(user.Data(), kROOTD_USER) < 0)
2724  return 0;
2725 
2726  // Get replay from server
2727  if (fSocket->Recv(stat, kind) < 0)
2728  return 0;
2729 
2730  // This check should guarantee backward compatibility with a private
2731  // version of rootd used by CDF
2732  if (kind == kROOTD_AUTH && stat == 1) {
2733  fSecContext =
2735  return 1;
2736  }
2737 
2738  if (kind == kROOTD_ERR) {
2739  TString server = "sockd";
2740  if (fProtocol.Contains("root"))
2741  server = "rootd";
2742  if (fProtocol.Contains("proof"))
2743  server = "proofd";
2744  if (stat == kErrConnectionRefused) {
2745  if (gDebug > 0)
2746  Error("ClearAuth",
2747  "%s@%s does not accept connections from %s@%s",
2748  server.Data(),fRemote.Data(),
2749  fUser.Data(),gSystem->HostName());
2750  return -2;
2751  } else if (stat == kErrNotAllowed) {
2752  if (gDebug > 0)
2753  Error("ClearAuth",
2754  "%s@%s does not accept %s authentication from %s@%s",
2755  server.Data(),fRemote.Data(),
2756  TAuthenticate::fgAuthMeth[0].Data(),
2757  fUser.Data(),gSystem->HostName());
2758  } else
2759  AuthError("ClearAuth", stat);
2760  return 0;
2761  }
2762  // Prepare passwd to send
2763  badpass1:
2764  if (passwd == "") {
2765  TString xp;
2766  xp.Form("%s@%s password: ", user.Data(),fRemote.Data());
2767  char *p = PromptPasswd(xp);
2768  passwd = p;
2769  delete [] p;
2770  if (passwd == "")
2771  Error("ClearAuth", "password not set");
2772  }
2773  if (fUser == "anonymous" || fUser == "rootd") {
2774  if (!passwd.Contains("@")) {
2775  Warning("ClearAuth",
2776  "please use passwd of form: user@host.do.main");
2777  passwd = "";
2778  goto badpass1;
2779  }
2780  }
2781 
2782  fgPasswd = passwd;
2783  fPasswd = passwd;
2784 
2785  // Invert passwd
2786  if (passwd != "") {
2787  for (int i = 0; i < passwd.Length(); i++) {
2788  char inv = ~passwd(i);
2789  passwd.Replace(i, 1, inv);
2790  }
2791  }
2792  // Send it over the net
2793  if (fSocket->Send(passwd, kROOTD_PASS) < 0)
2794  return 0;
2795 
2796  // Get result of attempt
2797  if (fSocket->Recv(stat, kind) < 0) // returns user
2798  return 0;
2799  if (gDebug > 3)
2800  Info("ClearAuth", "after kROOTD_PASS: kind= %d, stat= %d", kind,
2801  stat);
2802 
2803  if (kind == kROOTD_AUTH && stat == 1) {
2804  fSecContext =
2806  return 1;
2807  } else {
2808  if (kind == kROOTD_ERR)
2809  AuthError("ClearAuth", stat);
2810  return 0;
2811  }
2812  }
2813  return 0;
2814 }
2815 
2816 ////////////////////////////////////////////////////////////////////////////////
2817 /// Sets fUser=user and search fgAuthInfo for the entry pertaining to
2818 /// (host,user), setting fHostAuth accordingly.
2819 /// If opt = "P" use fgProofAuthInfo list instead
2820 /// If no entry is found fHostAuth is not changed
2821 
2822 THostAuth *TAuthenticate::GetHostAuth(const char *host, const char *user,
2823  Option_t *opt, Int_t *exact)
2824 {
2825  if (exact)
2826  *exact = 0;
2827 
2828  if (gDebug > 2)
2829  ::Info("TAuthenticate::GetHostAuth", "enter ... %s ... %s", host, user);
2830 
2831  // Strip off the servertype, if any
2832  Int_t srvtyp = -1;
2833  TString hostname = host;
2834  if (hostname.Contains(":")) {
2835  char *ps = (char *)strstr(host,":");
2836  if (ps)
2837  srvtyp = atoi(ps+1);
2838  hostname.Remove(hostname.Index(":"));
2839  }
2840  TString hostFQDN = hostname;
2841  if (strncmp(host,"default",7) && !hostFQDN.Contains("*")) {
2842  TInetAddress addr = gSystem->GetHostByName(hostFQDN);
2843  if (addr.IsValid())
2844  hostFQDN = addr.GetHostName();
2845  }
2846  TString usr = user;
2847  if (!usr.Length())
2848  usr = "*";
2849  THostAuth *rHA = 0;
2850 
2851  // Check list of auth info for already loaded info about this host
2852  TIter *next = new TIter(GetAuthInfo());
2853  if (!strncasecmp(opt,"P",1)) {
2854  SafeDelete(next);
2855  next = new TIter(GetProofAuthInfo());
2856  }
2857 
2858  THostAuth *ai;
2859  Bool_t notFound = kTRUE;
2860  Bool_t serverOK = kTRUE;
2861  while ((ai = (THostAuth *) (*next)())) {
2862  if (gDebug > 3)
2863  ai->Print("Authenticate::GetHostAuth");
2864 
2865  // server
2866  if (!(serverOK = (ai->GetServer() == -1) ||
2867  (ai->GetServer() == srvtyp)))
2868  continue;
2869 
2870  // Use default entry if existing and nothing more specific is found
2871  if (!strcmp(ai->GetHost(),"default") && serverOK && notFound)
2872  rHA = ai;
2873 
2874  // Check
2875  if (CheckHost(hostFQDN,ai->GetHost()) &&
2876  CheckHost(usr,ai->GetUser()) && serverOK) {
2877  rHA = ai;
2878  notFound = kFALSE;
2879  }
2880 
2881  if (hostFQDN == ai->GetHost() &&
2882  usr == ai->GetUser() && srvtyp == ai->GetServer() ) {
2883  rHA = ai;
2884  if (exact)
2885  *exact = 1;
2886  break;
2887  }
2888  }
2889  SafeDelete(next);
2890  return rHA;
2891 }
2892 
2893 ////////////////////////////////////////////////////////////////////////////////
2894 /// Checks if a THostAuth with exact match for {host,user} exists
2895 /// in the fgAuthInfo list
2896 /// If opt = "P" use ProofAuthInfo list instead
2897 /// Returns pointer to it or 0
2898 
2899 THostAuth *TAuthenticate::HasHostAuth(const char *host, const char *user,
2900  Option_t *opt)
2901 {
2902  if (gDebug > 2)
2903  ::Info("TAuthenticate::HasHostAuth", "enter ... %s ... %s", host, user);
2904 
2905  // Strip off the servertype, if any
2906  Int_t srvtyp = -1;
2907  TString hostFQDN = host;
2908  if (hostFQDN.Contains(":")) {
2909  char *ps = (char *)strstr(host,":");
2910  if (ps)
2911  srvtyp = atoi(ps+1);
2912  hostFQDN.Remove(hostFQDN.Index(":"));
2913  }
2914  if (strncmp(host,"default",7) && !hostFQDN.Contains("*")) {
2915  TInetAddress addr = gSystem->GetHostByName(hostFQDN);
2916  if (addr.IsValid())
2917  hostFQDN = addr.GetHostName();
2918  }
2919 
2920  TIter *next = new TIter(GetAuthInfo());
2921  if (!strncasecmp(opt,"P",1)) {
2922  SafeDelete(next);
2923  next = new TIter(GetProofAuthInfo());
2924  }
2925  THostAuth *ai;
2926  while ((ai = (THostAuth *) (*next)())) {
2927 
2928  if (hostFQDN == ai->GetHost() &&
2929  !strcmp(user, ai->GetUser()) && srvtyp == ai->GetServer()) {
2930  SafeDelete(next);
2931  return ai;
2932  }
2933  }
2934  SafeDelete(next);
2935  return 0;
2936 }
2937 
2938 ////////////////////////////////////////////////////////////////////////////////
2939 /// Expands include directives found in fexp files
2940 /// The expanded, temporary file, is pointed to by 'ftmp'
2941 /// and should be already open. To be called recursively.
2942 
2943 void TAuthenticate::FileExpand(const char *fexp, FILE *ftmp)
2944 {
2945  FILE *fin;
2946  char line[kMAXPATHLEN];
2947  char cinc[20], fileinc[kMAXPATHLEN];
2948 
2949  if (gDebug > 2)
2950  ::Info("TAuthenticate::FileExpand", "enter ... '%s' ... 0x%lx", fexp, (Long_t)ftmp);
2951 
2952  fin = fopen(fexp, "r");
2953  if (fin == 0)
2954  return;
2955 
2956  while (fgets(line, sizeof(line), fin) != 0) {
2957  // Skip comment lines
2958  if (line[0] == '#')
2959  continue;
2960  if (line[strlen(line) - 1] == '\n')
2961  line[strlen(line) - 1] = '\0';
2962  if (gDebug > 2)
2963  ::Info("TAuthenticate::FileExpand", "read line ... '%s'", line);
2964  int nw = sscanf(line, "%19s %8191s", cinc, fileinc);
2965  if (nw < 1)
2966  continue; // Not enough info in this line
2967  if (strcmp(cinc, "include") != 0) {
2968  // copy line in temporary file
2969  fprintf(ftmp, "%s\n", line);
2970  } else {
2971 
2972  // Drop quotes or double quotes, if any
2973  TString ln(line);
2974  ln.ReplaceAll("\"",1,"",0);
2975  ln.ReplaceAll("'",1,"",0);
2976  sscanf(ln.Data(), "%19s %8191s", cinc, fileinc);
2977 
2978  // support environment directories ...
2979  if (fileinc[0] == '$') {
2980  TString finc(fileinc);
2981  TString edir(fileinc);
2982  if (edir.Contains("/")) {
2983  edir.Remove(edir.Index("/"));
2984  edir.Remove(0,1);
2985  if (gSystem->Getenv(edir.Data())) {
2986  finc.Remove(0,1);
2987  finc.ReplaceAll(edir.Data(),gSystem->Getenv(edir.Data()));
2988  fileinc[0] = '\0';
2989  strncpy(fileinc,finc.Data(),kMAXPATHLEN);
2990  fileinc[kMAXPATHLEN-1] = '\0';
2991  }
2992  }
2993  }
2994 
2995  // open (expand) file in temporary file ...
2996  if (fileinc[0] == '~') {
2997  // needs to expand
2998  int flen =
2999  strlen(fileinc) + strlen(gSystem->HomeDirectory()) + 10;
3000  char *ffull = new char[flen];
3001  snprintf(ffull, flen, "%s/%s", gSystem->HomeDirectory(), fileinc + 1);
3002  if (strlen(ffull) < kMAXPATHLEN - 1) strlcpy(fileinc, ffull,kMAXPATHLEN);
3003  delete [] ffull;
3004  }
3005  // Check if file exist and can be read ... ignore if not ...
3006  if (!gSystem->AccessPathName(fileinc, kReadPermission)) {
3007  FileExpand(fileinc, ftmp);
3008  } else {
3009  ::Warning("TAuthenticate::FileExpand",
3010  "file specified by 'include' cannot be open or read (%s)",
3011  fileinc);
3012  }
3013  }
3014  }
3015  fclose(fin);
3016 }
3017 
3018 ////////////////////////////////////////////////////////////////////////////////
3019 /// Determine default authentication details for method 'sec' and user 'usr'.
3020 /// Checks .rootrc family files. Returned string must be deleted by the user.
3021 
3022 char *TAuthenticate::GetDefaultDetails(int sec, int opt, const char *usr)
3023 {
3024  char temp[kMAXPATHLEN] = { 0 };
3025  const char copt[2][5] = { "no", "yes" };
3026 
3027  if (gDebug > 2)
3028  ::Info("TAuthenticate::GetDefaultDetails",
3029  "enter ... %d ...pt:%d ... '%s'", sec, opt, usr);
3030 
3031  if (opt < 0 || opt > 1)
3032  opt = 1;
3033 
3034  // UsrPwd
3035  if (sec == TAuthenticate::kClear) {
3036  if (!usr[0] || !strncmp(usr,"*",1))
3037  usr = gEnv->GetValue("UsrPwd.Login", "");
3038  snprintf(temp, kMAXPATHLEN, "pt:%s ru:%s cp:%s us:%s",
3039  gEnv->GetValue("UsrPwd.LoginPrompt", copt[opt]),
3040  gEnv->GetValue("UsrPwd.ReUse", "1"),
3041  gEnv->GetValue("UsrPwd.Crypt", "1"), usr);
3042 
3043  // SRP
3044  } else if (sec == TAuthenticate::kSRP) {
3045  if (!usr[0] || !strncmp(usr,"*",1))
3046  usr = gEnv->GetValue("SRP.Login", "");
3047  snprintf(temp, kMAXPATHLEN, "pt:%s ru:%s us:%s",
3048  gEnv->GetValue("SRP.LoginPrompt", copt[opt]),
3049  gEnv->GetValue("SRP.ReUse", "0"), usr);
3050 
3051  // Kerberos
3052  } else if (sec == TAuthenticate::kKrb5) {
3053  if (!usr[0] || !strncmp(usr,"*",1))
3054  usr = gEnv->GetValue("Krb5.Login", "");
3055  snprintf(temp, kMAXPATHLEN, "pt:%s ru:%s us:%s",
3056  gEnv->GetValue("Krb5.LoginPrompt", copt[opt]),
3057  gEnv->GetValue("Krb5.ReUse", "0"), usr);
3058 
3059  // Globus
3060  } else if (sec == TAuthenticate::kGlobus) {
3061  snprintf(temp, kMAXPATHLEN,"pt:%s ru:%s %s",
3062  gEnv->GetValue("Globus.LoginPrompt", copt[opt]),
3063  gEnv->GetValue("Globus.ReUse", "1"),
3064  gEnv->GetValue("Globus.Login", ""));
3065 
3066  // SSH
3067  } else if (sec == TAuthenticate::kSSH) {
3068  if (!usr[0] || !strncmp(usr,"*",1))
3069  usr = gEnv->GetValue("SSH.Login", "");
3070  snprintf(temp, kMAXPATHLEN, "pt:%s ru:%s us:%s",
3071  gEnv->GetValue("SSH.LoginPrompt", copt[opt]),
3072  gEnv->GetValue("SSH.ReUse", "1"), usr);
3073 
3074  // Uid/Gid
3075  } else if (sec == TAuthenticate::kRfio) {
3076  if (!usr[0] || !strncmp(usr,"*",1))
3077  usr = gEnv->GetValue("UidGid.Login", "");
3078  snprintf(temp, kMAXPATHLEN, "pt:%s us:%s",
3079  gEnv->GetValue("UidGid.LoginPrompt", copt[opt]), usr);
3080  }
3081  if (gDebug > 2)
3082  ::Info("TAuthenticate::GetDefaultDetails", "returning ... %s", temp);
3083 
3084  return StrDup(temp);
3085 }
3086 
3087 ////////////////////////////////////////////////////////////////////////////////
3088 /// Remove THostAuth instance from the list
3089 
3091 {
3092  if (!strncasecmp(opt,"P",1))
3093  GetProofAuthInfo()->Remove(ha);
3094  else
3095  GetAuthInfo()->Remove(ha);
3096  // ... destroy it
3097  delete ha;
3098 }
3099 
3100 ////////////////////////////////////////////////////////////////////////////////
3101 /// Print info about the authentication sector.
3102 /// If 'opt' contains 's' or 'S' prints information about established TSecContext,
3103 /// else prints information about THostAuth (if 'opt' is 'p' or 'P', prints
3104 /// Proof related information)
3105 
3107 {
3108  TString sopt(opt);
3109 
3110  if (sopt.Contains("s",TString::kIgnoreCase)) {
3111 
3112  // Print established security contexts
3113  TIter next(gROOT->GetListOfSecContexts());
3114  TSecContext *sc = 0;
3115  while ((sc = (TSecContext *)next()))
3116  sc->Print();
3117 
3118  } else {
3119 
3120  ::Info("::Print",
3121  " +--------------------------- BEGIN --------------------------------+");
3122  ::Info("::Print",
3123  " + +");
3124  if (sopt.Contains("p",TString::kIgnoreCase)) {
3125  ::Info("::Print",
3126  " + List fgProofAuthInfo has %4d members +",
3127  GetProofAuthInfo()->GetSize());
3128  ::Info("::Print",
3129  " + +");
3130  ::Info("::Print",
3131  " +------------------------------------------------------------------+");
3132  TIter next(GetProofAuthInfo());
3133  THostAuth *ai;
3134  while ((ai = (THostAuth *) next())) {
3135  ai->Print();
3136  }
3137  } else {
3138  ::Info("::Print",
3139  " + List fgAuthInfo has %4d members +",
3140  GetAuthInfo()->GetSize());
3141  ::Info("::Print",
3142  " + +");
3143  ::Info("::Print",
3144  " +------------------------------------------------------------------+");
3145  TIter next(GetAuthInfo());
3146  THostAuth *ai;
3147  while ((ai = (THostAuth *) next())) {
3148  ai->Print();
3149  ai->PrintEstablished();
3150  }
3151  }
3152  ::Info("::Print",
3153  " +---------------------------- END ---------------------------------+");
3154  }
3155 }
3156 
3157 ////////////////////////////////////////////////////////////////////////////////
3158 /// Check if we have a valid established sec context in memory
3159 /// Retrieves relevant info and negotiates with server.
3160 /// options = "Opt,strlen(username),username.Data()"
3161 /// message = kROOTD_USER, ...
3162 
3163 Int_t TAuthenticate::AuthExists(TString username, Int_t method, const char *options,
3164  Int_t *message, Int_t *rflag,
3165  CheckSecCtx_t checksecctx)
3166 {
3167  // Welcome message, if requested ...
3168  if (gDebug > 2)
3169  Info("AuthExists","%d: enter: msg: %d options: '%s'",
3170  method,*message, options);
3171 
3172  // Look for an existing security context matching this request
3173  Bool_t notHA = kFALSE;
3174 
3175  // First in the local list
3176  TIter next(fHostAuth->Established());
3177  TRootSecContext *secctx;
3178  while ((secctx = (TRootSecContext *)next())) {
3179  if (secctx->GetMethod() == method) {
3180  if (fRemote == secctx->GetHost()) {
3181  if (checksecctx &&
3182  (*checksecctx)(username,secctx) == 1)
3183  break;
3184  }
3185  }
3186  }
3187 
3188  // If nothing found, try the all list
3189  if (!secctx) {
3190  next = TIter(gROOT->GetListOfSecContexts());
3191  while ((secctx = (TRootSecContext *)next())) {
3192  if (secctx->GetMethod() == method) {
3193  if (fRemote == secctx->GetHost()) {
3194  if (checksecctx &&
3195  (*checksecctx)(username,secctx) == 1) {
3196  notHA = kTRUE;
3197  break;
3198  }
3199  }
3200  }
3201  }
3202  }
3203 
3204  // If we have been given a valid sec context retrieve some info
3205  Int_t offset = -1;
3206  TString token;
3207  if (secctx) {
3208  offset = secctx->GetOffSet();
3209  token = secctx->GetToken();
3210  if (gDebug > 2)
3211  Info("AuthExists",
3212  "found valid TSecContext: offset: %d token: '%s'",
3213  offset, token.Data());
3214  }
3215 
3216  // Prepare string to be sent to the server
3217  TString sstr;
3218  sstr.Form("%d %d %s", fgProcessID, offset, options);
3219 
3220  // Send message
3221  if (fSocket->Send(sstr, *message) < 0)
3222  return -2;
3223 
3224  Int_t reuse = *rflag;
3225  if (reuse == 1 && offset > -1) {
3226 
3227  // Receive result of checking offset
3228  // But only for recent servers
3229  // NB: not backward compatible with dev version 4.00.02: switch
3230  // off 'reuse' for such servers to avoid hanging at this point.
3231  Int_t rproto = fSocket->GetRemoteProtocol();
3232  Bool_t oldsrv = ((fProtocol.BeginsWith("root") && rproto == 9) ||
3233  (fProtocol.BeginsWith("proof") && rproto == 8));
3234  Int_t stat = 1, kind;
3235  if (!oldsrv) {
3236  if (fSocket->Recv(stat, kind) < 0)
3237  return -2;
3238  if (kind != kROOTD_AUTH)
3239  Warning("AuthExists","protocol error: expecting %d got %d"
3240  " (value: %d)",kROOTD_AUTH,kind,stat);
3241  }
3242 
3243  if (stat > 0) {
3244  if (gDebug > 2)
3245  Info("AuthExists","offset OK");
3246 
3247  Int_t rsaKey = secctx->GetRSAKey();
3248  if (gDebug > 2)
3249  Info("AuthExists", "key type: %d", rsaKey);
3250 
3251  if (rsaKey > -1) {
3252 
3253  // Recent servers send a random tag in stat
3254  // It has to be signed too
3255  if (stat > 1) {
3256  // Create hex from tag
3257  char tag[9] = {0};
3258  snprintf(tag, 9, "%08x",stat);
3259  // Add to token
3260  token += tag;
3261  }
3262 
3263  // Send token encrypted
3264  if (SecureSend(fSocket, 1, rsaKey, token) == -1) {
3265  Warning("AuthExists", "problems secure-sending token %s",
3266  "- may trigger problems in proofing Id ");
3267  return -2;
3268  }
3269  } else {
3270  // Send inverted
3271  for (int i = 0; i < token.Length(); i++) {
3272  char inv = ~token(i);
3273  token.Replace(i, 1, inv);
3274  }
3275  if (fSocket->Send(token, kMESS_STRING) < 0)
3276  return -2;
3277  }
3278  } else {
3279  if (gDebug > 0)
3280  Info("AuthExists","offset not OK - rerun authentication");
3281  // If the sec context was not valid, deactivate it ...
3282  if (secctx)
3283  secctx->DeActivate("");
3284  }
3285  }
3286 
3287  Int_t stat, kind;
3288  if (fSocket->Recv(stat, kind) < 0)
3289  return -2;
3290  if (gDebug > 3)
3291  Info("AuthExists","%d: after msg %d: kind= %d, stat= %d",
3292  method,*message, kind, stat);
3293 
3294  // Return flags
3295  *message = kind;
3296  *rflag = stat;
3297 
3298  if (kind == kROOTD_ERR) {
3299  TString server = "sockd";
3301  server = "rootd";
3303  server = "proofd";
3304  if (stat == kErrConnectionRefused) {
3305  Error("AuthExists","%s@%s does not accept connections from %s@%s",
3306  server.Data(),fRemote.Data(),fUser.Data(),gSystem->HostName());
3307  return -2;
3308  } else if (stat == kErrNotAllowed) {
3309  if (gDebug > 0)
3310  Info("AuthExists",
3311  "%s@%s does not accept %s authentication from %s@%s",
3312  server.Data(),fRemote.Data(), fgAuthMeth[method].Data(),
3313  fUser.Data(),gSystem->HostName());
3314  } else
3315  AuthError("AuthExists", stat);
3316 
3317  // If the sec context was not valid, deactivate it ...
3318  if (secctx)
3319  secctx->DeActivate("");
3320  return 0;
3321  }
3322 
3323  if (kind == kROOTD_AUTH && stat >= 1) {
3324  if (!secctx)
3325  secctx =
3326  fHostAuth->CreateSecContext(fUser,fRemote,method,-stat,fDetails,0);
3327  if (gDebug > 3) {
3328  if (stat == 1)
3329  Info("AuthExists", "valid authentication exists");
3330  if (stat == 2)
3331  Info("AuthExists", "valid authentication exists: offset changed");
3332  if (stat == 3)
3333  Info("AuthExists", "remote access authorized by /etc/hosts.equiv");
3334  if (stat == 4)
3335  Info("AuthExists", "no authentication required remotely");
3336  }
3337 
3338  if (stat == 2) {
3339  int newOffSet;
3340  // Receive new offset ...
3341  if (fSocket->Recv(newOffSet, kind) < 0)
3342  return -2;
3343  // ... and save it
3344  secctx->SetOffSet(newOffSet);
3345  }
3346 
3347  fSecContext = secctx;
3348  // Add it to local list for later use (if not already there)
3349  if (notHA)
3350  fHostAuth->Established()->Add(secctx);
3351  return 1;
3352  }
3353  return 0;
3354 }
3355 
3356 ////////////////////////////////////////////////////////////////////////////////
3357 /// Initialize random machine using seed from /dev/urandom
3358 /// (or current time if /dev/urandom not available).
3359 
3361 {
3362  static Bool_t notinit = kTRUE;
3363 
3364  if (notinit) {
3365  const char *randdev = "/dev/urandom";
3366  Int_t fd;
3367  UInt_t seed;
3368  if ((fd = open(randdev, O_RDONLY)) != -1) {
3369  if (gDebug > 2)
3370  ::Info("InitRandom", "taking seed from %s", randdev);
3371  if (read(fd, &seed, sizeof(seed)) != sizeof(seed))
3372  ::Warning("InitRandom", "could not read seed from %s", randdev);
3373  close(fd);
3374  } else {
3375  if (gDebug > 2)
3376  ::Info("InitRandom", "%s not available: using time()", randdev);
3377  seed = time(0); //better use times() + win32 equivalent
3378  }
3379  srand(seed);
3380  notinit = kFALSE;
3381  }
3382 }
3383 
3384 ////////////////////////////////////////////////////////////////////////////////
3385 /// Generate a valid pair of private/public RSA keys to protect for
3386 /// authentication token exchange
3387 
3389 {
3390  if (gDebug > 2)
3391  Info("GenRSAKeys", "enter");
3392 
3393  if (fgRSAInit == 1) {
3394  if (gDebug > 2)
3395  Info("GenRSAKeys", "Keys prviously generated - return");
3396  }
3397 
3398  // This is for dynamic loads ...
3399  TString lib = "libRsa";
3400 
3401  // This is the local RSA implementation
3402  if (!TRSA_fun::RSA_genprim()) {
3403  char *p;
3404  if ((p = gSystem->DynamicPathName(lib, kTRUE))) {
3405  delete [] p;
3406  gSystem->Load(lib);
3407  }
3408  }
3409 
3410  // Init random machine
3412 
3413 #ifdef R__SSL
3414  if (fgRSAKey == 1) {
3415  // Generate also the SSL key
3416  if (gDebug > 2)
3417  Info("GenRSAKeys","SSL: Generate Blowfish key");
3418 
3419  // Init SSL ...
3420  SSL_library_init();
3421 
3422  // ... and its error strings
3424 
3425  // Load Ciphers
3426  OpenSSL_add_all_ciphers();
3427 
3428  // Number of bits for key
3429  Int_t nbits = gEnv->GetValue("SSL.BFBits",256);
3430 
3431  // Minimum is 128
3432  nbits = (nbits >= 128) ? nbits : 128;
3433 
3434  // Max to limit size of buffers to 15912 (internal limitation)
3435  nbits = (nbits <= 15912) ? nbits : 15912;
3436 
3437  // Closer Number of chars
3438  Int_t klen = nbits / 8 ;
3439 
3440  // Init random engine
3441  char *rbuf = GetRandString(0,klen);
3442  RAND_seed(rbuf,strlen(rbuf));
3443 
3444  // This is what we export
3445  fgRSAPubExport[1].len = klen;
3446  fgRSAPubExport[1].keys = rbuf;
3447  if (gDebug > 2)
3448  Info("GenRSAKeys","SSL: BF key length: %d", fgRSAPubExport[1].len);
3449 
3450  // Now set the key locally in BF form
3451  BF_set_key(&fgBFKey, klen, (const unsigned char *)rbuf);
3452  }
3453 #endif
3454 
3455  // Sometimes some bunch is not decrypted correctly
3456  // That's why we make retries to make sure that encryption/decryption
3457  // works as expected
3458  Bool_t notOk = 1;
3459  rsa_NUMBER p1, p2, rsa_n, rsa_e, rsa_d;
3460  Int_t l_n = 0, l_d = 0;
3461  char buf_n[rsa_STRLEN], buf_e[rsa_STRLEN], buf_d[rsa_STRLEN];
3462 #if R__RSADE
3463  Int_t l_e;
3464  char buf[rsa_STRLEN];
3465 #endif
3466 
3467  Int_t nAttempts = 0;
3468  Int_t thePrimeLen = kPRIMELENGTH;
3469  Int_t thePrimeExp = kPRIMEEXP; // Prime probability = 1-0.5^thePrimeExp
3470  while (notOk && nAttempts < kMAXRSATRIES) {
3471 
3472  nAttempts++;
3473  if (gDebug > 2 && nAttempts > 1) {
3474  Info("GenRSAKeys", "retry no. %d",nAttempts);
3475  srand(auth_rand());
3476  }
3477 
3478  // Valid pair of primes
3479  p1 = TRSA_fun::RSA_genprim()(thePrimeLen, thePrimeExp);
3480  p2 = TRSA_fun::RSA_genprim()(thePrimeLen+1, thePrimeExp);
3481 
3482  // Retry if equal
3483  Int_t nPrimes = 0;
3484  while (TRSA_fun::RSA_cmp()(&p1, &p2) == 0 && nPrimes < kMAXRSATRIES) {
3485  nPrimes++;
3486  if (gDebug > 2)
3487  Info("GenRSAKeys", "equal primes: regenerate (%d times)",nPrimes);
3488  srand(auth_rand());
3489  p1 = TRSA_fun::RSA_genprim()(thePrimeLen, thePrimeExp);
3490  p2 = TRSA_fun::RSA_genprim()(thePrimeLen+1, thePrimeExp);
3491  }
3492 #if R__RSADEB
3493  if (gDebug > 3) {
3495  Info("GenRSAKeys", "local: p1: '%s' ", buf);
3497  Info("GenRSAKeys", "local: p2: '%s' ", buf);
3498  }
3499 #endif
3500  // Generate keys
3501  if (TRSA_fun::RSA_genrsa()(p1, p2, &rsa_n, &rsa_e, &rsa_d)) {
3502  if (gDebug > 2 && nAttempts > 1)
3503  Info("GenRSAKeys"," genrsa: unable to generate keys (%d)",
3504  nAttempts);
3505  continue;
3506  }
3507 
3508  // Get equivalent strings and determine their lengths
3509  TRSA_fun::RSA_num_sput()(&rsa_n, buf_n, rsa_STRLEN);
3510  l_n = strlen(buf_n);
3511  TRSA_fun::RSA_num_sput()(&rsa_e, buf_e, rsa_STRLEN);
3512 #if R__RSADEB
3513  l_e = strlen(buf_e);
3514 #endif
3515  TRSA_fun::RSA_num_sput()(&rsa_d, buf_d, rsa_STRLEN);
3516  l_d = strlen(buf_d);
3517 
3518 #if R__RSADEB
3519  if (gDebug > 3) {
3520  Info("GenRSAKeys", "local: n: '%s' length: %d", buf_n, l_n);
3521  Info("GenRSAKeys", "local: e: '%s' length: %d", buf_e, l_e);
3522  Info("GenRSAKeys", "local: d: '%s' length: %d", buf_d, l_d);
3523  }
3524 #endif
3525  if (TRSA_fun::RSA_cmp()(&rsa_n, &rsa_e) <= 0)
3526  continue;
3527  if (TRSA_fun::RSA_cmp()(&rsa_n, &rsa_d) <= 0)
3528  continue;
3529 
3530  // Now we try the keys
3531  char test[2 * rsa_STRLEN] = "ThisIsTheStringTest01203456-+/";
3532  Int_t lTes = 31;
3533  char *tdum = GetRandString(0, lTes - 1);
3534  strlcpy(test, tdum, lTes+1);
3535  delete [] tdum;
3536  char buf[2 * rsa_STRLEN];
3537  if (gDebug > 3)
3538  Info("GenRSAKeys", "local: test string: '%s' ", test);
3539 
3540  // Private/Public
3541  strlcpy(buf, test, lTes+1);
3542 
3543  // Try encryption with private key
3544  int lout = TRSA_fun::RSA_encode()(buf, lTes, rsa_n, rsa_e);
3545  if (gDebug > 3)
3546  Info("GenRSAKeys",
3547  "local: length of crypted string: %d bytes", lout);
3548 
3549  // Try decryption with public key
3550  TRSA_fun::RSA_decode()(buf, lout, rsa_n, rsa_d);
3551  buf[lTes] = 0;
3552  if (gDebug > 3)
3553  Info("GenRSAKeys", "local: after private/public : '%s' ", buf);
3554 
3555  if (strncmp(test, buf, lTes))
3556  continue;
3557 
3558  // Public/Private
3559  strlcpy(buf, test, lTes+1);
3560 
3561  // Try encryption with public key
3562  lout = TRSA_fun::RSA_encode()(buf, lTes, rsa_n, rsa_d);
3563  if (gDebug > 3)
3564  Info("GenRSAKeys", "local: length of crypted string: %d bytes ",
3565  lout);
3566 
3567  // Try decryption with private key
3568  TRSA_fun::RSA_decode()(buf, lout, rsa_n, rsa_e);
3569  buf[lTes] = 0;
3570  if (gDebug > 3)
3571  Info("GenRSAKeys", "local: after public/private : '%s' ", buf);
3572 
3573  if (strncmp(test, buf, lTes))
3574  continue;
3575 
3576  notOk = 0;
3577  }
3578 
3579  // Save Private key
3580  TRSA_fun::RSA_assign()(&fgRSAPriKey.n, &rsa_n);
3581  TRSA_fun::RSA_assign()(&fgRSAPriKey.e, &rsa_e);
3582 
3583  // Save Public key
3584  TRSA_fun::RSA_assign()(&fgRSAPubKey.n, &rsa_n);
3585  TRSA_fun::RSA_assign()(&fgRSAPubKey.e, &rsa_d);
3586 
3587 #if R__RSADEB
3588  if (gDebug > 2) {
3589  // Determine their lengths
3590  Info("GenRSAKeys", "local: generated keys are:");
3591  Info("GenRSAKeys", "local: n: '%s' length: %d", buf_n, l_n);
3592  Info("GenRSAKeys", "local: e: '%s' length: %d", buf_e, l_e);
3593  Info("GenRSAKeys", "local: d: '%s' length: %d", buf_d, l_d);
3594  }
3595 #endif
3596  // Export form
3597  if (fgRSAPubExport[0].keys) {
3598  delete [] fgRSAPubExport[0].keys;
3599  fgRSAPubExport[0].len = 0;
3600  }
3601  fgRSAPubExport[0].len = l_n + l_d + 4;
3602  fgRSAPubExport[0].keys = new char[fgRSAPubExport[0].len];
3603 
3604  fgRSAPubExport[0].keys[0] = '#';
3605  memcpy(fgRSAPubExport[0].keys + 1, buf_n, l_n);
3606  fgRSAPubExport[0].keys[l_n + 1] = '#';
3607  memcpy(fgRSAPubExport[0].keys + l_n + 2, buf_d, l_d);
3608  fgRSAPubExport[0].keys[l_n + l_d + 2] = '#';
3609  fgRSAPubExport[0].keys[l_n + l_d + 3] = 0;
3610 #if R__RSADEB
3611  if (gDebug > 2)
3612  Info("GenRSAKeys", "local: export pub: '%s'", fgRSAPubExport[0].keys);
3613 #else
3614  if (gDebug > 2)
3615  Info("GenRSAKeys", "local: export pub length: %d bytes", fgRSAPubExport[0].len);
3616 #endif
3617 
3618  // Set availability flag
3619  fgRSAInit = 1;
3620 
3621  return 0;
3622 }
3623 
3624 ////////////////////////////////////////////////////////////////////////////////
3625 /// Allocates and fills a 0 terminated buffer of length len+1 with
3626 /// len random characters.
3627 /// Returns pointer to the buffer (to be deleted by the caller)
3628 /// opt = 0 any non dangerous char
3629 /// 1 letters and numbers (upper and lower case)
3630 /// 2 hex characters (upper and lower case)
3631 
3633 {
3634  unsigned int iimx[4][4] = {
3635  {0x0, 0xffffff08, 0xafffffff, 0x2ffffffe}, // opt = 0
3636  {0x0, 0x3ff0000, 0x7fffffe, 0x7fffffe}, // opt = 1
3637  {0x0, 0x3ff0000, 0x7e, 0x7e}, // opt = 2
3638  {0x0, 0x3ffc000, 0x7fffffe, 0x7fffffe} // opt = 3
3639  };
3640 
3641  const char *cOpt[4] = { "Any", "LetNum", "Hex", "Crypt" };
3642 
3643  // Default option 0
3644  if (opt < 0 || opt > 2) {
3645  opt = 0;
3646  if (gDebug > 2)
3647  Info("GetRandString", "unknown option: %d : assume 0", opt);
3648  }
3649  if (gDebug > 2)
3650  Info("GetRandString", "enter ... len: %d %s", len, cOpt[opt]);
3651 
3652  // Allocate buffer
3653  char *buf = new char[len + 1];
3654 
3655  // Init random machine (if needed)
3657 
3658  // randomize
3659  Int_t k = 0;
3660  Int_t i, j, l, m, frnd;
3661  while (k < len) {
3662  frnd = auth_rand();
3663  for (m = 7; m < 32; m += 7) {
3664  i = 0x7F & (frnd >> m);
3665  j = i / 32;
3666  l = i - j * 32;
3667  if ((iimx[opt][j] & (1 << l))) {
3668  buf[k] = i;
3669  k++;
3670  }
3671  if (k == len)
3672  break;
3673  }
3674  }
3675 
3676  // null terminated
3677  buf[len] = 0;
3678  if (gDebug > 3)
3679  Info("GetRandString", "got '%s' ", buf);
3680 
3681  return buf;
3682 }
3683 
3684 ////////////////////////////////////////////////////////////////////////////////
3685 /// Encode null terminated str using the session private key indicated by enc
3686 /// and sends it over the network
3687 /// Returns number of bytes sent, or -1 in case of error.
3688 /// enc = 1 for private encoding, enc = 2 for public encoding
3689 
3691  Int_t key, const char *str)
3692 {
3693  char buftmp[kMAXSECBUF];
3694  char buflen[20];
3695 
3696  if (gDebug > 2)
3697  ::Info("TAuthenticate::SecureSend", "local: enter ... (enc: %d)", enc);
3698 
3699  Int_t slen = strlen(str) + 1;
3700  Int_t ttmp = 0;
3701  Int_t nsen = -1;
3702 
3703  if (key == 0) {
3704  strlcpy(buftmp, str, slen+1);
3705 
3706  if (enc == 1)
3707  ttmp = TRSA_fun::RSA_encode()(buftmp, slen, fgRSAPriKey.n,
3708  fgRSAPriKey.e);
3709  else if (enc == 2)
3710  ttmp = TRSA_fun::RSA_encode()(buftmp, slen, fgRSAPubKey.n,
3711  fgRSAPubKey.e);
3712  else
3713  return nsen;
3714  } else if (key == 1) {
3715 
3716 #ifdef R__SSL
3717  ttmp = strlen(str);
3718  if ((ttmp % 8) > 0) // It should be a multiple of 8!
3719  ttmp = ((ttmp + 8)/8) * 8;
3720  unsigned char iv[8];
3721  memset((void *)&iv[0],0,8);
3722  BF_cbc_encrypt((const unsigned char *)str, (unsigned char *)buftmp,
3723  strlen(str), &fgBFKey, iv, BF_ENCRYPT);
3724 #else
3725  if (gDebug > 0)
3726  ::Info("TAuthenticate::SecureSend","not compiled with SSL support:"
3727  " you should not have got here!");
3728 #endif
3729  } else {
3730  if (gDebug > 0)
3731  ::Info("TAuthenticate::SecureSend","unknown key type (%d)",key);
3732  return nsen;
3733  }
3734 
3735  snprintf(buflen,20,"%d",ttmp);
3736  if (sock->Send(buflen, kROOTD_ENCRYPT) < 0)
3737  return -1;
3738  nsen = sock->SendRaw(buftmp, ttmp);
3739  if (gDebug > 3)
3740  ::Info("TAuthenticate::SecureSend",
3741  "local: sent %d bytes (expected: %d)", nsen,ttmp);
3742 
3743  return nsen;
3744 }
3745 
3746 ////////////////////////////////////////////////////////////////////////////////
3747 /// Receive str from sock and decode it using key indicated by key type
3748 /// Return number of received bytes or -1 in case of error.
3749 /// dec = 1 for private decoding, dec = 2 for public decoding
3750 
3751 Int_t TAuthenticate::SecureRecv(TSocket *sock, Int_t dec, Int_t key, char **str)
3752 {
3753 
3754  char buftmp[kMAXSECBUF];
3755  char buflen[20];
3756 
3757  Int_t nrec = -1;
3758  // We must get a pointer ...
3759  if (!str)
3760  return nrec;
3761 
3762  Int_t kind;
3763  if (sock->Recv(buflen, 20, kind) < 0)
3764  return -1;
3765  Int_t len = atoi(buflen);
3766  if (gDebug > 3)
3767  ::Info("TAuthenticate::SecureRecv", "got len '%s' %d (msg kind: %d)",
3768  buflen, len, kind);
3769  if (len == 0) {
3770  return len;
3771  }
3772  if (!strncmp(buflen, "-1", 2))
3773  return nrec;
3774 
3775  // Receive buffer
3776  if ((nrec = sock->RecvRaw(buftmp, len)) < 0)
3777  return nrec;
3778  if (key == 0) {
3779  if (dec == 1)
3780  TRSA_fun::RSA_decode()(buftmp, len, fgRSAPriKey.n, fgRSAPriKey.e);
3781  else if (dec == 2)
3782  TRSA_fun::RSA_decode()(buftmp, len, fgRSAPubKey.n, fgRSAPubKey.e);
3783  else
3784  return -1;
3785 
3786  // Prepare output
3787  const size_t strSize = strlen(buftmp) + 1;
3788  *str = new char[strSize];
3789  strlcpy(*str, buftmp, strSize);
3790 
3791  } else if (key == 1) {
3792 #ifdef R__SSL
3793  unsigned char iv[8];
3794  memset((void *)&iv[0],0,8);
3795  *str = new char[nrec + 1];
3796  BF_cbc_encrypt((const unsigned char *)buftmp, (unsigned char *)(*str),
3797  nrec, &fgBFKey, iv, BF_DECRYPT);
3798  (*str)[nrec] = '\0';
3799 #else
3800  if (gDebug > 0)
3801  ::Info("TAuthenticate::SecureRecv","not compiled with SSL support:"
3802  " you should not have got here!");
3803 #endif
3804  } else {
3805  if (gDebug > 0)
3806  ::Info("TAuthenticate::SecureRecv","unknown key type (%d)",key);
3807  return -1;
3808  }
3809 
3810  nrec= strlen(*str);
3811 
3812  return nrec;
3813 }
3814 
3815 ////////////////////////////////////////////////////////////////////////////////
3816 /// Store RSA public keys from export string rsaPubExport.
3817 
3818 Int_t TAuthenticate::DecodeRSAPublic(const char *rsaPubExport, rsa_NUMBER &rsa_n,
3819  rsa_NUMBER &rsa_d, char **rsassl)
3820 {
3821  if (!rsaPubExport)
3822  return -1;
3823 
3824  if (gDebug > 2)
3825  ::Info("TAuthenticate::DecodeRSAPublic",
3826  "enter: string length: %ld bytes", (Long_t)strlen(rsaPubExport));
3827 
3828  char str[kMAXPATHLEN] = { 0 };
3829  Int_t klen = strlen(rsaPubExport);
3830  if (klen > kMAXPATHLEN - 1) {
3831  ::Info("TAuthenticate::DecodeRSAPublic",
3832  "key too long (%d): truncate to %d",klen,kMAXPATHLEN);
3833  klen = kMAXPATHLEN - 1;
3834  }
3835  memcpy(str, rsaPubExport, klen);
3836  str[klen] ='\0';
3837 
3838  Int_t keytype = -1;
3839 
3840  if (klen > 0) {
3841 
3842  // Skip spaces at beginning, if any
3843  int k = 0;
3844  while (str[k] == 32) k++;
3845 
3846  if (str[k] == '#') {
3847 
3848  keytype = 0;
3849 
3850  // The format is #<hex_n>#<hex_d>#
3851  char *pd1 = strstr(str, "#");
3852  char *pd2 = pd1 ? strstr(pd1 + 1, "#") : (char *)0;
3853  char *pd3 = pd2 ? strstr(pd2 + 1, "#") : (char *)0;
3854  if (pd1 && pd2 && pd3) {
3855  // Get <hex_n> ...
3856  int l1 = (int) (pd2 - pd1 - 1);
3857  char *rsa_n_exp = new char[l1 + 1];
3858  strlcpy(rsa_n_exp, pd1 + 1, l1+1);
3859  if (gDebug > 2)
3860  ::Info("TAuthenticate::DecodeRSAPublic",
3861  "got %ld bytes for rsa_n_exp", (Long_t)strlen(rsa_n_exp));
3862  // Now <hex_d>
3863  int l2 = (int) (pd3 - pd2 - 1);
3864  char *rsa_d_exp = new char[l2 + 1];
3865  strlcpy(rsa_d_exp, pd2 + 1, 13);
3866  if (gDebug > 2)
3867  ::Info("TAuthenticate::DecodeRSAPublic",
3868  "got %ld bytes for rsa_d_exp", (Long_t)strlen(rsa_d_exp));
3869 
3870  TRSA_fun::RSA_num_sget()(&rsa_n, rsa_n_exp);
3871  TRSA_fun::RSA_num_sget()(&rsa_d, rsa_d_exp);
3872 
3873  if (rsa_n_exp)
3874  if (rsa_n_exp) delete[] rsa_n_exp;
3875  if (rsa_d_exp)
3876  if (rsa_d_exp) delete[] rsa_d_exp;
3877 
3878  } else
3879  ::Info("TAuthenticate::DecodeRSAPublic","bad format for input string");
3880 #ifdef R__SSL
3881  } else {
3882  // try SSL
3883  keytype = 1;
3884 
3885  RSA *rsatmp;
3886 
3887  // Bio for exporting the pub key
3888  BIO *bpub = BIO_new(BIO_s_mem());
3889 
3890  // Write key from kbuf to BIO
3891  BIO_write(bpub,(void *)str,strlen(str));
3892 
3893  // Read pub key from BIO
3894  if (!(rsatmp = PEM_read_bio_RSAPublicKey(bpub, 0, 0, 0))) {
3895  if (gDebug > 0)
3896  ::Info("TAuthenticate::DecodeRSAPublic",
3897  "unable to read pub key from bio");
3898  } else
3899  if (rsassl)
3900  *rsassl = (char *)rsatmp;
3901  else
3902  ::Info("TAuthenticate::DecodeRSAPublic",
3903  "no space allocated for output variable");
3904  BIO_free(bpub);
3905  }
3906 #else
3907  } else {
3908  if (rsassl) { } // To avoid compiler complains
3909  if (gDebug > 0)
3910  ::Info("TAuthenticate::DecodeRSAPublic","not compiled with SSL support:"
3911  " you should not have got here!");
3912  }
3913 #endif
3914  }
3915 
3916  return keytype;
3917 }
3918 
3919 ////////////////////////////////////////////////////////////////////////////////
3920 /// Store RSA public keys from export string rsaPubExport.
3921 /// Returns type of stored key, or -1 is not recognized
3922 
3923 Int_t TAuthenticate::SetRSAPublic(const char *rsaPubExport, Int_t klen)
3924 {
3925  if (gDebug > 2)
3926  ::Info("TAuthenticate::SetRSAPublic",
3927  "enter: string length %ld bytes", (Long_t)strlen(rsaPubExport));
3928 
3929  Int_t rsakey = -1;
3930  if (!rsaPubExport)
3931  return rsakey;
3932 
3933  if (klen > 0) {
3934 
3935  // Skip spaces at beginning, if any
3936  int k0 = 0;
3937  while (rsaPubExport[k0] == 32) k0++;
3938  int k2 = klen - 1;
3939 
3940  // Parse rsaPubExport
3941  // Type 0 is in the form
3942  //
3943  // #< gt 10 exa chars >#< gt 10 exa chars >#
3944  //
3945  rsakey = 1;
3946  if (rsaPubExport[k0] == '#' && rsaPubExport[k2] == '#') {
3947  char *p0 = (char *)&rsaPubExport[k0];
3948  char *p2 = (char *)&rsaPubExport[k2];
3949  char *p1 = strchr(p0+1,'#');
3950  if (p1 > p0 && p1 < p2) {
3951  Int_t l01 = (Int_t)(p1-p0)-1;
3952  Int_t l12 = (Int_t)(p2-p1)-1;
3953  if (l01 >= kPRIMELENGTH*2 && l12 >= kPRIMELENGTH*2) {
3954  // Require exadecimal chars in between
3955  char *c = p0+1;
3956  while (c < p1 && ((*c < 58 && *c > 47) || (*c < 91 && *c > 64)))
3957  c++;
3958  if (c == p1) {
3959  c++;
3960  while (c < p2 && ((*c < 58 && *c > 47) || (*c < 91 && *c > 64)))
3961  c++;
3962  if (c == p2)
3963  rsakey = 0;
3964  }
3965  }
3966  }
3967  }
3968  if (gDebug > 3)
3969  ::Info("TAuthenticate::SetRSAPublic"," Key type: %d",rsakey);
3970  if (rsakey == 0) {
3971 
3972  // Decode input string
3973  rsa_NUMBER rsa_n, rsa_d;
3974  rsakey = TAuthenticate::DecodeRSAPublic(rsaPubExport,rsa_n,rsa_d);
3975 
3976  // Save Public key
3977  TRSA_fun::RSA_assign()(&fgRSAPubKey.n, &rsa_n);
3978  TRSA_fun::RSA_assign()(&fgRSAPubKey.e, &rsa_d);
3979 
3980  } else {
3981  rsakey = 1;
3982 #ifdef R__SSL
3983  // Now set the key locally in BF form
3984  BF_set_key(&fgBFKey, klen, (const unsigned char *)rsaPubExport);
3985 #else
3986  if (gDebug > 0)
3987  ::Info("TAuthenticate::SetRSAPublic",
3988  "not compiled with SSL support:"
3989  " you should not have got here!");
3990 #endif
3991  }
3992  }
3993 
3994  return rsakey;
3995 }
3996 
3997 ////////////////////////////////////////////////////////////////////////////////
3998 /// Receives server RSA Public key
3999 /// Sends local RSA public key encoded
4000 
4002 {
4003  // Receive server public key
4004  char serverPubKey[kMAXSECBUF];
4005  int kind, nr = 0;
4006  if ((nr = socket->Recv(serverPubKey, kMAXSECBUF, kind)) < 0)
4007  return nr;
4008  if (gDebug > 3)
4009  ::Info("TAuthenticate::SendRSAPublicKey",
4010  "received key from server %ld bytes", (Long_t)strlen(serverPubKey));
4011 
4012  // Decode it
4013  rsa_NUMBER rsa_n, rsa_d;
4014 #ifdef R__SSL
4015  char *tmprsa = 0;
4016  if (TAuthenticate::DecodeRSAPublic(serverPubKey,rsa_n,rsa_d,
4017  &tmprsa) != key) {
4018  if (tmprsa)
4019  RSA_free((RSA *)tmprsa);
4020  return -1;
4021  }
4022  RSA *RSASSLServer = (RSA *)tmprsa;
4023 #else
4024  if (TAuthenticate::DecodeRSAPublic(serverPubKey,rsa_n,rsa_d) != key)
4025  return -1;
4026 #endif
4027 
4028  // Send local public key, encodes
4029  char buftmp[kMAXSECBUF] = {0};
4030  char buflen[20] = {0};
4031  Int_t slen = fgRSAPubExport[key].len;
4032  Int_t ttmp = 0;
4033  if (key == 0) {
4034  strlcpy(buftmp,fgRSAPubExport[key].keys,slen+1);
4035  ttmp = TRSA_fun::RSA_encode()(buftmp, slen, rsa_n, rsa_d);
4036  snprintf(buflen, 20, "%d", ttmp);
4037  } else if (key == 1) {
4038 #ifdef R__SSL
4039  Int_t lcmax = RSA_size(RSASSLServer) - 11;
4040  Int_t kk = 0;
4041  Int_t ke = 0;
4042  Int_t ns = slen;
4043  while (ns > 0) {
4044  Int_t lc = (ns > lcmax) ? lcmax : ns ;
4045  if ((ttmp = RSA_public_encrypt(lc,
4046  (unsigned char *)&fgRSAPubExport[key].keys[kk],
4047  (unsigned char *)&buftmp[ke],
4048  RSASSLServer,RSA_PKCS1_PADDING)) < 0) {
4049  char errstr[120];
4050  ERR_error_string(ERR_get_error(), errstr);
4051  ::Info("TAuthenticate::SendRSAPublicKey","SSL: error: '%s' ",errstr);
4052  }
4053  kk += lc;
4054  ke += ttmp;
4055  ns -= lc;
4056  }
4057  ttmp = ke;
4058  snprintf(buflen, 20, "%d", ttmp);
4059 #else
4060  if (gDebug > 0)
4061  ::Info("TAuthenticate::SendRSAPublicKey","not compiled with SSL support:"
4062  " you should not have got here!");
4063  return -1;
4064 #endif
4065  } else {
4066  if (gDebug > 0)
4067  ::Info("TAuthenticate::SendRSAPublicKey","unknown key type (%d)",key);
4068 #ifdef R__SSL
4069  if (RSASSLServer)
4070  RSA_free(RSASSLServer);
4071 #endif
4072  return -1;
4073  }
4074 
4075  // Send length first
4076  if ((nr = socket->Send(buflen, kROOTD_ENCRYPT)) < 0)
4077  return nr;
4078  // Send Key. second ...
4079  Int_t nsen = socket->SendRaw(buftmp, ttmp);
4080  if (gDebug > 3)
4081  ::Info("TAuthenticate::SendRSAPublicKey",
4082  "local: sent %d bytes (expected: %d)", nsen,ttmp);
4083 #ifdef R__SSL
4084  if (RSASSLServer)
4085  RSA_free(RSASSLServer);
4086 #endif
4087  return nsen;
4088 }
4089 
4090 ////////////////////////////////////////////////////////////////////////////////
4091 /// Read authentication directives from $ROOTAUTHRC, $HOME/.rootauthrc or
4092 /// <Root_etc_dir>/system.rootauthrc and create related THostAuth objects.
4093 /// Files are read only if they changed since last reading
4094 /// If 'proofconf' is defined, check also file proofconf for directives
4095 
4097 {
4098  // rootauthrc family
4099  char *authrc = 0;
4100  if (gSystem->Getenv("ROOTAUTHRC") != 0) {
4101  authrc = StrDup(gSystem->Getenv("ROOTAUTHRC"));
4102  } else {
4103  if (fgReadHomeAuthrc)
4104  authrc = gSystem->ConcatFileName(gSystem->HomeDirectory(), ".rootauthrc");
4105  }
4106  if (authrc && gDebug > 2)
4107  ::Info("TAuthenticate::ReadRootAuthrc", "Checking file: %s", authrc);
4108  if (!authrc || gSystem->AccessPathName(authrc, kReadPermission)) {
4109  if (authrc && gDebug > 1)
4110  ::Info("TAuthenticate::ReadRootAuthrc",
4111  "file %s cannot be read (errno: %d)", authrc, errno);
4112  delete [] authrc;
4113  authrc = gSystem->ConcatFileName(TROOT::GetEtcDir(), "system.rootauthrc");
4114  if (gDebug > 2)
4115  ::Info("TAuthenticate::ReadRootAuthrc", "Checking system file: %s", authrc);
4116  if (gSystem->AccessPathName(authrc, kReadPermission)) {
4117  if (gDebug > 1)
4118  ::Info("TAuthenticate::ReadRootAuthrc",
4119  "file %s cannot be read (errno: %d)", authrc, errno);
4120  delete [] authrc;
4121  return 0;
4122  }
4123  }
4124 
4125  // Check if file has changed since last read
4126  TString tRootAuthrc = authrc;
4127  if (tRootAuthrc == fgRootAuthrc) {
4128  struct stat si;
4129  stat(tRootAuthrc, &si);
4130  if ((UInt_t)si.st_mtime < fgLastAuthrc.Convert()) {
4131  if (gDebug > 1)
4132  ::Info("TAuthenticate::ReadRootAuthrc",
4133  "file %s already read", authrc);
4134  delete [] authrc;
4135  return 0;
4136  }
4137  }
4138 
4139  // Save filename in static variable
4140  fgRootAuthrc = tRootAuthrc;
4141  fgLastAuthrc = TDatime();
4142 
4143  // THostAuth lists
4144  TList *authinfo = TAuthenticate::GetAuthInfo();
4145  TList *proofauthinfo = TAuthenticate::GetProofAuthInfo();
4146 
4147  // Expand File into temporary file name and open it
4148  int expand = 1;
4149  TString filetmp = "rootauthrc";
4150  FILE *ftmp = gSystem->TempFileName(filetmp);
4151  if (gDebug > 2)
4152  ::Info("TAuthenticate::ReadRootAuthrc", "got tmp file: %s open at 0x%lx",
4153  filetmp.Data(), (Long_t)ftmp);
4154  if (ftmp == 0)
4155  expand = 0; // Problems opening temporary file: ignore 'include's ...
4156 
4157  FILE *fd = 0;
4158  // If the temporary file is open, copy everything to the new file ...
4159  if (expand == 1) {
4160  TAuthenticate::FileExpand(authrc, ftmp);
4161  fd = ftmp;
4162  rewind(fd);
4163  } else {
4164  // Open file
4165  fd = fopen(authrc, "r");
4166  if (fd == 0) {
4167  if (gDebug > 2)
4168  ::Info("TAuthenticate::ReadRootAuthrc",
4169  "file %s cannot be open (errno: %d)", authrc, errno);
4170  delete [] authrc;
4171  return 0;
4172  }
4173  }
4174 
4175  // Now scan file for meaningful directives
4176  TList tmpAuthInfo;
4177  char line[kMAXPATHLEN];
4178  Bool_t cont = kFALSE;
4179  TString proofserv;
4180  while (fgets(line, sizeof(line), fd) != 0) {
4181 
4182  // Skip comment lines
4183  if (line[0] == '#')
4184  continue;
4185 
4186  // Get rid of end of line '\n', if there ...
4187  if (line[strlen(line) - 1] == '\n')
4188  line[strlen(line) - 1] = '\0';
4189 
4190  // Skip empty lines
4191  if (!line[0])
4192  continue;
4193 
4194  // Now scan
4195  const size_t tmpSize = strlen(line) + 1;
4196  char *tmp = new char[tmpSize];
4197  if (!tmp) {
4198  ::Error("TAuthenticate::ReadRootAuthrc",
4199  "could not allocate temporary buffer");
4200  return 0;
4201  }
4202  strlcpy(tmp, line, tmpSize);
4203  char *nxt = strtok(tmp," ");
4204 
4205  if (!strcmp(nxt, "proofserv") || cont) {
4206 
4207  // Building the list of data servers for proof (analyzed at the end)
4208  char *ph = 0;
4209  if (cont)
4210  ph = nxt;
4211  else
4212  ph = strtok(0," ");
4213  while (ph) {
4214  if (*ph != 92) {
4215  proofserv += TString((const char *)ph);
4216  proofserv += TString(" ");
4217  cont = kFALSE;
4218  } else {
4219  cont = kTRUE;
4220  }
4221  ph = strtok(0," ");
4222  }
4223 
4224  } else {
4225 
4226  TString hostsrv = nxt;
4227  TString host = hostsrv;
4228  TString server = "";
4229  if (hostsrv.Contains(":")) {
4230  server = hostsrv;
4231  host.Remove(host.Index(":"));
4232  server.Remove(0,server.Index(":")+1);
4233  }
4234  Int_t srvtyp = -1;
4235  if (server.Length()) {
4236  if (server == "0" || server.BeginsWith("sock"))
4237  srvtyp = TSocket::kSOCKD;
4238  else if (server == "1" || server.BeginsWith("root"))
4239  srvtyp = TSocket::kROOTD;
4240  else if (server == "2" || server.BeginsWith("proof"))
4241  srvtyp = TSocket::kPROOFD;
4242  }
4243 
4244  // Line with host info directives
4245  TString user = "*";
4246 
4247  nxt = strtok(0," ");
4248  if (!strncmp(nxt,"user",4)) {
4249  nxt = strtok(0," ");
4250  if (strncmp(nxt,"list",4) && strncmp(nxt,"method",6)) {
4251  user = TString(nxt);
4252  nxt = strtok(0," ");
4253  }
4254  }
4255 
4256  // Get related THostAuth, if exists in the tmp list,
4257  TIter next(&tmpAuthInfo);
4258  THostAuth *ha;
4259  while ((ha = (THostAuth *)next())) {
4260  if (host == ha->GetHost() && user == ha->GetUser() &&
4261  srvtyp == ha->GetServer())
4262  break;
4263  }
4264  if (!ha) {
4265  // Create a new one
4266  ha = new THostAuth(host,srvtyp,user);
4267  tmpAuthInfo.Add(ha);
4268  }
4269 
4270  if (!strncmp(nxt,"list",4)) {
4271  // list of methods for {host,usr}
4272  Int_t nm = 0, me[kMAXSEC] = {0};
4273  char *mth = strtok(0," ");
4274  while (mth) {
4275  Int_t met = -1;
4276  if (strlen(mth) > 1) {
4277  // Method passed as string: translate it to number
4278  met = GetAuthMethodIdx(mth);
4279  if (met == -1 && gDebug > 2)
4280  ::Info("TAuthenticate::ReadRootAuthrc",
4281  "unrecognized method (%s): ", mth);
4282  } else {
4283  met = atoi(mth);
4284  }
4285  if (met > -1 && met < kMAXSEC)
4286  me[nm++] = met;
4287  mth = strtok(0," ");
4288  }
4289  if (nm)
4290  ha->ReOrder(nm,me);
4291 
4292  } else if (!strncmp(nxt,"method",6)) {
4293 
4294  // details for {host,usr,method}
4295  char *mth = strtok(0," ");
4296  Int_t met = -1;
4297  if (strlen(mth) > 1) {
4298  // Method passed as string: translate it to number
4299  met = GetAuthMethodIdx(mth);
4300  if (met == -1 && gDebug > 2)
4301  ::Info("TAuthenticate::ReadRootAuthrc",
4302  "unrecognized method (%s): ", mth);
4303  } else {
4304  met = atoi(mth);
4305  }
4306  if (met > -1 && met < kMAXSEC) {
4307  const char *det = 0;
4308  nxt = strtok(0," ");
4309  if (nxt) {
4310  det = (const char *)strstr(line,nxt);
4311  }
4312  if (ha->HasMethod(met))
4313  ha->SetDetails(met,det);
4314  else
4315  ha->AddMethod(met,det);
4316  }
4317  }
4318  }
4319  if (tmp) delete [] tmp;
4320  }
4321  // Close file and remove it if temporary
4322  fclose(fd);
4323  if (expand == 1)
4324  gSystem->Unlink(filetmp);
4325  // Cleanup allocated memory
4326  delete [] authrc;
4327 
4328  // Update authinfo with new info found
4329  TAuthenticate::MergeHostAuthList(authinfo,&tmpAuthInfo);
4330 
4331  // Print those left, if requested ...
4332  if (gDebug > 2)
4334 
4335  // Now create the list of THostAuth to be sent over to
4336  // the Master/Slaves, if requested ...
4337  TList tmpproofauthinfo;
4338  if (proofserv.Length() > 0) {
4339  char *tmps = new char[proofserv.Length()+1];
4340  strlcpy(tmps,proofserv.Data(),proofserv.Length()+1);
4341  char *nxt = strtok(tmps," ");
4342  while (nxt) {
4343  TString tmp((const char *)nxt);
4344  Int_t pdd = -1;
4345  // host
4346  TString host;
4347  if ((pdd = tmp.Index(":")) == -1) {
4348  host = tmp;
4349  } else {
4350  host = tmp;
4351  host.Resize(pdd);
4352  if (!host.Length())
4353  host = "*";
4354  tmp.Remove(0,pdd+1);
4355  }
4356  // user
4357  TString user;
4358  if ((pdd = tmp.Index(":")) == -1) {
4359  user = tmp;
4360  } else {
4361  user = tmp;
4362  user.Resize(pdd);
4363  if (!user.Length())
4364  user = "*";
4365  tmp.Remove(0,pdd+1);
4366  }
4367  // method(s)
4368  TString meth;
4369  Int_t nm = 0, me[kMAXSEC] = {0}, met = -1;
4370  while (tmp.Length() > 0) {
4371  meth = tmp;
4372  if ((pdd = tmp.Index(":")) > -1)
4373  meth.Resize(pdd);
4374  if (meth.Length() > 1) {
4375  // Method passed as string: translate it to number
4376  met = GetAuthMethodIdx(meth.Data());
4377  if (met == -1 && gDebug > 2)
4378  ::Info("TAuthenticate::ReadRootAuthrc",
4379  "unrecognized method (%s): ",meth.Data());
4380  } else if (meth.Length() == 1) {
4381  met = atoi(meth.Data());
4382  if (met > -1 && met < kMAXSEC)
4383  me[nm++] = met;
4384  }
4385  if (pdd > -1)
4386  tmp.Remove(0,pdd+1);
4387  else
4388  tmp.Resize(0);
4389  }
4390 
4391  // Get related THostAuth, if exists, or create a new one
4392  THostAuth *ha = 0;
4393  THostAuth *hatmp = TAuthenticate::GetHostAuth(host,user);
4394  if (!hatmp) {
4395  ha = new THostAuth(host,user,nm,me,0);
4396  } else {
4397  // Create an empty THostAuth
4398  ha = new THostAuth(host,user);
4399  // Update with hatmp info
4400  ha->Update(hatmp);
4401  // ReOrder following new directives
4402  ha->ReOrder(nm,me);
4403  }
4404  // Add to the tmp list
4405  tmpproofauthinfo.Add(ha);
4406  // Go to next
4407  nxt = strtok(0," ");
4408  }
4409  delete [] tmps;
4410  }
4411 
4412  // Update proofauthinfo with new info found
4413  TAuthenticate::MergeHostAuthList(proofauthinfo,&tmpproofauthinfo,"P");
4414  // Print those, if requested ...
4415  if (gDebug > 2)
4416  TAuthenticate::Show("P");
4417 
4418  return authinfo->GetSize();
4419 }
4420 
4421 ////////////////////////////////////////////////////////////////////////////////
4422 /// Check if the authentication method can be attempted for the client.
4423 
4425 {
4426  Bool_t rc = kFALSE;
4427  const char sshid[3][20] = { "/.ssh/identity", "/.ssh/id_dsa", "/.ssh/id_rsa" };
4428  const char netrc[2][20] = { "/.netrc", "/.rootnetrc" };
4429  TString user;
4430 
4431  // Get user logon name
4432  UserGroup_t *pw = gSystem->GetUserInfo();
4433  if (pw) {
4434  user = TString(pw->fUser);
4435  delete pw;
4436  } else {
4437  ::Info("CheckProofAuth",
4438  "not properly logged on (getpwuid unable to find relevant info)!");
4439  out = "";
4440  return rc;
4441  }
4442 
4443  // UsrPwd
4444  if (cSec == (Int_t) TAuthenticate::kClear) {
4445  Int_t i = 0;
4446  for (; i < 2; i++) {
4447  TString infofile = TString(gSystem->HomeDirectory())+TString(netrc[i]);
4448  if (!gSystem->AccessPathName(infofile, kReadPermission))
4449  rc = kTRUE;
4450  }
4451  if (rc)
4452  out.Form("pt:0 ru:1 us:%s",user.Data());
4453  }
4454 
4455  // SRP
4456  if (cSec == (Int_t) TAuthenticate::kSRP) {
4457 #ifdef R__SRP
4458  out.Form("pt:0 ru:1 us:%s",user.Data());
4459  rc = kTRUE;
4460 #endif
4461  }
4462 
4463  // Kerberos
4464  if (cSec == (Int_t) TAuthenticate::kKrb5) {
4465 #ifdef R__KRB5
4466  out.Form("pt:0 ru:0 us:%s",user.Data());
4467  rc = kTRUE;
4468 #endif
4469  }
4470 
4471  // Globus
4472  if (cSec == (Int_t) TAuthenticate::kGlobus) {
4473 #ifdef R__GLBS
4474  TApplication *lApp = gROOT->GetApplication();
4475  if (lApp != 0 && lApp->Argc() > 9) {
4476  if (gROOT->IsProofServ()) {
4477  // Delegated Credentials
4478  Int_t ShmId = -1;
4479  if (gSystem->Getenv("ROOTSHMIDCRED"))
4480  ShmId = strtol(gSystem->Getenv("ROOTSHMIDCRED"),
4481  (char **)0, 10);
4482  if (ShmId != -1) {
4483  struct shmid_ds shm_ds;
4484  if (shmctl(ShmId, IPC_STAT, &shm_ds) == 0)
4485  rc = kTRUE;
4486  }
4487  if (rc) {
4488  // Build details .. CA dir
4489  TString Adir(gSystem->Getenv("X509_CERT_DIR"));
4490  // Usr Cert
4491  TString Ucer(gSystem->Getenv("X509_USER_CERT"));
4492  // Usr Key
4493  TString Ukey(gSystem->Getenv("X509_USER_KEY"));
4494  // Usr Dir
4495  TString Cdir = Ucer;
4496  Cdir.Resize(Cdir.Last('/')+1);
4497  // Create output
4498  out.Form("pt=0 ru:0 cd:%s cf:%s kf:%s ad:%s",
4499  Cdir.Data(),Ucer.Data(),Ukey.Data(),Adir.Data());
4500  }
4501  }
4502  }
4503 #endif
4504  }
4505 
4506  // SSH
4507  if (cSec == (Int_t) TAuthenticate::kSSH) {
4508  Int_t i = 0;
4509  for (; i < 3; i++) {
4510  TString infofile = TString(gSystem->HomeDirectory())+TString(sshid[i]);
4511  if (!gSystem->AccessPathName(infofile,kReadPermission))
4512  rc = kTRUE;
4513  }
4514  if (rc)
4515  out.Form("pt:0 ru:1 us:%s",user.Data());
4516  }
4517 
4518  // Rfio
4519  if (cSec == (Int_t) TAuthenticate::kRfio) {
4520  out.Form("pt:0 ru:0 us:%s",user.Data());
4521  rc = kTRUE;
4522  }
4523 
4524  if (gDebug > 3) {
4525  if (strlen(out) > 0)
4526  ::Info("CheckProofAuth",
4527  "meth: %d ... is available: details: %s", cSec, out.Data());
4528  else
4529  ::Info("CheckProofAuth",
4530  "meth: %d ... is NOT available", cSec);
4531  }
4532 
4533  // return
4534  return rc;
4535 }
4536 
4537 ////////////////////////////////////////////////////////////////////////////////
4538 /// Standard version of CheckSecCtx to be passed to TAuthenticate::AuthExists
4539 /// Check if User is matches the one in Ctx
4540 /// Returns: 1 if ok, 0 if not
4541 /// Deactivates Ctx is not valid
4542 
4543 Int_t StdCheckSecCtx(const char *user, TRootSecContext *ctx)
4544 {
4545  Int_t rc = 0;
4546 
4547  if (ctx->IsActive()) {
4548  if (!strcmp(user,ctx->GetUser()) &&
4549  strncmp("AFS", ctx->GetID(), 3))
4550  rc = 1;
4551  }
4552  return rc;
4553 }
4554 
4555 ////////////////////////////////////////////////////////////////////////////////
4556 /// Tool for updating fgAuthInfo or fgProofAuthInfo
4557 /// 'nin' contains list of last input information through (re)reading
4558 /// of a rootauthrc-alike file. 'nin' info has priority.
4559 /// 'std' is cleaned from inactive members.
4560 /// 'nin' members used to update existing members in 'std' are
4561 /// removed from 'nin', do that they do not leak
4562 /// opt = "P" for proofauthinfo.
4563 
4565 {
4566  // Remove inactive from the 'std'
4567  TIter nxstd(std);
4568  THostAuth *ha;
4569  while ((ha = (THostAuth *) nxstd())) {
4570  if (!ha->IsActive()) {
4571  std->Remove(ha);
4572  SafeDelete(ha);
4573  }
4574  }
4575 
4576  // Merge 'nin' info in 'std'
4577  TIter nxnew(nin);
4578  THostAuth *hanew;
4579  while ((hanew = (THostAuth *)nxnew())) {
4580  if (hanew->NumMethods()) {
4581  TString hostsrv;
4582  hostsrv.Form("%s:%d",hanew->GetHost(),hanew->GetServer());
4583  THostAuth *hastd =
4584  TAuthenticate::HasHostAuth(hostsrv,hanew->GetUser(),opt);
4585  if (hastd) {
4586  // Update with new info
4587  hastd->Update(hanew);
4588  // Flag for removal
4589  hanew->DeActivate();
4590  } else {
4591  // Add new ThostAuth to std
4592  std->Add(hanew);
4593  }
4594  } else
4595  // Flag for removal empty objects
4596  hanew->DeActivate();
4597  }
4598 
4599  // Cleanup memory before quitting
4600  nxnew.Reset();
4601  while ((hanew = (THostAuth *)nxnew())) {
4602  if (!hanew->IsActive()) {
4603  nin->Remove(hanew);
4604  SafeDelete(hanew);
4605  }
4606  }
4607 
4608 }
4609 
4610 ////////////////////////////////////////////////////////////////////////////////
4611 /// Tool for removing SecContext ctx from THostAuth listed in
4612 /// fgAuthInfo or fgProofAuthInfo
4613 
4615 {
4616  THostAuth *ha = 0;
4617 
4618  // authinfo first
4619  TIter nxai(GetAuthInfo());
4620  while ((ha = (THostAuth *)nxai())) {
4621  TIter next(ha->Established());
4622  TRootSecContext *lctx = 0;
4623  while ((lctx = (TRootSecContext *) next())) {
4624  if (lctx == ctx) {
4625  ha->Established()->Remove(ctx);
4626  break;
4627  }
4628  }
4629  }
4630 
4631  // proofauthinfo second
4632  TIter nxpa(GetProofAuthInfo());
4633  while ((ha = (THostAuth *)nxpa())) {
4634  TIter next(ha->Established());
4635  TRootSecContext *lctx = 0;
4636  while ((lctx = (TRootSecContext *) next())) {
4637  if (lctx == ctx) {
4638  ha->Established()->Remove(ctx);
4639  break;
4640  }
4641  }
4642  }
4643 
4644 }
4645 
4646 ////////////////////////////////////////////////////////////////////////////////
4647 /// Authentication related stuff setup in TProofServ.
4648 /// This is the place where the buffer send by the client / master is
4649 /// decoded. It contains also password information, if the case requires.
4650 /// Return 0 on success, -1 on failure.
4651 
4653 {
4654  static Bool_t done = kFALSE;
4655 
4656  // Only once
4657  if (done)
4658  return 0;
4659  done = kTRUE;
4660 
4661  // Localise the buffer and decode it
4662  const char *p = gSystem->Getenv("ROOTPROOFAUTHSETUP");
4663  if (!p) {
4664  if (gDebug > 2)
4665  Info("ProofAuthSetup","Buffer not found: nothing to do");
4666  return 0;
4667  }
4668  TString mbuf = TBase64::Decode(p);
4669 
4670  // Create the message
4671  TMessage *mess = new TMessage((void*)mbuf.Data(), mbuf.Length()+sizeof(UInt_t));
4672 
4673  // Extract the information
4674  TString user = "";
4675  TString passwd = "";
4676  Bool_t pwhash = kFALSE;
4677  Bool_t srppwd = kFALSE;
4678  Int_t rsakey = -1;
4679  *mess >> user >> passwd >> pwhash >> srppwd >> rsakey;
4680 
4681  // Set Globals for later use
4687  const char *h = gSystem->Getenv("ROOTHOMEAUTHRC");
4688  if (h) {
4689  Bool_t rha = (Bool_t)(strtol(h, (char **)0, 10));
4691  }
4692 
4693  // Extract the list of THostAuth
4694  TList *pha = (TList *)mess->ReadObject(TList::Class());
4695  if (!pha) {
4696  if (gDebug > 0)
4697  Info("ProofAuthSetup","List of THostAuth not found");
4698  return 0;
4699  }
4700 
4701  Bool_t master = gROOT->IsProofServ();
4702  TIter next(pha);
4703  THostAuth *ha = 0;
4704  while ((ha = (THostAuth *)next())) {
4705 
4706  // Check if there is already one compatible
4707  Int_t kExact = 0;
4708  THostAuth *haex = 0;
4709  Bool_t fromProofAI = kFALSE;
4710  if (master) {
4711  // Look first in the proof list
4712  haex = TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"P",&kExact);
4713  // If nothing found, look also in the standard list
4714  if (!haex) {
4715  haex =
4716  TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"R",&kExact);
4717  } else
4718  fromProofAI = kTRUE;
4719  } else {
4720  // For slaves look first in the standard list only
4721  haex = TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"R",&kExact);
4722  }
4723 
4724  if (haex) {
4725  // If yes, action depends on whether it matches exactly or not
4726  if (kExact == 1) {
4727  // Update info in authinfo if Slave or in proofauthinfo
4728  // if Master and the entry was already in proofauthinfo
4729  if (!master || fromProofAI) {
4730  // update this existing one with the information found in
4731  // in the new one, if needed
4732  haex->Update(ha);
4733  // Delete temporary THostAuth
4734  SafeDelete(ha);
4735  } else
4736  // Master, entry not already in proofauthinfo,
4737  // Add it to the list
4739  } else {
4740  // update this new one with the information found in
4741  // in the existing one (if needed) and ...
4742  Int_t i = 0;
4743  for (; i < haex->NumMethods(); i++) {
4744  Int_t met = haex->GetMethod(i);
4745  if (!ha->HasMethod(met))
4746  ha->AddMethod(met,haex->GetDetails(met));
4747  }
4748  if (master)
4749  // ... add the new one to the list
4751  else
4752  // We add this one to the standard list
4754  }
4755  } else {
4756  if (master)
4757  // We add this one to the list for forwarding
4759  else
4760  // We add this one to the standard list
4762  }
4763  }
4764 
4765  // We are done
4766  return 0;
4767 }
4768 
4769 ////////////////////////////////////////////////////////////////////////////////
4770 /// Setup of authetication related stuff in PROOF run after a
4771 /// successful authentication.
4772 /// Return 0 on success, -1 on failure.
4773 
4775 {
4776  // Fill some useful info
4777  TSecContext *sc = sock->GetSecContext();
4778  TString user = sc->GetUser();
4779  Int_t remoteOffSet = sc->GetOffSet();
4780 
4781  // send user name to remote host
4782  // for UsrPwd and SRP methods send also passwd, rsa encoded
4783  TMessage pubkey;
4784  TString passwd = "";
4785  Bool_t pwhash = kFALSE;
4786  Bool_t srppwd = kFALSE;
4787  Bool_t sndsrp = kFALSE;
4788 
4789  Bool_t upwd = sc->IsA("UsrPwd");
4790  Bool_t srp = sc->IsA("SRP");
4791 
4792  TPwdCtx *pwdctx = 0;
4793  if (remoteOffSet > -1 && (upwd || srp))
4794  pwdctx = (TPwdCtx *)(sc->GetContext());
4795 
4796  if (client) {
4797  if ((gEnv->GetValue("Proofd.SendSRPPwd",0)) && (remoteOffSet > -1))
4798  sndsrp = kTRUE;
4799  } else {
4800  if (srp && pwdctx) {
4801  if (strcmp(pwdctx->GetPasswd(), "") && remoteOffSet > -1)
4802  sndsrp = kTRUE;
4803  }
4804  }
4805 
4806  if ((upwd && pwdctx) || (srp && sndsrp)) {
4807  if (pwdctx) {
4808  passwd = pwdctx->GetPasswd();
4809  pwhash = pwdctx->IsPwHash();
4810  }
4811  }
4812 
4813  Int_t keytyp = ((TRootSecContext *)sc)->GetRSAKey();
4814 
4815  // Prepare buffer
4816  TMessage mess;
4817  mess << user << passwd << pwhash << srppwd << keytyp;
4818 
4819  // Add THostAuth info
4821 
4822  // Get buffer as a base 64 string
4823  char *mbuf = mess.Buffer();
4824  Int_t mlen = mess.Length();
4825  TString messb64 = TBase64::Encode(mbuf, mlen);
4826 
4827  if (gDebug > 2)
4828  ::Info("ProofAuthSetup","sending %d bytes", messb64.Length());
4829 
4830  // Send it over
4831  if (remoteOffSet > -1) {
4832  if (TAuthenticate::SecureSend(sock, 1, keytyp, messb64.Data()) == -1) {
4833  ::Error("ProofAuthSetup","problems secure-sending message buffer");
4834  return -1;
4835  }
4836  } else {
4837  // There is no encryption key: send it plain
4838  char buflen[20];
4839  snprintf(buflen,20, "%d", messb64.Length());
4840  if (sock->Send(buflen, kMESS_ANY) < 0) {
4841  ::Error("ProofAuthSetup","plain: problems sending message length");
4842  return -1;
4843  }
4844  if (sock->SendRaw(messb64.Data(), messb64.Length()) < 0) {
4845  ::Error("ProofAuthSetup","problems sending message buffer");
4846  return -1;
4847  }
4848  }
4849 
4850  // We are done
4851  return 0;
4852 }
4853 
4854 ////////////////////////////////////////////////////////////////////////////////
4855 /// Static method returning supported client protocol.
4856 
4858 {
4859  return TSocket::GetClientProtocol();
4860 }
4861 
4862 //
4863 // The code below is needed by TSlave and TProofServ for backward
4864 // compatibility.
4865 //
4866 
4867 ////////////////////////////////////////////////////////////////////////////////
4868 /// Sends the list of the relevant THostAuth objects to the master or
4869 /// to the active slaves, typically data servers external to the proof
4870 /// cluster. The list is of THostAuth to be sent is specified by
4871 /// TAuthenticate::fgProofAuthInfo after directives found in the
4872 /// .rootauthrc family files ('proofserv' key)
4873 /// Returns -1 if a problem sending THostAuth has occured, -2 in case
4874 /// of problems closing the transmission.
4875 
4877 {
4878  Int_t retval = 0, ns = 0;
4879 
4880  if (!s) {
4881  Error("SendHostAuth","invalid input: socket undefined");
4882  return -1;
4883  }
4884 
4885 
4887  THostAuth *ha;
4888  while ((ha = (THostAuth *)next())) {
4889  TString buf;
4890  ha->AsString(buf);
4891  if((ns = s->Send(buf, kPROOF_HOSTAUTH)) < 1) {
4892  retval = -1;
4893  break;
4894  }
4895  if (gDebug > 2)
4896  Info("SendHostAuth","sent %d bytes (%s)",ns,buf.Data());
4897  }
4898 
4899  // End of transmission ...
4900  if ((ns = s->Send("END", kPROOF_HOSTAUTH)) < 1)
4901  retval = -2;
4902  if (gDebug > 2)
4903  Info("SendHostAuth","sent %d bytes for closing",ns);
4904 
4905  return retval;
4906 }
4907 
4908 ////////////////////////////////////////////////////////////////////////////////
4909 /// Receive from client/master directives for authentications, create
4910 /// related THostAuth and add them to the TAuthenticate::ProofAuthInfo
4911 /// list. Opt = "M" or "m" if Master, "S" or "s" if Proof slave.
4912 /// The 'proofconf' file is read only if Master
4913 
4915 {
4916  if (!s) {
4917  Error("RecvHostAuth","invalid input: socket undefined");
4918  return -1;
4919  }
4920 
4921  // Check if Master
4922  Bool_t master = !strncasecmp(opt,"M",1) ? kTRUE : kFALSE;
4923 
4924  // First read directives from <rootauthrc>, <proofconf> and alike files
4926 
4927  // Receive buffer
4928  Int_t kind;
4929  char buf[kMAXSECBUF];
4930  Int_t nr = s->Recv(buf, kMAXSECBUF, kind);
4931  if (nr < 0 || kind != kPROOF_HOSTAUTH) {
4932  Error("RecvHostAuth", "received: kind: %d (%d bytes)", kind, nr);
4933  return -1;
4934  }
4935  if (gDebug > 2)
4936  Info("RecvHostAuth","received %d bytes (%s)",nr,buf);
4937 
4938  while (strcmp(buf, "END")) {
4939  // Clean buffer
4940  Int_t nc = (nr >= kMAXSECBUF) ? kMAXSECBUF - 1 : nr ;
4941  buf[nc] = '\0';
4942 
4943  // Create THostAuth
4944  THostAuth *ha = new THostAuth((const char *)&buf);
4945 
4946  // Check if there is already one compatible
4947  Int_t kExact = 0;
4948  THostAuth *haex = 0;
4949  Bool_t fromProofAI = kFALSE;
4950  if (master) {
4951  // Look first in the proof list
4952  haex = TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"P",&kExact);
4953  // If nothing found, look also in the standard list
4954  if (!haex) {
4955  haex =
4956  TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"R",&kExact);
4957  } else
4958  fromProofAI = kTRUE;
4959  } else {
4960  // For slaves look first in the standard list only
4961  haex = TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"R",&kExact);
4962  }
4963 
4964  if (haex) {
4965  // If yes, action depends on whether it matches exactly or not
4966  if (kExact == 1) {
4967  // Update info in authinfo if Slave or in proofauthinfo
4968  // if master and the entry was already in proofauthinfo
4969  if (!master || fromProofAI) {
4970  // update this existing one with the information found in
4971  // in the new one, if needed
4972  haex->Update(ha);
4973  // Delete temporary THostAuth
4974  SafeDelete(ha);
4975  } else
4976  // master, entry not already in proofauthinfo,
4977  // Add it to the list
4979  } else {
4980  // update this new one with the information found in
4981  // in the existing one (if needed) and ...
4982  Int_t i = 0;
4983  for (; i < haex->NumMethods(); i++) {
4984  Int_t met = haex->GetMethod(i);
4985  if (!ha->HasMethod(met))
4986  ha->AddMethod(met,haex->GetDetails(met));
4987  }
4988  if (master)
4989  // ... add the new one to the list
4991  else
4992  // We add this one to the standard list
4994  }
4995  } else {
4996  if (master)
4997  // We add this one to the list for forwarding
4999  else
5000  // We add this one to the standard list
5002  }
5003 
5004 
5005  // Get the next one
5006  nr = s->Recv(buf, kMAXSECBUF, kind);
5007  if (nr < 0 || kind != kPROOF_HOSTAUTH) {
5008  Info("RecvHostAuth","Error: received: kind: %d (%d bytes)", kind, nr);
5009  return -1;
5010  }
5011  if (gDebug > 2)
5012  Info("RecvHostAuth","received %d bytes (%s)",nr,buf);
5013  }
5014 
5015  return 0;
5016 }
5017 
5018 extern "C" {
5019 
5020 ////////////////////////////////////////////////////////////////////////////////
5021 /// Setup of authetication in PROOF run after successful opening
5022 /// of the socket. Provided for backward compatibility.
5023 /// Return 0 on success, -1 on failure.
5024 
5026  Bool_t master, TString ord, TString conf)
5027 {
5028 
5029  // Fill some useful info
5030  TSecContext *sc = sock->GetSecContext();
5031  TString user = sc->GetUser();
5032  Int_t proofdProto = sock->GetRemoteProtocol();
5033  Int_t remoteOffSet = sc->GetOffSet();
5034 
5035  // send user name to remote host
5036  // for UsrPwd and SRP methods send also passwd, rsa encoded
5037  TMessage pubkey;
5038  TString passwd = "";
5039  Bool_t pwhash = kFALSE;
5040  Bool_t srppwd = kFALSE;
5041  Bool_t sndsrp = kFALSE;
5042 
5043  Bool_t upwd = sc->IsA("UsrPwd");
5044  Bool_t srp = sc->IsA("SRP");
5045 
5046  TPwdCtx *pwdctx = 0;
5047  if (remoteOffSet > -1 && (upwd || srp))
5048  pwdctx = (TPwdCtx *)(sc->GetContext());
5049 
5050  if (!master) {
5051  if ((gEnv->GetValue("Proofd.SendSRPPwd",0)) && (remoteOffSet > -1))
5052  sndsrp = kTRUE;
5053  } else {
5054  if (srp && pwdctx) {
5055  if (strcmp(pwdctx->GetPasswd(), "") && remoteOffSet > -1)
5056  sndsrp = kTRUE;
5057  }
5058  }
5059 
5060  if ((upwd && pwdctx) || (srp && sndsrp)) {
5061 
5062  // Send offset to identify remotely the public part of RSA key
5063  if (sock->Send(remoteOffSet, kROOTD_RSAKEY) != 2*sizeof(Int_t)) {
5064  Error("OldAuthSetup", "failed to send offset in RSA key");
5065  return -1;
5066  }
5067 
5068  if (pwdctx) {
5069  passwd = pwdctx->GetPasswd();
5070  pwhash = pwdctx->IsPwHash();
5071  }
5072 
5073  Int_t keytyp = ((TRootSecContext *)sc)->GetRSAKey();
5074  if (TAuthenticate::SecureSend(sock, 1, keytyp, passwd.Data()) == -1) {
5075  if (remoteOffSet > -1)
5076  Warning("OldAuthSetup","problems secure-sending pass hash %s",
5077  "- may result in failures");
5078  // If non RSA encoding available try passwd inversion
5079  if (upwd) {
5080  for (int i = 0; i < passwd.Length(); i++) {
5081  char inv = ~passwd(i);
5082  passwd.Replace(i, 1, inv);
5083  }
5084  TMessage mess;
5085  mess << passwd;
5086  if (sock->Send(mess) < 0) {
5087  Error("OldAuthSetup", "failed to send inverted password");
5088  return -1;
5089  }
5090  }
5091  }
5092 
5093  } else {
5094 
5095  // Send notification of no offset to be sent ...
5096  if (sock->Send(-2, kROOTD_RSAKEY) != 2*sizeof(Int_t)) {
5097  Error("OldAuthSetup", "failed to send no offset notification in RSA key");
5098  return -1;
5099  }
5100  }
5101 
5102  // Send ordinal (and config) info to slave (or master)
5103  TMessage mess;
5104  mess << user << pwhash << srppwd << ord << conf;
5105 
5106  if (sock->Send(mess) < 0) {
5107  Error("OldAuthSetup", "failed to send ordinal and config info");
5108  return -1;
5109  }
5110 
5111  if (proofdProto > 6) {
5112  // Now we send authentication details to access, e.g., data servers
5113  // not in the proof cluster and to be propagated to slaves.
5114  // This is triggered by the 'proofserv <dserv1> <dserv2> ...'
5115  // line in .rootauthrc
5116  if (SendHostAuth(sock) < 0) {
5117  Error("OldAuthSetup", "failed to send HostAuth info");
5118  return -1;
5119  }
5120  }
5121 
5122  // We are done
5123  return 0;
5124 }
5125 
5126 ////////////////////////////////////////////////////////////////////////////////
5127 /// Authentication related setup in TProofServ run after successful
5128 /// startup. Provided for backward compatibility.
5129 /// Return 0 on success, -1 on failure.
5130 
5132  TString &user, TString &ord, TString &conf)
5133 {
5134  // First receive, decode and store the public part of RSA key
5135  Int_t retval, kind;
5136  if (sock->Recv(retval, kind) != 2*sizeof(Int_t)) {
5137  //other side has closed connection
5138  Info("OldProofServAuthSetup",
5139  "socket has been closed due to protocol mismatch - Exiting");
5140  return -1;
5141  }
5142 
5143  Int_t rsakey = 0;
5144  TString passwd;
5145  if (kind == kROOTD_RSAKEY) {
5146 
5147  if (retval > -1) {
5148  if (gSystem->Getenv("ROOTKEYFILE")) {
5149 
5150  TString keyfile = gSystem->Getenv("ROOTKEYFILE");
5151  keyfile += retval;
5152 
5153  FILE *fKey = 0;
5154  char pubkey[kMAXPATHLEN] = { 0 };
5155  if (!gSystem->AccessPathName(keyfile.Data(), kReadPermission)) {
5156  if ((fKey = fopen(keyfile.Data(), "r"))) {
5157  Int_t klen = fread((void *)pubkey,1,sizeof(pubkey),fKey);
5158  if (klen <= 0) {
5159  Error("OldProofServAuthSetup",
5160  "failed to read public key from '%s'", keyfile.Data());
5161  fclose(fKey);
5162  return -1;
5163  }
5164  pubkey[klen] = 0;
5165  // Set RSA key
5166  rsakey = TAuthenticate::SetRSAPublic(pubkey,klen);
5167  fclose(fKey);
5168  } else {
5169  Error("OldProofServAuthSetup", "failed to open '%s'", keyfile.Data());
5170  return -1;
5171  }
5172  }
5173  }
5174 
5175  // Receive passwd
5176  char *pwd = 0;
5177  if (TAuthenticate::SecureRecv(sock, 2, rsakey, &pwd) < 0) {
5178  Error("OldProofServAuthSetup", "failed to receive password");
5179  return -1;
5180  }
5181  passwd = pwd;
5182  delete[] pwd;
5183 
5184  } else if (retval == -1) {
5185 
5186  // Receive inverted passwd
5187  TMessage *mess;
5188  if ((sock->Recv(mess) <= 0) || !mess) {
5189  Error("OldProofServAuthSetup", "failed to receive inverted password");
5190  return -1;
5191  }
5192  (*mess) >> passwd;
5193  delete mess;
5194 
5195  for (Int_t i = 0; i < passwd.Length(); i++) {
5196  char inv = ~passwd(i);
5197  passwd.Replace(i, 1, inv);
5198  }
5199 
5200  }
5201  }
5202 
5203  // Receive final information
5204  TMessage *mess;
5205  if ((sock->Recv(mess) <= 0) || !mess) {
5206  Error("OldProofServAuthSetup", "failed to receive ordinal and config info");
5207  return -1;
5208  }
5209 
5210  // Decode it
5211  Bool_t pwhash, srppwd;
5212  if (master) {
5213  if (protocol < 4) {
5214  (*mess) >> user >> pwhash >> srppwd >> conf;
5215  ord = "0";
5216  } else {
5217  (*mess) >> user >> pwhash >> srppwd >> ord >> conf;
5218  }
5219  } else {
5220  if (protocol < 4) {
5221  Int_t iord;
5222  (*mess) >> user >> pwhash >> srppwd >> iord;
5223  ord = "0.";
5224  ord += iord;
5225  } else {
5226  (*mess) >> user >> pwhash >> srppwd >> ord >> conf;
5227  }
5228  }
5229  delete mess;
5230 
5231  // Set Globals for later use
5237  const char *h = gSystem->Getenv("ROOTHOMEAUTHRC");
5238  if (h) {
5239  Bool_t rha = (Bool_t)(strtol(h, (char **)0, 10));
5241  }
5242 
5243  // Read user or system authentication directives and
5244  // receive auth info transmitted from the client
5245  Int_t harc = master ? RecvHostAuth(sock, "M") : RecvHostAuth(sock, "S");
5246 
5247  if (harc < 0) {
5248  Error("OldProofServAuthSetup", "failed to receive HostAuth info");
5249  return -1;
5250  }
5251 
5252  // We are done
5253  return 0;
5254 }
5255 
5256 } // extern "C"
THostAuth * GetHostAuth() const
void SetDetails(Int_t level, const char *details)
Set authentication details for specified level.
Definition: THostAuth.cxx:405
const Int_t kAUTH_SSALT_MSK
Definition: AuthConst.h:32
Int_t fGid
Definition: TSystem.h:151
static Bool_t GetGlobalSRPPwd()
Static method returning the global SRP password flag.
static void SetKrb5AuthHook(Krb5Auth_t func)
Set kerberos5 authorization function.
Int_t GetServType() const
Definition: TSocket.h:147
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition: TSystem.cxx:1264
static void SetDefaultUser(const char *defaultuser)
Set default user name.
double read(const std::string &file_name)
reading
static Int_t GetRSAInit()
Static method returning the RSA initialization flag.
void AsString(TString &out) const
Return a static string with all info in a serialized form.
Definition: THostAuth.cxx:743
friend class TSocket
Definition: TAuthenticate.h:67
virtual int GetPid()
Get process id.
Definition: TSystem.cxx:711
action
Definition: ROOT.py:93
static Int_t GetClientProtocol()
Static method returning supported client protocol.
static void InitRandom()
Initialize random machine using seed from /dev/urandom (or current time if /dev/urandom not available...
static Bool_t GetAuthReUse()
Static method returning the authentication reuse settings.
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:892
static Int_t fgAuthTO
static RSA_num_sput_t RSA_num_sput()
Definition: rsafun.cxx:60
THostAuth * fHostAuth
Definition: TAuthenticate.h:74
const char * GetHostAddress() const
Returns the IP address string "%d.%d.%d.%d".
TString fPasswd
Definition: TAuthenticate.h:75
static Bool_t fgUsrPwdCrypt
#define ERR_get_error
Definition: civetweb.c:429
void Set()
Set Date/Time to current time as reported by the system.
Definition: TDatime.cxx:286
void AddForCleanup(Int_t port, Int_t proto, Int_t type)
Create a new TSecContextCleanup Internally is added to the list.
static TDatime fgExpDate
void PrintEstablished() const
Print info about established authentication vis-a-vis of this Host.
Definition: THostAuth.cxx:450
static void RemoveSecContext(TRootSecContext *ctx)
Tool for removing SecContext ctx from THostAuth listed in fgAuthInfo or fgProofAuthInfo.
Int_t GetPort() const
Definition: TSocket.h:145
R__EXTERN const char * gRootdErrStr[]
Definition: NetErrors.h:74
Int_t AuthExists(TString User, Int_t method, const char *Options, Int_t *Message, Int_t *Rflag, CheckSecCtx_t funcheck)
Check if we have a valid established sec context in memory Retrieves relevant info and negotiates wit...
TLine * line
static Bool_t fgPromptUser
Int_t(* GlobusAuth_t)(TAuthenticate *auth, TString &user, TString &det)
Definition: TAuthenticate.h:56
const char Option_t
Definition: RtypesCore.h:62
virtual void Print(Option_t *option="F") const
If opt is "F" (default) print object content.
const char * GetHostName() const
Definition: TInetAddress.h:75
TString fDetails
Definition: TAuthenticate.h:73
virtual Int_t Send(const TMessage &mess)
Send a TMessage object.
Definition: TSocket.cxx:520
static void SetGlobalUser(const char *user)
Set global user name to be used for authentication to rootd or proofd.
Int_t(* Krb5Auth_t)(TAuthenticate *auth, TString &user, TString &det, Int_t version)
Definition: TAuthenticate.h:57
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:635
#define SSL_library_init
Definition: civetweb.c:408
int GetPathInfo(const char *path, Long_t *id, Long_t *size, Long_t *flags, Long_t *modtime)
Get info about a file: id, size, flags, modification time.
Definition: TSystem.cxx:1362
static int auth_rand()
rand() implementation using /udev/random or /dev/random, if available
virtual Int_t Recv(TMessage *&mess)
Receive a TMessage object.
Definition: TSocket.cxx:818
static RSA_decode_t RSA_decode()
Definition: rsafun.cxx:59
TH1 * h
Definition: legend2.C:5
Int_t SshAuth(TString &user)
SSH client authentication code.
Int_t OldProofServAuthSetup(TSocket *sock, Bool_t master, Int_t protocol, TString &user, TString &ord, TString &conf)
Authentication related setup in TProofServ run after successful startup.
static void RemoveHostAuth(THostAuth *ha, Option_t *opt="")
Remove THostAuth instance from the list.
This class represents an Internet Protocol (IP) address.
Definition: TInetAddress.h:40
virtual const char * HomeDirectory(const char *userName=0)
Return the user&#39;s home directory.
Definition: TSystem.cxx:881
static TString Decode(const char *data)
Decode a base64 string date into a generic TString.
Definition: TBase64.cxx:140
Regular expression class.
Definition: TRegexp.h:35
const char * GetSshUser(TString user) const
Method returning the user to be used for the ssh login.
This class implements a mutex interface.
Definition: TVirtualMutex.h:34
static GlobusAuth_t GetGlobusAuthHook()
Static method returning the globus authorization hook.
TString ferr
Definition: pq2main.cxx:38
#define gROOT
Definition: TROOT.h:352
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:582
virtual UserGroup_t * GetGroupInfo(Int_t gid)
Returns all group info in the UserGroup_t structure.
Definition: TSystem.cxx:1586
double inv(double x)
For comparisons.
Definition: inv.h:58
Int_t LoadPlugin()
Load the plugin library for this handler.
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition: TSystem.cxx:1817
const char * GetDetails(Int_t level)
Return authentication details for specified level or "" if the specified level does not exist for thi...
Definition: THostAuth.cxx:373
Int_t StdCheckSecCtx(const char *, TRootSecContext *)
Standard version of CheckSecCtx to be passed to TAuthenticate::AuthExists Check if User is matches th...
Basic string class.
Definition: TString.h:137
static Bool_t fgSRPPwd
const Int_t kMAXSEC
Definition: AuthConst.h:28
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
static TList * fgProofAuthInfo
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition: TSystem.cxx:1510
Int_t GetOffSet() const
Definition: TSecContext.h:85
Int_t GetServer() const
Definition: THostAuth.h:103
static char * GetDefaultDetails(Int_t method, Int_t opt, const char *user)
Determine default authentication details for method &#39;sec&#39; and user &#39;usr&#39;.
STL namespace.
static RSA_num_sget_t RSA_num_sget()
Definition: rsafun.cxx:62
void CountFailure(Int_t level)
Count failures for &#39;method&#39;.
Definition: THostAuth.cxx:710
static const char * GetKrb5Principal()
Static method returning the principal to be used to init Krb5 tickets.
TLatex * t1
Definition: textangle.C:20
Bool_t HasMethod(Int_t level, Int_t *pos=0)
Return kTRUE if method &#39;level&#39; is in the list.
Definition: THostAuth.cxx:389
Bool_t Authenticate()
Authenticate to remote rootd or proofd server.
static SecureAuth_t fgSecAuthHook
const Int_t kAUTH_RSATY_MSK
Definition: AuthConst.h:33
Int_t fUid
Definition: TSystem.h:150
const char * GetUser() const
Definition: THostAuth.h:104
static void SetReadHomeAuthrc(Bool_t readhomeauthrc)
Set flag controlling the reading of $HOME/.rootauthrc.
Int_t ClearAuth(TString &user, TString &passwd, Bool_t &pwhash)
UsrPwd client authentication code.
void Reset()
Definition: TCollection.h:161
void DeActivate()
Definition: THostAuth.h:94
Bool_t R_ISREG(Int_t mode)
Definition: TSystem.h:129
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition: TString.h:625
Int_t Length() const
Definition: TBuffer.h:94
Int_t fMode
Definition: TSystem.h:138
void CountSuccess(Int_t level)
Count successes for &#39;method&#39;.
Definition: THostAuth.cxx:696
void Print(Option_t *option="F") const
If opt is "F" (default) print object content.
virtual TObject * ReadObject(const TClass *cl)
Read object from I/O buffer.
static TPluginHandler * fgPasswdDialog
static TString Encode(const char *data)
Transform data into a null terminated base64 string.
Definition: TBase64.cxx:113
static Int_t fgRSAKey
virtual Int_t SendRaw(const void *buffer, Int_t length, ESendRecvOptions opt=kDefault)
Send a raw buffer of specified length.
Definition: TSocket.cxx:620
Bool_t IsActive() const
Check remote OffSet and expiring Date.
#define ERR_error_string
Definition: civetweb.c:430
static Int_t ReadRootAuthrc()
Read authentication directives from $ROOTAUTHRC, $HOME/.rootauthrc or <Root_etc_dir>/system.rootauthrc and create related THostAuth objects.
static TList * fgAuthInfo
static void SetPromptUser(Bool_t promptuser)
Set global PromptUser flag.
#define SafeDelete(p)
Definition: RConfig.h:449
rsa_NUMBER n
Definition: rsadef.h:113
virtual int Unlink(const char *name)
Unlink, i.e. remove, a file.
Definition: TSystem.cxx:1345
static char * PromptPasswd(const char *prompt="Password: ")
Static method to prompt for the user&#39;s passwd to be used for authentication to rootd or proofd...
static GlobusAuth_t fgGlobusAuthHook
static RSA_assign_t RSA_assign()
Definition: rsafun.cxx:64
static rsa_KEY fgRSAPubKey
void SetServer(Int_t server)
Definition: THostAuth.h:107
static Int_t fgProcessID
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2334
virtual FILE * TempFileName(TString &base, const char *dir=0)
Create a secure temporary file by appending a unique 6 letter string to base.
Definition: TSystem.cxx:1461
void Class()
Definition: Class.C:29
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition: TSystem.cxx:441
const Int_t kMAXRSATRIES
Definition: AuthConst.h:34
ESecurity fSecurity
Definition: TAuthenticate.h:81
static Int_t DecodeRSAPublic(const char *rsapubexport, rsa_NUMBER &n, rsa_NUMBER &d, char **rsassl=0)
Store RSA public keys from export string rsaPubExport.
static rsa_KEY_export fgRSAPubExport[2]
Int_t NumMethods() const
Definition: THostAuth.h:79
char * Buffer() const
Definition: TBuffer.h:91
static double p2(double t, double a, double b, double c)
TList * Established() const
Definition: THostAuth.h:110
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1626
void Info(const char *location, const char *msgfmt,...)
TString & Append(const char *cs)
Definition: TString.h:492
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2220
std::vector< std::vector< double > > Data
Int_t ProofAuthSetup()
Authentication related stuff setup in TProofServ.
Int_t RfioAuth(TString &user)
UidGid client authentication code.
virtual UserGroup_t * GetUserInfo(Int_t uid)
Returns all user info in the UserGroup_t structure.
Definition: TSystem.cxx:1562
static Int_t fgRSAInit
static RSA_genprim_t RSA_genprim()
Definition: rsafun.cxx:56
static void SetTimeOut(Int_t to)
Set timeout (active if > 0)
static void SetGlobalSRPPwd(Bool_t srppwd)
Set global SRP passwd flag to be used for authentication to rootd or proofd.
const char * GetPasswd() const
Definition: TSecContext.h:149
static Bool_t GetPromptUser()
Static method returning the prompt user settings.
Int_t GetRemoteProtocol() const
Definition: TSocket.h:156
message
Definition: ROOT.py:94
virtual TInetAddress GetHostByName(const char *server)
Get Internet Protocol (IP) address of host.
Definition: TSystem.cxx:2232
void Error(const char *location, const char *msgfmt,...)
TAuthenticate(TSocket *sock, const char *remote, const char *proto, const char *user="")
Create authentication object.
Int_t(* CheckSecCtx_t)(const char *subj, TRootSecContext *ctx)
Definition: TAuthenticate.h:55
const Int_t kPRIMEEXP
Definition: AuthConst.h:36
const Int_t kAUTH_REUSE_MSK
Definition: AuthConst.h:30
const char * GetUser() const
Definition: TSecContext.h:88
static Int_t SecureSend(TSocket *Socket, Int_t enc, Int_t KeyType, const char *In)
Encode null terminated str using the session private key indicated by enc and sends it over the netwo...
A doubly linked list.
Definition: TList.h:47
Int_t SshError(const char *errfile)
SSH error parsing: returns 0 : no error or fatal 1 : should retry (eg &#39;connection closed by remote ho...
char * keys
Definition: rsadef.h:118
void RemoveMethod(Int_t level)
Remove method &#39;meth&#39; from the list, if there ...
Definition: THostAuth.cxx:312
static void AuthError(const char *where, Int_t error)
Print error string depending on error code.
static RSA_cmp_t RSA_cmp()
Definition: rsafun.cxx:65
Bool_t IsPwHash() const
Definition: TSecContext.h:150
TString fUser
Definition: TSystem.h:152
virtual void Close(Option_t *opt="")
Close the socket.
Definition: TSocket.cxx:388
static Krb5Auth_t fgKrb5AuthHook
TPaveText * pt
ROOT::R::TRInterface & r
Definition: Object.C:4
R__EXTERN TSystem * gSystem
Definition: TSystem.h:549
Bool_t IsA(const char *methodname)
Checks if this security context is for method named &#39;methname&#39; Case sensitive.
static void SetRSAInit(Int_t init=1)
Static method setting RSA initialization flag.
Long_t ExecPlugin(int nargs, const T &... params)
virtual Int_t GetValue(const char *name, Int_t dflt)
Returns the integer value for a resource.
Definition: TEnv.cxx:480
const Int_t kMAXSECBUF
Definition: AuthConst.h:29
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:674
static TDatime GetGlobalExpDate()
Static method returning default expiring date for new validity contexts.
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:558
Int_t(* SecureAuth_t)(TAuthenticate *auth, const char *user, const char *passwd, const char *remote, TString &det, Int_t version)
Definition: TAuthenticate.h:58
static void SetSecureAuthHook(SecureAuth_t func)
Set secure authorization function.
Int_t GenRSAKeys()
Generate a valid pair of private/public RSA keys to protect for authentication token exchange...
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2321
void SetID(const char *id)
Definition: TSecContext.h:96
unsigned int UInt_t
Definition: RtypesCore.h:42
TMarker * m
Definition: textangle.C:8
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
char * Form(const char *fmt,...)
Ssiz_t Length() const
Definition: TString.h:390
static char * PromptUser(const char *remote)
Static method to prompt for the user name to be used for authentication to rootd or proofd...
static TList * GetProofAuthInfo()
Static method returning the list with authentication directives to be sent to proof.
static Int_t SetRSAPublic(const char *rsapubexport, Int_t klen)
Store RSA public keys from export string rsaPubExport.
TLine * l
Definition: textangle.C:4
Handles synchronous and a-synchronous timer events.
Definition: TTimer.h:57
static Bool_t CheckProofAuth(Int_t cSec, TString &det)
Check if the authentication method can be attempted for the client.
virtual Int_t Exec(const char *shellcmd)
Execute a command.
Definition: TSystem.cxx:657
void AddMethod(Int_t level, const char *details=0)
Add method to the list.
Definition: THostAuth.cxx:279
static double p1(double t, double a, double b)
TRootSecContext * fSecContext
Definition: TAuthenticate.h:80
static const char * GetDefaultUser()
Static method returning the default user information.
static TDatime fgLastAuthrc
static void Show(Option_t *opt="S")
Print info about the authentication sector.
static TString fgUser
void SetHost(const char *host)
Definition: THostAuth.h:106
#define Printf
Definition: TGeoToOCC.h:18
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2513
#define R__LOCKGUARD2(mutex)
static TList * GetAuthInfo()
Static method returning the list with authentication details.
TString & Remove(Ssiz_t pos)
Definition: TString.h:616
long Long_t
Definition: RtypesCore.h:50
int Ssiz_t
Definition: RtypesCore.h:63
const char * GetID() const
Definition: TSecContext.h:82
static void SetAuthReUse(Bool_t authreuse)
Set global AuthReUse flag.
void * GetContext() const
Definition: TSecContext.h:79
TString fProtocol
Definition: TAuthenticate.h:76
#define rsa_STRLEN
Definition: rsadef.h:87
virtual Int_t GetEffectiveUid()
Returns the effective user id.
Definition: TSystem.cxx:1533
static Int_t fgLastError
void SetUser(const char *user)
Definition: THostAuth.h:108
static TString fgKrb5Principal
TRootSecContext * CreateSecContext(const char *user, const char *host, Int_t meth, Int_t offset, const char *details, const char *token, TDatime expdate=kROOTTZERO, void *ctx=0, Int_t key=-1)
Create a Security context and add it to local list Return pointer to it to be stored in TAuthenticate...
Definition: THostAuth.cxx:725
Int_t Argc() const
Definition: TApplication.h:141
#define ClassImp(name)
Definition: Rtypes.h:279
static Int_t init()
void CatchTimeOut()
Called in connection with a timer timeout.
Int_t OldSlaveAuthSetup(TSocket *sock, Bool_t master, TString ord, TString conf)
Setup of authetication in PROOF run after successful opening of the socket.
TSocket * fSocket
Definition: TAuthenticate.h:82
virtual const char * HostName()
Return the system&#39;s host name.
Definition: TSystem.cxx:307
rsa_NUMBER e
Definition: rsadef.h:114
Ssiz_t Index(const TString &str, Ssiz_t *len, Ssiz_t start=0) const
Find the first occurrence of the regexp in string and return the position, or -1 if there is no match...
Definition: TRegexp.cxx:208
char * DynamicPathName(const char *lib, Bool_t quiet=kFALSE)
Find a dynamic library called lib using the system search paths.
Definition: TSystem.cxx:1945
Bool_t GetUserPasswd(TString &user, TString &passwd, Bool_t &pwhash, Bool_t srppwd)
Try to get user name and passwd from several sources.
const char * GetHost() const
Definition: THostAuth.h:102
void SetEnvironment()
Set default authentication environment.
static void FileExpand(const char *fin, FILE *ftmp)
Expands include directives found in fexp files The expanded, temporary file, is pointed to by &#39;ftmp&#39; ...
R__EXTERN TEnv * gEnv
Definition: TEnv.h:174
static const TString & GetEtcDir()
Get the sysconfig directory in the installation. Static utility function.
Definition: TROOT.cxx:2601
static Int_t SecureRecv(TSocket *Socket, Int_t dec, Int_t KeyType, char **Out)
Receive str from sock and decode it using key indicated by key type Return number of received bytes o...
double func(double *x, double *p)
Definition: stressTF1.cxx:213
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:567
Int_t GetMethod(Int_t idx) const
Definition: THostAuth.h:80
#define SSL_load_error_strings
Definition: civetweb.c:416
static Int_t SendHostAuth(TSocket *s)
Sends the list of the relevant THostAuth objects to the master or to the active slaves, typically data servers external to the proof cluster.
void ReOrder(Int_t nmet, Int_t *fmet)
Reorder nmet methods according fmet[nmet].
Definition: THostAuth.cxx:475
virtual void DispatchOneEvent(Bool_t pendingOnly=kFALSE)
Dispatch a single event.
Definition: TSystem.cxx:433
UInt_t Convert(Bool_t toGMT=kFALSE) const
Convert fDatime from TDatime format to the standard time_t format.
Definition: TDatime.cxx:179
static Bool_t CheckHost(const char *Host, const char *host)
Check if &#39;host&#39; matches &#39;href&#39;: this means either equal or "containing" it, even with wild cards * in...
static void SetGlobalExpDate(TDatime expdate)
Set default expiring date for new validity contexts.
static TString fgDefaultUser
static void SetGlobusAuthHook(GlobusAuth_t func)
Set Globus authorization function.
static void SetGlobalPwHash(Bool_t pwhash)
Set global passwd hash flag to be used for authentication to rootd or proofd.
Bool_t IsNull() const
Definition: TString.h:387
#define name(a, b)
Definition: linkTestLib0.cpp:5
static void MergeHostAuthList(TList *Std, TList *New, Option_t *Opt="")
Tool for updating fgAuthInfo or fgProofAuthInfo &#39;nin&#39; contains list of last input information through...
static TString fgPasswd
static const char * GetRSAPubExport(Int_t key=0)
Static method returning the RSA public keys.
Bool_t IsActive() const
Definition: THostAuth.h:93
static TString fgRootAuthrc
Bool_t IsValid() const
Definition: TInetAddress.h:80
Bool_t R_ISDIR(Int_t mode)
Definition: TSystem.h:126
TSecContext * GetSecContext() const
Definition: TSocket.h:157
void SetFirst(Int_t level)
Set &#39;method&#39; to be the first used (if in the list ...).
Definition: THostAuth.cxx:585
static const char * GetGlobalUser()
Static method returning the global user.
virtual void Add(TObject *obj)
Definition: TList.h:81
const Ssiz_t kNPOS
Definition: Rtypes.h:115
static Bool_t fgPwHash
virtual Int_t GetEffectiveGid()
Returns the effective group id.
Definition: TSystem.cxx:1552
static TString fgAuthMeth[kMAXSEC]
void WriteObject(const TObject *obj)
Write object to message buffer.
Definition: TMessage.cxx:418
void Update(THostAuth *ha)
Update info with the one in ha Remaining methods, if any, get lower priority.
Definition: THostAuth.cxx:535
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
Int_t Atoi() const
Return integer value of string.
Definition: TString.cxx:1964
static RSA_encode_t RSA_encode()
Definition: rsafun.cxx:58
static Bool_t fgReadHomeAuthrc
static Int_t GetClientProtocol()
Static method returning supported client protocol.
Definition: TSocket.cxx:1494
Bool_t IsDigit() const
Returns true if all characters in string are digits (0-9) or white spaces, i.e.
Definition: TString.cxx:1806
double result[121]
static rsa_KEY fgRSAPriKey
Bool_t CheckNetrc(TString &user, TString &passwd)
Try to get user name and passwd from the ~/.rootnetrc or ~/.netrc files.
char * GetRandString(Int_t Opt, Int_t Len)
Allocates and fills a 0 terminated buffer of length len+1 with len random characters.
This class creates the ROOT Application Environment that interfaces to the windowing system eventloop...
Definition: TApplication.h:45
static RSA_genrsa_t RSA_genrsa()
Definition: rsafun.cxx:57
static void SetDefaultRSAKeyType(Int_t key)
Static method setting the default type of RSA key.
static Bool_t GetGlobalPwHash()
Static method returning the global password hash flag.
void SetLast(Int_t level)
Set &#39;method&#39; to be the last used (if in the list ...).
Definition: THostAuth.cxx:617
virtual Int_t GetSize() const
Definition: TCollection.h:95
static Bool_t fgAuthReUse
void AddFirst(Int_t level, const char *details=0)
Add new method in first position If already in the list, set as first method &#39;level&#39; with authenticat...
Definition: THostAuth.cxx:653
virtual Int_t RecvRaw(void *buffer, Int_t length, ESendRecvOptions opt=kDefault)
Receive a raw buffer of specified length bytes.
Definition: TSocket.cxx:901
const Bool_t kTRUE
Definition: Rtypes.h:91
virtual void Print(Option_t *option="") const
Print object content.
Definition: THostAuth.cxx:426
TString fRemote
Definition: TAuthenticate.h:78
const Int_t kAUTH_CRYPT_MSK
Definition: AuthConst.h:31
virtual char * ConcatFileName(const char *dir, const char *name)
Concatenate a directory and a file name. User must delete returned string.
Definition: TSystem.cxx:1044
static Int_t GetAuthMethodIdx(const char *meth)
Static method returning the method index (which can be used to find the method in GetAuthMethod())...
static THostAuth * HasHostAuth(const char *host, const char *user, Option_t *opt="R")
Checks if a THostAuth with exact match for {host,user} exists in the fgAuthInfo list If opt = "P" use...
static void SetGlobalPasswd(const char *passwd)
Set global passwd to be used for authentication to rootd or proofd.
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:904
void Resize(Ssiz_t n)
Resize the string. Truncate or add blanks as necessary.
Definition: TString.cxx:1058
static Int_t SendRSAPublicKey(TSocket *Socket, Int_t key=0)
Receives server RSA Public key Sends local RSA public key encoded.
const Int_t kPRIMELENGTH
Definition: AuthConst.h:35
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition: TDatime.h:39
static Int_t RecvHostAuth(TSocket *s, Option_t *opt)
Receive from client/master directives for authentications, create related THostAuth and add them to t...
const char * Data() const
Definition: TString.h:349
static const char * GetAuthMethod(Int_t idx)
Static method returning the method corresponding to idx.