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