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