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