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