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