Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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#include "strlcpy.h"
43#include "snprintf.h"
44
45#include "rsafun.h"
46
47#ifndef R__LYNXOS
48#include <sys/stat.h>
49#endif
50#include <errno.h>
51#include <sys/types.h>
52#include <time.h>
53#if !defined(R__WIN32) && !defined(R__MACOSX) && !defined(R__FBSD) && \
54 !defined(R__OBSD)
55#include <crypt.h>
56#endif
57#ifdef WIN32
58# include <io.h>
59#endif /* WIN32 */
60#if defined(R__LINUX) || defined(R__FBSD) || defined(R__OBSD)
61# include <unistd.h>
62#endif
63#include <stdlib.h>
64#ifndef WIN32
65# include <sys/time.h>
66#endif /* WIN32 */
67
68#if defined(R__MACOSX)
69extern "C" char *crypt(const char *, const char *);
70#endif
71
72#ifdef R__SSL
73// SSL specific headers
74# include <openssl/bio.h>
75# include <openssl/err.h>
76# include <openssl/pem.h>
77# include <openssl/rand.h>
78# include <openssl/rsa.h>
79# include <openssl/ssl.h>
80# include <openssl/blowfish.h>
81#endif
82
83struct R__rsa_KEY: rsa_KEY { R__rsa_KEY(): rsa_KEY() {} };
84struct R__rsa_KEY_export: rsa_KEY_export {};
85struct R__rsa_NUMBER: rsa_NUMBER {};
86
87#ifdef R__SSL
88 static BF_KEY fgBFKey; // Blowfish symmetric key
89#endif
90
91// Statics initialization
93TString TAuthenticate::fgAuthMeth[] = { "UsrPwd", "Unsupported", "Unsupported",
94 "Unsupported", "Unsupported", "Unsupported" };
98TDatime TAuthenticate::fgLastAuthrc; // Time of last reading of fgRootAuthrc
104Bool_t TAuthenticate::fgReadHomeAuthrc = kTRUE; // on/off search for $HOME/.rootauthrc
105TString TAuthenticate::fgRootAuthrc; // Path to last rootauthrc-like file read
106Int_t TAuthenticate::fgRSAKey = -1; // Default RSA key type to be used
109R__rsa_KEY_export R__fgRSAPubExport[2] = {{}, {}};
116Int_t TAuthenticate::fgAuthTO = -2; // Timeout value
117
118// ID of the main thread as unique identifier
120
122
123// Standard version of Sec Context match checking
124Int_t StdCheckSecCtx(const char *, TRootSecContext *);
125
126
128
129////////////////////////////////////////////////////////////////////////////////
130/// rand() implementation using /udev/random or /dev/random, if available
131
132static int auth_rand()
133{
134#ifndef WIN32
135 int frnd = open("/dev/urandom", O_RDONLY);
136 if (frnd < 0) frnd = open("/dev/random", O_RDONLY);
137 int r;
138 if (frnd >= 0) {
139 ssize_t rs = read(frnd, (void *) &r, sizeof(int));
140 close(frnd);
141 if (r < 0) r = -r;
142 if (rs == sizeof(int)) return r;
143 }
144 Printf("+++ERROR+++ : auth_rand: neither /dev/urandom nor /dev/random are available or readable!");
145 struct timeval tv;
146 if (gettimeofday(&tv,0) == 0) {
147 int t1, t2;
148 memcpy((void *)&t1, (void *)&tv.tv_sec, sizeof(int));
149 memcpy((void *)&t2, (void *)&tv.tv_usec, sizeof(int));
150 r = t1 + t2;
151 if (r < 0) r = -r;
152 return r;
153 }
154 return -1;
155#else
156 // No special random device available: use rand()
157 return rand();
158#endif
159}
160
161////////////////////////////////////////////////////////////////////////////////
162/// Create authentication object.
163
164TAuthenticate::TAuthenticate(TSocket *sock, const char *remote,
165 const char *proto, const char *user)
166{
167 if (gDebug > 2 && gAuthenticateMutex)
168 Info("Authenticate", "locking mutex (pid: %d)",gSystem->GetPid());
170
171 // In PROOF decode the buffer sent by the client, if any
172 if (gROOT->IsProofServ())
174
175 // Use the ID of the starting thread as unique identifier
176 if (fgProcessID < 0)
178
179 if (fgAuthTO == -2)
180 fgAuthTO = gEnv->GetValue("Auth.Timeout",-1);
181
182 fSocket = sock;
183 fRemote = remote;
184 fHostAuth = 0;
185 fVersion = 5; // The latest, by default
186 fSecContext = 0;
187
188 if (gDebug > 2)
189 Info("TAuthenticate", "Enter: local host: %s, user is: %s (proto: %s)",
190 gSystem->HostName(), user, proto);
191
192 // Set protocol string.
193 // Check if version should be different ...
194 char *pdd;
195 Int_t servtype = TSocket::kSOCKD;
196 if (proto && strlen(proto) > 0) {
197 char *sproto = StrDup(proto);
198 if ((pdd = strstr(sproto, ":")) != 0) {
199 int rproto = atoi(pdd + 1);
200 *pdd = '\0';
201 if (strstr(sproto, "root") != 0) {
202 if (rproto < 12 ) {
203 fVersion = 4;
204 if (rproto < 11 ) {
205 fVersion = 3;
206 if (rproto < 9 ) {
207 fVersion = 2;
208 if (rproto < 8) {
209 fVersion = 1;
210 if (rproto < 6)
211 fVersion = 0;
212 }
213 }
214 }
215 }
216 servtype = TSocket::kROOTD;
217 }
218 if (strstr(sproto, "proof") != 0) {
219 if (rproto < 11) {
220 fVersion = 4;
221 if (rproto < 10) {
222 fVersion = 3;
223 if (rproto < 8) {
224 fVersion = 2;
225 if (rproto < 7)
226 fVersion = 1;
227 }
228 }
229 }
230 servtype = TSocket::kPROOFD;
231 }
232 if (gDebug > 3)
233 Info("TAuthenticate",
234 "service: %s (remote protocol: %d): fVersion: %d", sproto,
235 rproto, fVersion);
236 }
237 fProtocol = sproto;
238 delete [] sproto;
239 }
240
241 // Check or get user name
242 fUser = "";
243 TString checkUser;
244 if (user && strlen(user) > 0) {
245 fUser = user;
246 checkUser = user;
247 } else {
249 if (u)
250 checkUser = u->fUser;
251 delete u;
252 }
253 fPasswd = "";
254 fPwHash = kFALSE;
255
256 // Type of RSA key
257 if (fgRSAKey < 0) {
258 fgRSAKey = 0; // Default key
259#ifdef R__SSL
260 // Another choice possible: check user preferences
261 if (gEnv->GetValue("RSA.KeyType",0) == 1)
262 fgRSAKey = 1;
263#endif
264 }
265 // This is the key actually used: we propose the default
266 // to the server, and behave according to its reply
268 if (gDebug > 3)
269 Info("TAuthenticate","RSA key: default type %d", fgRSAKey);
270
271 // RSA key generation (one per session)
272 if (!fgRSAInit) {
273 GenRSAKeys();
274 fgRSAInit = 1;
275 }
276
277 // Check and save the host FQDN ...
278 TString fqdn;
280 if (addr.IsValid())
281 fqdn = addr.GetHostName();
282 TString fqdnsrv;
283 fqdnsrv.Form("%s:%d",fqdn.Data(),servtype);
284
285 // Read directives from files; re-read if files have changed
287
288 if (gDebug > 3) {
289 Info("TAuthenticate",
290 "number of HostAuth Instantiations in memory: %d",
291 GetAuthInfo()->GetSize());
294 }
295
296 // Check the list of auth info for already loaded info about this host
297 fHostAuth = GetHostAuth(fqdnsrv, checkUser);
298
299 //
300 // If generic THostAuth (i.e. with wild card or user == any)
301 // make a personalized memory copy of this THostAuth
302 if (strchr(fHostAuth->GetHost(),'*') || strchr(fHostAuth->GetHost(),'*') ||
303 fHostAuth->GetServer() == -1 ) {
305 fHostAuth->SetHost(fqdn);
306 fHostAuth->SetUser(checkUser);
307 fHostAuth->SetServer(servtype);
308 }
309
310 // If a specific method has been requested via the protocol
311 // set it as first
312 Int_t sec = -1;
313 TString tmp = fProtocol;
314 tmp.ReplaceAll("root",4,"",0);
315 tmp.ReplaceAll("proof",5,"",0);
316 tmp.ReplaceAll("sock",4,"",0);
317 if (!strncmp(tmp.Data(),"up",2))
318 sec = 0;
319 else if (!strncmp(tmp.Data(),"s",1))
320 sec = 1;
321 else if (!strncmp(tmp.Data(),"k",1))
322 sec = 2;
323 else if (!strncmp(tmp.Data(),"g",1))
324 sec = 3;
325 else if (!strncmp(tmp.Data(),"h",1))
326 sec = 4;
327 else if (!strncmp(tmp.Data(),"ug",2))
328 sec = 5;
329 if (sec > -1 && sec < kMAXSEC) {
330 if (fHostAuth->HasMethod(sec)) {
331 fHostAuth->SetFirst(sec);
332 } else {
333 char *dtmp = GetDefaultDetails(sec, 1, checkUser);
334 TString det(dtmp);
335 fHostAuth->AddFirst(sec, det);
336 if (dtmp)
337 delete [] dtmp;
338 }
339 }
340
341 // This is what we have in memory
342 if (gDebug > 3) {
343 TIter next(fHostAuth->Established());
344 TRootSecContext *ctx;
345 while ((ctx = (TRootSecContext *) next()))
346 ctx->Print("0");
347 }
348}
349
350////////////////////////////////////////////////////////////////////////////////
351/// Called in connection with a timer timeout
352
354{
355 Info("CatchTimeOut", "%d sec timeout expired (protocol: %s)",
356 fgAuthTO, fgAuthMeth[fSecurity].Data());
357
358 fTimeOut = 1;
359 if (fSocket)
360 fSocket->Close("force");
361
362 return;
363}
364
365////////////////////////////////////////////////////////////////////////////////
366/// Authenticate to remote rootd or proofd server. Return kTRUE if
367/// authentication succeeded.
368
370{
371 if (gDebug > 2 && gAuthenticateMutex)
372 Info("Authenticate", "locking mutex (pid: %d)",gSystem->GetPid());
374
375 Bool_t rc = kFALSE;
376 Int_t st = -1;
377 Int_t remMeth = 0, rMth[kMAXSEC], tMth[kMAXSEC] = {0};
378 Int_t meth = 0;
379 char noSupport[80] = { 0 };
380 char triedMeth[80] = { 0 };
381 Int_t ntry = 0;
382
383 TString user, passwd;
384 Bool_t pwhash;
385
386 if (gDebug > 2)
387 Info("Authenticate", "enter: fUser: %s", fUser.Data());
388
389 //
390 // Setup timeout timer, if required
391 TTimer *alarm = 0;
392 if (fgAuthTO > 0) {
393 alarm = new TTimer(0, kFALSE);
394 alarm->SetInterruptSyscalls();
395 // The method CatchTimeOut will be called at timeout
396 alarm->Connect("Timeout()", "TAuthenticate", this, "CatchTimeOut()");
397 }
398
399negotia:
400 st = -1;
401 tMth[meth] = 1;
402 ntry++;
403 if (gDebug > 2)
404 Info("Authenticate", "try #: %d", ntry);
405
406 user = "";
407 passwd = "";
408 pwhash = kFALSE;
409
410 // Security level from the list (if not in cleanup mode ...)
413 if (gDebug > 2)
414 Info("Authenticate",
415 "trying authentication: method:%d, default details:%s",
417
418 // Keep track of tried methods in a list
419 if (triedMeth[0] != '\0')
420 (void) strlcat(triedMeth, " ", sizeof(triedMeth) - 1);
421
422 (void) strlcat(triedMeth, fgAuthMeth[fSecurity].Data(), sizeof(triedMeth) - 1);
423
424 // Set environments
426
427 st = -1;
428
429 //
430 // Reset timeout variables and start timer
431 fTimeOut = 0;
432 if (fgAuthTO > 0 && alarm) {
433 alarm->Start(fgAuthTO*1000, kTRUE);
434 }
435
436 // Auth calls depend of fSec
437 if (fSecurity == kClear) {
438
439 rc = kFALSE;
440
441 // UsrPwd Authentication
442 user = fgDefaultUser;
443 if (user != "")
444 CheckNetrc(user, passwd, pwhash, kFALSE);
445 if (passwd == "") {
446 if (fgPromptUser) {
447 char *u = PromptUser(fRemote);
448 user = u;
449 delete[] u;
450 }
451 rc = GetUserPasswd(user, passwd, pwhash, kFALSE);
452 }
453 fUser = user;
454 fPasswd = passwd;
455
456 if (!rc) {
457
458 if (fUser != "root")
459 st = ClearAuth(user, passwd, pwhash);
460 } else {
461 Error("Authenticate",
462 "unable to get user name for UsrPwd authentication");
463 }
464
465 }
466
467 // Stop timer
468 if (alarm) alarm->Stop();
469
470 // Flag timeout condition
471 st = (fTimeOut > 0) ? -3 : st;
472
473 //
474 // Analyse the result now ...
475 // Type of action after the analysis:
476 // 0 = return, 1 = negotiation, 2 = send kROOTD_BYE + 3,
477 // 3 = print failure and return
478 Int_t action = 0;
479 Int_t nmet = fHostAuth->NumMethods();
480 Int_t remloc = nmet - ntry;
481 if (gDebug > 0)
482 Info("Authenticate","remloc: %d, ntry: %d, meth: %d, fSecurity: %d",
483 remloc, ntry, meth, fSecurity);
484 Int_t kind, stat;
485 switch (st) {
486
487 case 1:
488 //
489 // Success
491 if (gDebug > 2)
493 if (fSecContext->IsActive())
496 rc = kTRUE;
497 break;
498
499 case 0:
500 //
501 // Failure
503 if (fVersion < 2) {
504 //
505 // Negotiation not supported by old daemons ...
506 if (gDebug > 2)
507 Info("Authenticate",
508 "negotiation not supported remotely: try next method, if any");
509 if (meth < nmet - 1) {
510 meth++;
511 action = 1;
512 } else {
513 action = 2;
514 }
515 rc = kFALSE;
516 break;
517 }
518 //
519 // Attempt negotiation ...
520 if (fSocket->Recv(stat, kind) < 0) {
521 action = 0;
522 rc = kFALSE;
523 }
524 if (gDebug > 2)
525 Info("Authenticate",
526 "after failed attempt: kind= %d, stat= %d", kind, stat);
527 if (kind == kROOTD_ERR) {
528 action = 2;
529 rc = kFALSE;
530 } else if (kind == kROOTD_NEGOTIA) {
531 if (stat > 0) {
532 int len = 3 * stat;
533 char *answer = new char[len];
534 int nrec = fSocket->Recv(answer, len, kind); // returns user
535 if (nrec < 0) {
536 delete[] answer; // delete buffer while it exit switch() scope
537 action = 0;
538 rc = kFALSE;
539 break;
540 }
541 if (kind != kMESS_STRING)
542 Warning("Authenticate",
543 "strings with accepted methods not received (%d:%d)",
544 kind, nrec);
545 remMeth =
546 sscanf(answer, "%d %d %d %d %d %d", &rMth[0], &rMth[1],
547 &rMth[2], &rMth[3], &rMth[4], &rMth[5]);
548 if (gDebug > 0 && remloc > 0)
549 Info("Authenticate",
550 "remotely allowed methods not yet tried: %s",
551 answer);
552 delete[] answer;
553 } else if (stat == 0) {
554 Info("Authenticate",
555 "no more methods accepted remotely to be tried");
556 action = 3;
557 rc = kFALSE;
558 break;
559 }
560 // If no more local methods, return
561 if (remloc < 1) {
562 action = 2;
563 rc = kFALSE;
564 break;
565 }
566 // Look if a non-tried method matches
567 int i, j;
568 std::string available{};
569 Bool_t methfound = kFALSE;
570 for (i = 0; i < remMeth; i++) {
571 for (j = 0; j < nmet; j++) {
572 if (fHostAuth->GetMethod(j) == rMth[i] && tMth[j] == 0) {
573 meth = j;
574 action = 1;
575 methfound = kTRUE;
576 break;
577 }
578 if (i == 0)
579 available += " " + std::to_string(fHostAuth->GetMethod(j));
580 }
581 if (methfound) break;
582 }
583 if (methfound) break;
584 //
585 // No method left to be tried: notify and exit
586 if (gDebug > 0)
587 Warning("Authenticate", "no match with those locally available: %s", available.c_str());
588 action = 2;
589 rc = kFALSE;
590 break;
591 } else { // unknown message code at this stage
592 action = 3;
593 rc = kFALSE;
594 break;
595 }
596 break;
597
598 case -1:
599 //
600 // Method not supported
602 if (gDebug > 2)
603 Info("Authenticate",
604 "method not even started: insufficient or wrong info: %s",
605 "try with next method, if any");
607 nmet--;
608 if (nmet > 0) {
609 action = 1;
610 } else
611 action = 2;
612
613 break;
614
615 case -2:
616 //
617 // Remote host does not accepts connections from local host
619 if (fVersion <= 2)
620 if (gDebug > 2)
621 Warning("Authenticate",
622 "status code -2 not expected from old daemons");
623 rc = kFALSE;
624 break;
625
626 case -3:
627 //
628 // Timeout: we set the method as last one, should the caller
629 // decide to retry, if it will attempt first something else.
630 // (We can not retry directly, because the server will not be
631 // synchronized ...)
633 if (gDebug > 2)
634 Info("Authenticate", "got a timeout");
636 if (meth < nmet - 1) {
637 fTimeOut = 2;
638 } else
639 fTimeOut = 1;
640 rc = kFALSE;
641 break;
642
643 default:
645 if (gDebug > 2)
646 Info("Authenticate", "unknown status code: %d - assume failure",st);
647 rc = kFALSE;
648 action = 0;
649 break;
650 }
651
652 switch (action) {
653 case 1:
654 goto negotia;
655 // No break but we go away anyhow
656 case 2:
657 fSocket->Send("0", kROOTD_BYE);
658 // fallthrough
659 case 3:
660 if (strlen(noSupport) > 0)
661 Info("Authenticate", "attempted methods %s are not supported"
662 " by remote server version", noSupport);
663 Info("Authenticate",
664 "failure: list of attempted methods: %s", triedMeth);
665 AuthError("Authenticate",-1);
666 rc = kFALSE;
667 break;
668 default:
669 break;
670 }
671
672 // Cleanup timer
673 SafeDelete(alarm);
674
675 return rc;
676
677}
678
679////////////////////////////////////////////////////////////////////////////////
680/// Set default authentication environment. The values are inferred
681/// from fSecurity and fDetails.
682
684{
686
687 if (gDebug > 2)
688 Info("SetEnvironment",
689 "setting environment: fSecurity:%d, fDetails:%s", fSecurity,
690 fDetails.Data());
691
692 // Defaults
696
697 // Decode fDetails, is non empty ...
698 if (fDetails != "") {
699 char usdef[kMAXPATHLEN] = { 0 };
700 char pt[5] = { 0 }, ru[5] = { 0 };
701 Int_t hh = 0, mm = 0;
702 char us[kMAXPATHLEN] = {0}, cp[kMAXPATHLEN] = {0};
703 const char *ptr;
704
705 TString usrPromptDef = TString(GetAuthMethod(fSecurity)) + ".LoginPrompt";
706 if ((ptr = strstr(fDetails, "pt:")) != 0) {
707 sscanf(ptr + 3, "%4s %8191s", pt, usdef);
708 } else {
709 if (!strncasecmp(gEnv->GetValue(usrPromptDef,""),"no",2) ||
710 !strncmp(gEnv->GetValue(usrPromptDef,""),"0",1))
711 strncpy(pt,"0",2);
712 else
713 strncpy(pt,"1",2);
714 }
715 TString usrReUseDef = TString(GetAuthMethod(fSecurity)) + ".ReUse";
716 if ((ptr = strstr(fDetails, "ru:")) != 0) {
717 sscanf(ptr + 3, "%4s %8191s", ru, usdef);
718 } else {
719 if (!strncasecmp(gEnv->GetValue(usrReUseDef,""),"no",2) ||
720 !strncmp(gEnv->GetValue(usrReUseDef,""),"0",1))
721 strncpy(ru,"0",2);
722 else
723 strncpy(ru,"1",2);
724 }
725 TString usrValidDef = TString(GetAuthMethod(fSecurity)) + ".Valid";
726 TString hours(gEnv->GetValue(usrValidDef,"24:00"));
727 Int_t pd = 0;
728 if ((pd = hours.Index(":")) > -1) {
729 TString minutes = hours;
730 hours.Resize(pd);
731 minutes.Replace(0,pd+1,"");
732 hh = atoi(hours.Data());
733 mm = atoi(minutes.Data());
734 } else {
735 hh = atoi(hours.Data());
736 mm = 0;
737 }
738
739 // Now action depends on method ...
740 if (fSecurity == kClear) {
741 if ((ptr = strstr(fDetails, "us:")) != 0)
742 sscanf(ptr + 3, "%8191s %8191s", us, usdef);
743 if ((ptr = strstr(fDetails, "cp:")) != 0)
744 sscanf(ptr + 3, "%8191s %8191s", cp, usdef);
745 if (gDebug > 2)
746 Info("SetEnvironment", "details:%s, pt:%s, ru:%s, us:%s cp:%s",
747 fDetails.Data(), pt, ru, us, cp);
748 } else {
749 if ((ptr = strstr(fDetails, "us:")) != 0)
750 sscanf(ptr + 3, "%8191s %8191s", us, usdef);
751 if (gDebug > 2)
752 Info("SetEnvironment", "details:%s, pt:%s, ru:%s, us:%s",
753 fDetails.Data(), pt, ru, us);
754 }
755
756 // Set Prompt flag
757 if (!strncasecmp(pt, "yes",3) || !strncmp(pt, "1", 1))
759
760 // Set ReUse flag
761 if (!gROOT->IsProofServ()) {
763 if (!strncasecmp(ru, "no",2) || !strncmp(ru, "0",1))
765 }
766
767 // Set Expiring date
768 fgExpDate = TDatime();
769 fgExpDate.Set(fgExpDate.Convert() + hh*3600 + mm*60);
770
771 // UnSet Crypt flag for UsrPwd, if requested
772 if (fSecurity == kClear) {
774 if (!strncmp(cp, "no", 2) || !strncmp(cp, "0", 1))
776 }
777 // Build UserDefaults
778 usdef[0] = '\0';
779 // give highest priority to command-line specification
780 if (fUser == "") {
781 if (strlen(us) > 0) snprintf(usdef, kMAXPATHLEN, "%s", us);
782 } else {
783 snprintf(usdef, kMAXPATHLEN, "%s", fUser.Data());
784 }
785
786 if (strlen(usdef) > 0) {
787 fgDefaultUser = usdef;
788 } else {
789 if (fgUser != "") {
791 } else {
793 if (u)
794 fgDefaultUser = u->fUser;
795 delete u;
796 }
797 }
798 if (fgDefaultUser == "anonymous" || fgDefaultUser == "rootd" ||
799 fgUser != "" || fUser != "") {
800 // when set by user don't prompt for it anymore
802 }
803
804 if (gDebug > 2)
805 Info("SetEnvironment", "usdef:%s", fgDefaultUser.Data());
806 }
807}
808
809////////////////////////////////////////////////////////////////////////////////
810/// Try to get user name and passwd from several sources.
811
813 Bool_t &pwhash, Bool_t srppwd)
814{
815 if (srppwd) {
816 Error("GetUserPasswd", "SRP no longer supported by ROOT");
817 return 1;
818 }
819
820 if (gDebug > 3)
821 Info("GetUserPasswd", "Enter: User: '%s' Hash:%d SRP:%d",
822 user.Data(),(Int_t)pwhash,(Int_t)false);
823
824 // Get user and passwd set via static functions SetUser and SetPasswd.
825 if (user == "" && fgUser != "")
826 user = fgUser;
827
828 if (fgUser != "" && user == fgUser) {
829 if (passwd == "" && fgPasswd != "") {
831 pwhash = fgPwHash;
832 }
833 }
834
835 if (gDebug > 3)
836 Info("GetUserPasswd", "In memory: User: '%s' Hash:%d",
837 user.Data(),(Int_t)pwhash);
838
839 // Check system info for user if still not defined
840 if (user == "") {
842 if (u)
843 user = u->fUser;
844 delete u;
845 if (gDebug > 3)
846 Info("GetUserPasswd", "In memory: User: '%s' Hash:%d",
847 user.Data(),(Int_t)pwhash);
848 }
849
850 // Check ~/.rootnetrc and ~/.netrc files if user was not set via
851 // the static SetUser() method.
852 if (user == "" || passwd == "") {
853 if (gDebug > 3)
854 Info("GetUserPasswd", "Checking .netrc family ...");
855 CheckNetrc(user, passwd, pwhash, /* srppwd */ false);
856 }
857 if (gDebug > 3)
858 Info("GetUserPasswd", "From .netrc family: User: '%s' Hash:%d",
859 user.Data(),(Int_t)pwhash);
860
861 // If user also not set via ~/.rootnetrc or ~/.netrc ask user.
862 if (user == "") {
863 char *p = PromptUser(fRemote);
864 user = p;
865 delete [] p;
866 if (user == "") {
867 Error("GetUserPasswd", "user name not set");
868 return 1;
869 }
870 }
871
872 return 0;
873}
874
875////////////////////////////////////////////////////////////////////////////////
876/// Try to get user name and passwd from the ~/.rootnetrc or
877/// ~/.netrc files. For more info see the version with 4 arguments.
878/// This version is maintained for backward compatability reasons.
879
881{
882 Bool_t hash = false;
883 return CheckNetrc(user, passwd, hash, /* srppwd */ false);
884}
885
886////////////////////////////////////////////////////////////////////////////////
887/// Try to get user name and passwd from the ~/.rootnetrc or
888/// ~/.netrc files. First ~/.rootnetrc is tried, after that ~/.netrc.
889/// These files will only be used when their access masks are 0600.
890/// Returns kTRUE if user and passwd were found for the machine
891/// specified in the URL. If kFALSE, user and passwd are "".
892/// The boolean pwhash is set to kTRUE if the returned passwd is to
893/// be understood as password hash, i.e. if the 'password-hash' keyword
894/// is found in the 'machine' lines; not implemented for 'secure'
895/// and the .netrc file.
896/// The format of these files are:
897///
898/// # this is a comment line
899/// machine <machine fqdn> login <user> password <passwd>
900/// machine <machine fqdn> login <user> password-hash <passwd>
901///
902/// and in addition ~/.rootnetrc also supports:
903///
904/// secure <machine fqdn> login <user> password <passwd>
905///
906/// <machine fqdn> may be a domain name or contain the wild card '*'.
907///
908/// for the secure protocols. All lines must start in the first column.
909
911 Bool_t &pwhash, Bool_t srppwd)
912{
913 if (srppwd) {
914 Error("CheckNetrc", "SRP no longer supported by ROOT");
915 return 1;
916 }
917
918 Bool_t result = kFALSE;
920 TString remote = fRemote;
921
922 passwd = "";
923 pwhash = kFALSE;
924
925 char *net =
926 gSystem->ConcatFileName(gSystem->HomeDirectory(), ".rootnetrc");
927
928 // Determine FQDN of the host ...
930 if (addr.IsValid())
931 remote = addr.GetHostName();
932
933again:
934 // Only use file when its access rights are 0600
935 FileStat_t buf;
936 if (gSystem->GetPathInfo(net, buf) == 0) {
937#ifdef WIN32
938 // Since Win32 does not have proper protections use file always
939 bool mode0600 = true;
940#else
941 bool mode0600 = (buf.fMode & 0777) == (kS_IRUSR | kS_IWUSR);
942#endif
943 if (R_ISREG(buf.fMode) && !R_ISDIR(buf.fMode) && mode0600) {
944 FILE *fd = fopen(net, "r");
945 char line[256];
946 while (fgets(line, sizeof(line), fd) != 0) {
947 if (line[0] == '#')
948 continue;
949 char word[6][64];
950 int nword = sscanf(line, "%63s %63s %63s %63s %63s %63s",
951 word[0], word[1], word[2], word[3], word[4], word[5]);
952 if (nword != 6)
953 continue;
954 if (strcmp(word[0], "machine"))
955 continue;
956 if (strcmp(word[2], "login"))
957 continue;
958 if (strcmp(word[4], "password") && strcmp(word[4], "password-hash"))
959 continue;
960
961 // Treat the host name found in file as a regular expression
962 // with '*' as a wild card
963 TString href(word[1]);
964 href.ReplaceAll("*",".*");
965 TRegexp rg(href);
966 if (remote.Index(rg) != kNPOS) {
967 if (user == "") {
968 user = word[3];
969 passwd = word[5];
970 if (!strcmp(word[4], "password-hash"))
971 pwhash = kTRUE;
972 result = kTRUE;
973 break;
974 } else {
975 if (!strcmp(word[3], user.Data())) {
976 passwd = word[5];
977 if (!strcmp(word[4], "password-hash"))
978 pwhash = kTRUE;
979 result = kTRUE;
980 break;
981 }
982 }
983 }
984 }
985 fclose(fd);
986 } else
987 Warning("CheckNetrc",
988 "file %s exists but has not 0600 permission", net);
989 }
990 delete [] net;
991
992 if (first && !result) {
993 net = gSystem->ConcatFileName(gSystem->HomeDirectory(), ".netrc");
994 first = kFALSE;
995 goto again;
996 }
997
998 return result;
999 }
1000
1001////////////////////////////////////////////////////////////////////////////////
1002/// Static method returning the global user.
1003
1005{
1006 return fgUser;
1007}
1008
1009////////////////////////////////////////////////////////////////////////////////
1010/// Static method returning the global password hash flag.
1011
1013{
1014 return fgPwHash;
1015}
1016
1017////////////////////////////////////////////////////////////////////////////////
1018/// Static method returning the global SRP password flag.
1019
1021{
1022 return false;
1023}
1024
1025////////////////////////////////////////////////////////////////////////////////
1026/// Static method returning default expiring date for new validity contexts
1027
1029{
1030 return fgExpDate;
1031}
1032
1033////////////////////////////////////////////////////////////////////////////////
1034/// Static method returning the default user information.
1035
1037{
1038 return fgDefaultUser;
1039}
1040
1041////////////////////////////////////////////////////////////////////////////////
1042/// Static method returning the principal to be used to init Krb5 tickets.
1043
1045{
1046 ::Error("Krb5Auth", "Kerberos5 is no longer supported by ROOT");
1047 return nullptr;
1048}
1049
1050////////////////////////////////////////////////////////////////////////////////
1051/// Static method returning the authentication reuse settings.
1052
1054{
1055 return fgAuthReUse;
1056}
1057
1058////////////////////////////////////////////////////////////////////////////////
1059/// Static method returning the prompt user settings.
1060
1062{
1063 return fgPromptUser;
1064}
1065
1066////////////////////////////////////////////////////////////////////////////////
1067/// Static method returning the method corresponding to idx.
1068
1070{
1072
1073 if (idx < 0 || idx > kMAXSEC-1) {
1074 ::Error("Authenticate::GetAuthMethod", "idx out of bounds (%d)", idx);
1075 idx = 0;
1076 }
1077 return fgAuthMeth[idx];
1078}
1079
1080////////////////////////////////////////////////////////////////////////////////
1081/// Static method returning the method index (which can be used to find
1082/// the method in GetAuthMethod()). Returns -1 in case meth is not found.
1083
1085{
1087
1088 if (meth && meth[0]) {
1089 for (Int_t i = 0; i < kMAXSEC; i++) {
1090 if (!fgAuthMeth[i].CompareTo(meth, TString::kIgnoreCase))
1091 return i;
1092 }
1093 }
1094
1095 return -1;
1096}
1097
1098////////////////////////////////////////////////////////////////////////////////
1099/// Static method to prompt for the user name to be used for authentication
1100/// to rootd or proofd. User is asked to type user name.
1101/// Returns user name (which must be deleted by caller) or 0.
1102/// If non-interactive run (eg ProofServ) returns default user.
1103
1104char *TAuthenticate::PromptUser(const char *remote)
1105{
1107
1108 const char *user;
1109 if (fgDefaultUser != "")
1110 user = fgDefaultUser;
1111 else
1112 user = gSystem->Getenv("USER");
1113#ifdef R__WIN32
1114 if (!user)
1115 user = gSystem->Getenv("USERNAME");
1116#endif
1117 if (isatty(0) == 0 || isatty(1) == 0) {
1118 ::Warning("TAuthenticate::PromptUser",
1119 "not tty: cannot prompt for user, returning default");
1120 if (strlen(user))
1121 return StrDup(user);
1122 else
1123 return StrDup("None");
1124 }
1125
1126 const char *usrIn = Getline(Form("Name (%s:%s): ", remote, user));
1127 if (usrIn[0]) {
1128 TString usr(usrIn);
1129 usr.Remove(usr.Length() - 1); // get rid of \n
1130 if (!usr.IsNull())
1131 return StrDup(usr);
1132 else
1133 return StrDup(user);
1134 }
1135 return 0;
1136}
1137
1138////////////////////////////////////////////////////////////////////////////////
1139/// Static method to prompt for the user's passwd to be used for
1140/// authentication to rootd or proofd. Uses non-echoing command line
1141/// to get passwd. Returns passwd (which must de deleted by caller) or 0.
1142/// If non-interactive run (eg ProofServ) returns -1
1143
1144char *TAuthenticate::PromptPasswd(const char *prompt)
1145{
1146 if (isatty(0) == 0 || isatty(1) == 0) {
1147 ::Warning("TAuthenticate::PromptPasswd",
1148 "not tty: cannot prompt for passwd, returning -1");
1149 static char noint[4] = {"-1"};
1150 return StrDup(noint);
1151 }
1152
1153 char buf[128];
1154 const char *pw = buf;
1155 // Get the plugin for the passwd dialog box, if needed
1156 if (!gROOT->IsBatch() && (fgPasswdDialog == (TPluginHandler *)(-1)) &&
1157 gEnv->GetValue("Auth.UsePasswdDialogBox", 1) == 1) {
1158 if ((fgPasswdDialog =
1159 gROOT->GetPluginManager()->FindHandler("TGPasswdDialog"))) {
1160 if (fgPasswdDialog->LoadPlugin() == -1) {
1161 fgPasswdDialog = 0;
1162 ::Warning("TAuthenticate",
1163 "could not load plugin for the password dialog box");
1164 }
1165 }
1166 }
1167 if (fgPasswdDialog && (fgPasswdDialog != (TPluginHandler *)(-1))) {
1168
1169 // Use graphic dialog
1170 fgPasswdDialog->ExecPlugin(3, prompt, buf, 128);
1171
1172 // Wait until the user is done
1173 while (gROOT->IsInterrupted())
1175
1176 } else {
1177 Gl_config("noecho", 1);
1178 pw = Getline(prompt);
1179 Gl_config("noecho", 0);
1180 }
1181
1182 // Final checks
1183 if (pw[0]) {
1184 TString spw(pw);
1185 if (spw.EndsWith("\n"))
1186 spw.Remove(spw.Length() - 1); // get rid of \n
1187 char *rpw = StrDup(spw);
1188 return rpw;
1189 }
1190 return 0;
1191}
1192
1193////////////////////////////////////////////////////////////////////////////////
1194/// Static method returning the globus authorization hook (no longer supported)
1195
1197{
1198 return nullptr;
1199}
1200
1201////////////////////////////////////////////////////////////////////////////////
1202/// Static method returning the RSA public keys.
1203
1205{
1206 key = (key >= 0 && key <= 1) ? key : 0;
1207 return fgRSAPubExport[key].keys;
1208}
1209
1210////////////////////////////////////////////////////////////////////////////////
1211/// Static method returning the RSA initialization flag.
1212
1214{
1215 return fgRSAInit;
1216}
1217
1218////////////////////////////////////////////////////////////////////////////////
1219/// Static method setting the default type of RSA key.
1220
1222{
1223 if (key >= 0 && key <= 1)
1224 fgRSAKey = key;
1225}
1226
1227////////////////////////////////////////////////////////////////////////////////
1228/// Static method setting RSA initialization flag.
1229
1231{
1232 fgRSAInit = init;
1233}
1234
1235////////////////////////////////////////////////////////////////////////////////
1236/// Static method returning the list with authentication details.
1237
1239{
1241
1242 if (!fgAuthInfo)
1243 fgAuthInfo = new TList;
1244 return fgAuthInfo;
1245}
1246
1247////////////////////////////////////////////////////////////////////////////////
1248/// Static method returning the list with authentication directives
1249/// to be sent to proof.
1250
1252{
1254
1255 if (!fgProofAuthInfo)
1256 fgProofAuthInfo = new TList;
1257 return fgProofAuthInfo;
1258}
1259
1260////////////////////////////////////////////////////////////////////////////////
1261/// Print error string depending on error code.
1262
1263void TAuthenticate::AuthError(const char *where, Int_t err)
1264{
1266
1267 // Make sure it is in range
1268 err = (err < kErrError) ? ((err > -1) ? err : -1) : kErrError;
1269
1270 Int_t erc = err;
1271 Bool_t forceprint = kFALSE;
1272 TString lasterr = "";
1273 if (err == -1) {
1274 forceprint = kTRUE;
1275 erc = fgLastError;
1276 lasterr = "(last error only; re-run with gDebug > 0 for more details)";
1277 }
1278
1279 if (erc > -1)
1280 if (gDebug > 0 || forceprint) {
1281 if (gRootdErrStr[erc])
1282 ::Error(Form("TAuthenticate::%s", where), "%s %s",
1283 gRootdErrStr[erc], lasterr.Data());
1284 else
1285 ::Error(Form("TAuthenticate::%s", where),
1286 "unknown error code: server must be running a newer ROOT version %s",
1287 lasterr.Data());
1288 }
1289
1290 // Update last error code
1291 fgLastError = err;
1292}
1293
1294////////////////////////////////////////////////////////////////////////////////
1295/// Set global user name to be used for authentication to rootd or proofd.
1296
1297void TAuthenticate::SetGlobalUser(const char *user)
1298{
1300
1301 if (fgUser != "")
1302 fgUser = "";
1303
1304 if (user && user[0])
1305 fgUser = user;
1306}
1307
1308////////////////////////////////////////////////////////////////////////////////
1309/// Set global passwd to be used for authentication to rootd or proofd.
1310
1312{
1314
1315 if (fgPasswd != "")
1316 fgPasswd = "";
1317
1318 if (passwd && passwd[0])
1319 fgPasswd = passwd;
1320}
1321
1322////////////////////////////////////////////////////////////////////////////////
1323/// Set global passwd hash flag to be used for authentication to rootd or proofd.
1324
1326{
1327 fgPwHash = pwhash;
1328}
1329
1330////////////////////////////////////////////////////////////////////////////////
1331/// Set global SRP passwd flag to be used for authentication to rootd or proofd.
1332
1334{
1335 ::Error("SetGlobalSRPPwd", "SRP no longer supported by ROOT");
1336}
1337
1338////////////////////////////////////////////////////////////////////////////////
1339/// Set flag controlling the reading of $HOME/.rootauthrc.
1340/// In PROOF the administrator may want to switch off private settings.
1341/// Always true, may only be set false via option to proofd.
1342
1344{
1345 fgReadHomeAuthrc = readhomeauthrc;
1346}
1347
1348////////////////////////////////////////////////////////////////////////////////
1349/// Set default expiring date for new validity contexts
1350
1352{
1353 fgExpDate = expdate;
1354}
1355
1356////////////////////////////////////////////////////////////////////////////////
1357/// Set default user name.
1358
1359void TAuthenticate::SetDefaultUser(const char *defaultuser)
1360{
1361 if (fgDefaultUser != "")
1362 fgDefaultUser = "";
1363
1364 if (defaultuser && defaultuser[0])
1365 fgDefaultUser = defaultuser;
1366}
1367
1368////////////////////////////////////////////////////////////////////////////////
1369/// Set timeout (active if > 0)
1370
1372{
1373 fgAuthTO = (to <= 0) ? -1 : to;
1374}
1375
1376////////////////////////////////////////////////////////////////////////////////
1377/// Set global AuthReUse flag
1378
1380{
1381 fgAuthReUse = authreuse;
1382}
1383
1384////////////////////////////////////////////////////////////////////////////////
1385/// Set global PromptUser flag
1386
1388{
1389 fgPromptUser = promptuser;
1390}
1391
1392////////////////////////////////////////////////////////////////////////////////
1393/// Set secure authorization function.
1394
1396{
1397 fgSecAuthHook = func;
1398}
1399
1400////////////////////////////////////////////////////////////////////////////////
1401/// Set kerberos5 authorization function. Automatically called when
1402/// libKrb5Auth is loaded.
1403
1405{
1406 ::Error("Krb5Auth", "Kerberos5 is no longer supported by ROOT");
1407}
1408
1409////////////////////////////////////////////////////////////////////////////////
1410/// Set Globus authorization function. Automatically called when
1411/// libGlobusAuth is loaded.
1412
1414{
1415 ::Error("GlobusAuth", "Globus is no longer supported by ROOT");
1416}
1417
1418////////////////////////////////////////////////////////////////////////////////
1419/// SSH client authentication code (no longer supported)
1420
1422{
1423 ::Error("SshAuth", "SSH is no longer supported by ROOT");
1424 return 1;
1425}
1426
1427////////////////////////////////////////////////////////////////////////////////
1428/// Method returning the user to be used for the ssh login (no longer supported)
1429
1430const char *TAuthenticate::GetSshUser(TString /* user */) const
1431{
1432 ::Error("GetSshUser", "SSH is no longer supported by ROOT");
1433 return nullptr;
1434}
1435
1436////////////////////////////////////////////////////////////////////////////////
1437/// Check if 'host' matches 'href':
1438/// this means either equal or "containing" it, even with wild cards *
1439/// in the first field (in the case 'href' is a name, ie not IP address)
1440/// Returns kTRUE if the two matches.
1441
1442Bool_t TAuthenticate::CheckHost(const char *host, const char *href)
1443{
1445
1446 Bool_t retval = kTRUE;
1447
1448 // Both strings should have been defined
1449 if (!host || !href)
1450 return kFALSE;
1451
1452 // 'href' == '*' indicates any 'host' ...
1453 if (!strcmp(href,"*"))
1454 return kTRUE;
1455
1456 // If 'href' contains at a letter or an hyphen it is assumed to be
1457 // a host name. Otherwise a name.
1458 // Check also for wild cards
1459 Bool_t name = kFALSE;
1460 TRegexp rename("[+a-zA-Z]");
1461 Int_t len;
1462 if (rename.Index(href,&len) != -1 || strstr(href,"-"))
1463 name = kTRUE;
1464
1465 // Check also for wild cards
1466 Bool_t wild = kFALSE;
1467 if (strstr(href,"*"))
1468 wild = kTRUE;
1469
1470 // Now build the regular expression for final checking
1471 TRegexp rehost(href,wild);
1472
1473 // host to check
1474 TString theHost(host);
1475 if (!name) {
1476 TInetAddress addr = gSystem->GetHostByName(host);
1477 theHost = addr.GetHostAddress();
1478 if (gDebug > 2)
1479 ::Info("TAuthenticate::CheckHost", "checking host IP: %s", theHost.Data());
1480 }
1481
1482 // Check 'host' against 'rehost'
1483 Ssiz_t pos = rehost.Index(theHost,&len);
1484 if (pos == -1)
1485 retval = kFALSE;
1486
1487 // If IP and no wilds, it should match either
1488 // the beginning or the end of the string
1489 if (!wild) {
1490 if (pos > 0 && pos != (Ssiz_t)(theHost.Length()-strlen(href)))
1491 retval = kFALSE;
1492 }
1493
1494 return retval;
1495}
1496
1497////////////////////////////////////////////////////////////////////////////////
1498/// RFIO authentication (no longer supported)
1499
1501{
1502 ::Error("RfioAuth", "RfioAuth is no longer supported by ROOT");
1503 return -1;
1504}
1505
1506////////////////////////////////////////////////////////////////////////////////
1507/// UsrPwd client authentication code.
1508/// Returns 0 in case authentication failed
1509/// 1 in case of success
1510
1512{
1514
1515 if (gDebug > 2)
1516 Info("ClearAuth", "enter: user: %s (passwd hashed?: %d)",
1517 user.Data(),(Int_t)pwdhash);
1518
1519 Int_t reuse = fgAuthReUse;
1520 Int_t prompt = fgPromptUser;
1521 Int_t cryptopt = fgUsrPwdCrypt;
1522 Int_t needsalt = 1;
1523 if (pwdhash)
1524 needsalt = 0;
1525 fDetails = TString::Format("pt:%d ru:%d cp:%d us:",
1527 if (gDebug > 2)
1528 Info("ClearAuth", "ru:%d pt:%d cp:%d ns:%d rk:%d",
1530#ifdef R__WIN32
1531 needsalt = 0;
1532#endif
1533 Int_t stat, kind;
1534
1535 if (fVersion > 1) {
1536
1537 //
1538 // New protocol
1539 //
1540 Int_t anon = 0;
1541 TString salt = "";
1542 TString pashash = "";
1543
1544 // Get effective user (fro remote checks in $HOME/.rhosts)
1546 TString effUser;
1547 if (pw) {
1548 effUser = TString(pw->fUser);
1549 delete pw;
1550 } else
1551 effUser = user;
1552
1553 // Create options string
1554 int opt = (reuse * kAUTH_REUSE_MSK) + (cryptopt * kAUTH_CRYPT_MSK) +
1555 (needsalt * kAUTH_SSALT_MSK) + (fRSAKey * kAUTH_RSATY_MSK);
1556 TString options;
1557 options.Form("%d %ld %s %ld %s", opt,
1558 (Long_t)user.Length(), user.Data(),
1559 (Long_t)effUser.Length(), effUser.Data());
1560
1561 // Check established authentications
1562 kind = kROOTD_USER;
1563 stat = reuse;
1564 Int_t rc = 0;
1565 if ((rc = AuthExists(user, (Int_t) TAuthenticate::kClear, options,
1566 &kind, &stat, &StdCheckSecCtx)) == 1) {
1567 // A valid authentication exists: we are done ...
1568 return 1;
1569 }
1570 if (rc == -2) {
1571 return rc;
1572 }
1573 if (stat == kErrNotAllowed && kind == kROOTD_ERR) {
1574 return 0;
1575 }
1576
1577 if (kind == kROOTD_AUTH && stat == -1) {
1578 if (gDebug > 3)
1579 Info("ClearAuth", "anonymous user");
1580 anon = 1;
1581 cryptopt = 0;
1582 reuse = 0;
1583 needsalt = 0;
1584 }
1585
1586 // The random tag in hex representation
1587 // Protection against reply attacks
1588 char ctag[11] = {0};
1589 if (anon == 0 && cryptopt == 1) {
1590
1591 // Check that we got the right thing ..
1592 if (kind != kROOTD_RSAKEY || stat < 1 || stat > 2 ) {
1593 // Check for errors
1594 if (kind != kROOTD_ERR) {
1595 Warning("ClearAuth",
1596 "problems recvn RSA key flag: got message %d, flag: %d",
1597 kind, stat);
1598 }
1599 return 0;
1600 }
1601 if (gDebug > 3)
1602 Info("ClearAuth", "get key request ...");
1603
1604 // Save type of key
1605 fRSAKey = stat - 1;
1606
1607 // Send the key securely
1609 return 0;
1610
1611 int slen = 0;
1612 if (needsalt) {
1613 // Receive password salt
1614 char *tmpsalt = 0;
1615 if ((slen = SecureRecv(fSocket, 1, fRSAKey, &tmpsalt)) == -1) {
1616 Warning("ClearAuth", "problems secure-receiving salt -"
1617 " may result in corrupted salt");
1618 Warning("ClearAuth", "switch off reuse for this session");
1619 needsalt = 0;
1620 return 0;
1621 }
1622 if (slen) {
1623 // Extract random tag, if there
1624 if (slen > 9) {
1625 int ltmp = slen;
1626 while (ltmp && tmpsalt[ltmp-1] != '#') ltmp--;
1627 if (ltmp) {
1628 if (tmpsalt[ltmp-1] == '#' &&
1629 tmpsalt[ltmp-10] == '#') {
1630 strlcpy(ctag,&tmpsalt[ltmp-10],11);
1631 // We drop the random tag
1632 ltmp -= 10;
1633 tmpsalt[ltmp] = 0;
1634 // Update salt length
1635 slen -= 10;
1636 }
1637 }
1638 if (!tmpsalt[0]) {
1639 // No salt left
1640 needsalt = 0;
1641 slen = 0;
1642 }
1643 }
1644 if (slen)
1645 salt = TString(tmpsalt);
1646 delete [] tmpsalt;
1647 }
1648 if (gDebug > 2)
1649 Info("ClearAuth", "got salt: '%s' (len: %d)", salt.Data(), slen);
1650 } else {
1651 if (gDebug > 2)
1652 Info("ClearAuth", "Salt not required");
1653 char *tmptag = 0;
1654 if (SecureRecv(fSocket, 1, fRSAKey, &tmptag) == -1) {
1655 Warning("ClearAuth", "problems secure-receiving rndmtag -"
1656 " may result in corrupted rndmtag");
1657 }
1658 if (tmptag) {
1659 strlcpy(ctag, tmptag, 11);
1660 delete [] tmptag;
1661 }
1662 }
1663 // We may not have got a salt (if the server may not access it
1664 // or if it needs the full password, like for AFS ...)
1665 if (!slen)
1666 needsalt = 0;
1667 }
1668 // Now get the password either from prompt or from memory, if saved already
1669 if (anon == 1) {
1670
1671 if (fgPasswd.Contains("@")) {
1672 // Anonymous like login with user chosen passwd ...
1673 passwd = fgPasswd;
1674 } else {
1675 // Anonymous like login with automatic passwd generation ...
1676 TString localuser;
1677 pw = gSystem->GetUserInfo();
1678 if (pw) {
1679 char *u = StrDup(pw->fUser);
1680 localuser = u;
1681 delete[] u;
1682 }
1683 delete pw;
1684 static TString localFQDN;
1685 if (localFQDN == "") {
1687 if (addr.IsValid())
1688 localFQDN = addr.GetHostName();
1689 }
1690 passwd.Form("%s@%s", localuser.Data(), localFQDN.Data());
1691 if (gDebug > 2)
1692 Info("ClearAuth",
1693 "automatically generated anonymous passwd: %s",
1694 passwd.Data());
1695 }
1696
1697 } else {
1698
1699 if (prompt == 1 || pashash.Length() == 0) {
1700
1701 if (passwd == "") {
1702 TString xp;
1703 xp.Form("%s@%s password: ", user.Data(),fRemote.Data());
1704 char *pwd = PromptPasswd(xp);
1705 passwd = TString(pwd);
1706 delete [] pwd;
1707 if (passwd == "") {
1708 Error("ClearAuth", "password not set");
1709 fSocket->Send("-1", kROOTD_PASS); // Needs this for consistency
1710 return 0;
1711 }
1712 }
1713 if (needsalt && !pwdhash) {
1714#ifndef R__WIN32
1715 pashash = TString(crypt(passwd, salt));
1716 if (!pashash.BeginsWith(salt)) {
1717 // not the right version of the crypt function:
1718 // do not send hash
1719 pashash = passwd;
1720 }
1721#else
1722 pashash = passwd;
1723#endif
1724 } else {
1725 pashash = passwd;
1726 }
1727 }
1728
1729 }
1730
1731 // Store password for later use
1732 fgUser = fUser;
1733 fgPwHash = kFALSE;
1734 fPwHash = kFALSE;
1735 fgPasswd = passwd;
1736 fPasswd = passwd;
1737
1738 // Send it to server
1739 if (anon == 0 && cryptopt == 1) {
1740
1741 // Needs to send this for consistency
1742 if (fSocket->Send("\0", kROOTD_PASS) < 0)
1743 return 0;
1744
1745 // Add the random tag received from the server
1746 // (if any); makes packets non re-usable
1747 if (strlen(ctag))
1748 pashash += ctag;
1749
1750 if (SecureSend(fSocket, 1, fRSAKey, pashash.Data()) == -1) {
1751 Warning("ClearAuth", "problems secure-sending pass hash"
1752 " - may result in authentication failure");
1753 return 0;
1754 }
1755 } else {
1756
1757 // Standard technique: invert passwd
1758 if (passwd != "") {
1759 for (int i = 0; i < passwd.Length(); i++) {
1760 char inv = ~passwd(i);
1761 passwd.Replace(i, 1, inv);
1762 }
1763 }
1764 if (fSocket->Send(passwd.Data(), kROOTD_PASS) < 0)
1765 return 0;
1766 }
1767
1768 Int_t nrec = 0;
1769 // Receive username used for login
1770 if ((nrec = fSocket->Recv(stat, kind)) < 0 ) // returns user
1771 return 0;
1772 if (gDebug > 3)
1773 Info("ClearAuth", "after kROOTD_PASS: kind= %d, stat= %d", kind,
1774 stat);
1775
1776 // Check for errors
1777 if (kind == kROOTD_ERR) {
1778 AuthError("ClearAuth", stat);
1779 fgPasswd = "";
1780 return 0;
1781 }
1782
1783 if (kind != kROOTD_PASS || stat < 1)
1784 Warning("ClearAuth",
1785 "problems recvn (user,offset) length (%d:%d bytes:%d)",
1786 kind, stat, nrec);
1787
1788 // Get user and offset
1789 char answer[256];
1790 int reclen = (stat+1 > 256) ? 256 : stat+1;
1791 if ((nrec = fSocket->Recv(answer, reclen, kind)) < 0)
1792 return 0;
1793 if (kind != kMESS_STRING)
1794 Warning("ClearAuth",
1795 "username and offset not received (%d:%d)", kind,
1796 nrec);
1797
1798 // Parse answer
1799 char lUser[128];
1800 Int_t offset = -1;
1801 sscanf(answer, "%127s %d", lUser, &offset);
1802 if (gDebug > 3)
1803 Info("ClearAuth",
1804 "received from server: user: %s, offset: %d (%s)", lUser,
1805 offset, answer);
1806
1807 // Return username
1808 user = lUser;
1809
1810 char *token = 0;
1811 if (reuse == 1 && offset > -1) {
1812 // Receive token
1813 if (cryptopt == 1) {
1814 if (SecureRecv(fSocket, 1, fRSAKey, &token) == -1) {
1815 Warning("ClearAuth",
1816 "problems secure-receiving token -"
1817 " may result in corrupted token");
1818 return 0;
1819 }
1820 } else {
1821 Int_t tlen = 9;
1822 token = new char[tlen];
1823 if (fSocket->Recv(token, tlen, kind) < 0) {
1824 delete [] token;
1825 return 0;
1826 }
1827 if (kind != kMESS_STRING)
1828 Warning("ClearAuth", "token not received (%d:%d)", kind,
1829 nrec);
1830 // Invert token
1831 for (int i = 0; i < (int) strlen(token); i++) {
1832 token[i] = ~token[i];
1833 }
1834
1835 }
1836 if (gDebug > 3)
1837 Info("ClearAuth", "received from server: token: '%s' ",
1838 token);
1839 }
1840 TPwdCtx *pwdctx = new TPwdCtx(fPasswd,fPwHash);
1841 // Create SecContext object
1842 fSecContext = fHostAuth->CreateSecContext((const char *)lUser, fRemote,
1843 kClear, offset, fDetails, (const char *)token,
1844 fgExpDate, (void *)pwdctx, fRSAKey);
1845
1846 // Release allocated memory ...
1847 if (token)
1848 delete [] token;
1849
1850 // This from remote login
1851 if (fSocket->Recv(stat, kind) < 0)
1852 return 0;
1853
1854
1855 if (kind == kROOTD_AUTH && stat >= 1) {
1856 if (stat == 5 && fSocket->GetServType() == TSocket::kPROOFD)
1857 // AFS: we cannot reuse the token because remotely the
1858 // daemon token must be re-initialized; for PROOF, we
1859 // just flag the entry as AFS; this allows to skip reusing
1860 // but to keep the session key for password forwarding
1861 fSecContext->SetID("AFS authentication");
1862 return 1;
1863 } else {
1864 fgPasswd = "";
1865 if (kind == kROOTD_ERR)
1866 AuthError("ClearAuth", stat);
1867 return 0;
1868 }
1869
1870 } else {
1871
1872 // Old Protocol
1873
1874 // Send username
1875 if (fSocket->Send(user.Data(), kROOTD_USER) < 0)
1876 return 0;
1877
1878 // Get replay from server
1879 if (fSocket->Recv(stat, kind) < 0)
1880 return 0;
1881
1882 // This check should guarantee backward compatibility with a private
1883 // version of rootd used by CDF
1884 if (kind == kROOTD_AUTH && stat == 1) {
1885 fSecContext =
1887 return 1;
1888 }
1889
1890 if (kind == kROOTD_ERR) {
1891 TString server = "sockd";
1892 if (fProtocol.Contains("root"))
1893 server = "rootd";
1894 if (fProtocol.Contains("proof"))
1895 server = "proofd";
1896 if (stat == kErrConnectionRefused) {
1897 if (gDebug > 0)
1898 Error("ClearAuth",
1899 "%s@%s does not accept connections from %s@%s",
1900 server.Data(),fRemote.Data(),
1901 fUser.Data(),gSystem->HostName());
1902 return -2;
1903 } else if (stat == kErrNotAllowed) {
1904 if (gDebug > 0)
1905 Error("ClearAuth",
1906 "%s@%s does not accept %s authentication from %s@%s",
1907 server.Data(),fRemote.Data(),
1909 fUser.Data(),gSystem->HostName());
1910 } else
1911 AuthError("ClearAuth", stat);
1912 return 0;
1913 }
1914 // Prepare passwd to send
1915 badpass1:
1916 if (passwd == "") {
1917 TString xp;
1918 xp.Form("%s@%s password: ", user.Data(),fRemote.Data());
1919 char *p = PromptPasswd(xp);
1920 passwd = p;
1921 delete [] p;
1922 if (passwd == "")
1923 Error("ClearAuth", "password not set");
1924 }
1925 if (fUser == "anonymous" || fUser == "rootd") {
1926 if (!passwd.Contains("@")) {
1927 Warning("ClearAuth",
1928 "please use passwd of form: user@host.do.main");
1929 passwd = "";
1930 goto badpass1;
1931 }
1932 }
1933
1934 fgPasswd = passwd;
1935 fPasswd = passwd;
1936
1937 // Invert passwd
1938 if (passwd != "") {
1939 for (int i = 0; i < passwd.Length(); i++) {
1940 char inv = ~passwd(i);
1941 passwd.Replace(i, 1, inv);
1942 }
1943 }
1944 // Send it over the net
1945 if (fSocket->Send(passwd, kROOTD_PASS) < 0)
1946 return 0;
1947
1948 // Get result of attempt
1949 if (fSocket->Recv(stat, kind) < 0) // returns user
1950 return 0;
1951 if (gDebug > 3)
1952 Info("ClearAuth", "after kROOTD_PASS: kind= %d, stat= %d", kind,
1953 stat);
1954
1955 if (kind == kROOTD_AUTH && stat == 1) {
1956 fSecContext =
1958 return 1;
1959 } else {
1960 if (kind == kROOTD_ERR)
1961 AuthError("ClearAuth", stat);
1962 return 0;
1963 }
1964 }
1965 return 0;
1966}
1967
1968////////////////////////////////////////////////////////////////////////////////
1969/// Sets fUser=user and search fgAuthInfo for the entry pertaining to
1970/// (host,user), setting fHostAuth accordingly.
1971/// If opt = "P" use fgProofAuthInfo list instead
1972/// If no entry is found fHostAuth is not changed
1973
1974THostAuth *TAuthenticate::GetHostAuth(const char *host, const char *user,
1975 Option_t *opt, Int_t *exact)
1976{
1977 if (exact)
1978 *exact = 0;
1979
1980 if (gDebug > 2)
1981 ::Info("TAuthenticate::GetHostAuth", "enter ... %s ... %s", host, user);
1982
1983 // Strip off the servertype, if any
1984 Int_t srvtyp = -1;
1985 TString hostname = host;
1986 if (hostname.Contains(":")) {
1987 char *ps = (char *)strstr(host,":");
1988 if (ps)
1989 srvtyp = atoi(ps+1);
1990 hostname.Remove(hostname.Index(":"));
1991 }
1992 TString hostFQDN = hostname;
1993 if (strncmp(host,"default",7) && !hostFQDN.Contains("*")) {
1994 TInetAddress addr = gSystem->GetHostByName(hostFQDN);
1995 if (addr.IsValid())
1996 hostFQDN = addr.GetHostName();
1997 }
1998 TString usr = user;
1999 if (!usr.Length())
2000 usr = "*";
2001 THostAuth *rHA = 0;
2002
2003 // Check list of auth info for already loaded info about this host
2004 TIter *next = new TIter(GetAuthInfo());
2005 if (!strncasecmp(opt,"P",1)) {
2006 SafeDelete(next);
2007 next = new TIter(GetProofAuthInfo());
2008 }
2009
2010 THostAuth *ai;
2011 Bool_t notFound = kTRUE;
2012 Bool_t serverOK = kTRUE;
2013 while ((ai = (THostAuth *) (*next)())) {
2014 if (gDebug > 3)
2015 ai->Print("Authenticate::GetHostAuth");
2016
2017 // server
2018 if (!(serverOK = (ai->GetServer() == -1) ||
2019 (ai->GetServer() == srvtyp)))
2020 continue;
2021
2022 // Use default entry if existing and nothing more specific is found
2023 if (!strcmp(ai->GetHost(),"default") && serverOK && notFound)
2024 rHA = ai;
2025
2026 // Check
2027 if (CheckHost(hostFQDN,ai->GetHost()) &&
2028 CheckHost(usr,ai->GetUser()) && serverOK) {
2029 rHA = ai;
2030 notFound = kFALSE;
2031 }
2032
2033 if (hostFQDN == ai->GetHost() &&
2034 usr == ai->GetUser() && srvtyp == ai->GetServer() ) {
2035 rHA = ai;
2036 if (exact)
2037 *exact = 1;
2038 break;
2039 }
2040 }
2041 SafeDelete(next);
2042 return rHA;
2043}
2044
2045////////////////////////////////////////////////////////////////////////////////
2046/// Checks if a THostAuth with exact match for {host,user} exists
2047/// in the fgAuthInfo list
2048/// If opt = "P" use ProofAuthInfo list instead
2049/// Returns pointer to it or 0
2050
2051THostAuth *TAuthenticate::HasHostAuth(const char *host, const char *user,
2052 Option_t *opt)
2053{
2054 if (gDebug > 2)
2055 ::Info("TAuthenticate::HasHostAuth", "enter ... %s ... %s", host, user);
2056
2057 // Strip off the servertype, if any
2058 Int_t srvtyp = -1;
2059 TString hostFQDN = host;
2060 if (hostFQDN.Contains(":")) {
2061 char *ps = (char *)strstr(host,":");
2062 if (ps)
2063 srvtyp = atoi(ps+1);
2064 hostFQDN.Remove(hostFQDN.Index(":"));
2065 }
2066 if (strncmp(host,"default",7) && !hostFQDN.Contains("*")) {
2067 TInetAddress addr = gSystem->GetHostByName(hostFQDN);
2068 if (addr.IsValid())
2069 hostFQDN = addr.GetHostName();
2070 }
2071
2072 TIter *next = new TIter(GetAuthInfo());
2073 if (!strncasecmp(opt,"P",1)) {
2074 SafeDelete(next);
2075 next = new TIter(GetProofAuthInfo());
2076 }
2077 THostAuth *ai;
2078 while ((ai = (THostAuth *) (*next)())) {
2079
2080 if (hostFQDN == ai->GetHost() &&
2081 !strcmp(user, ai->GetUser()) && srvtyp == ai->GetServer()) {
2082 SafeDelete(next);
2083 return ai;
2084 }
2085 }
2086 SafeDelete(next);
2087 return 0;
2088}
2089
2090////////////////////////////////////////////////////////////////////////////////
2091/// Expands include directives found in fexp files
2092/// The expanded, temporary file, is pointed to by 'ftmp'
2093/// and should be already open. To be called recursively.
2094
2095void TAuthenticate::FileExpand(const char *fexp, FILE *ftmp)
2096{
2097 FILE *fin;
2098 char line[kMAXPATHLEN];
2099 char cinc[20], fileinc[kMAXPATHLEN];
2100
2101 if (gDebug > 2)
2102 ::Info("TAuthenticate::FileExpand", "enter ... '%s' ... 0x%lx", fexp, (Long_t)ftmp);
2103
2104 fin = fopen(fexp, "r");
2105 if (fin == 0)
2106 return;
2107
2108 while (fgets(line, sizeof(line), fin) != 0) {
2109 // Skip comment lines
2110 if (line[0] == '#')
2111 continue;
2112 if (line[strlen(line) - 1] == '\n')
2113 line[strlen(line) - 1] = '\0';
2114 if (gDebug > 2)
2115 ::Info("TAuthenticate::FileExpand", "read line ... '%s'", line);
2116 int nw = sscanf(line, "%19s %8191s", cinc, fileinc);
2117 if (nw < 1)
2118 continue; // Not enough info in this line
2119 if (strcmp(cinc, "include") != 0) {
2120 // copy line in temporary file
2121 fprintf(ftmp, "%s\n", line);
2122 } else {
2123
2124 // Drop quotes or double quotes, if any
2125 TString ln(line);
2126 ln.ReplaceAll("\"",1,"",0);
2127 ln.ReplaceAll("'",1,"",0);
2128 sscanf(ln.Data(), "%19s %8191s", cinc, fileinc);
2129
2130 // support environment directories ...
2131 if (fileinc[0] == '$') {
2132 TString finc(fileinc);
2133 TString edir(fileinc);
2134 if (edir.Contains("/")) {
2135 edir.Remove(edir.Index("/"));
2136 edir.Remove(0,1);
2137 if (gSystem->Getenv(edir.Data())) {
2138 finc.Remove(0,1);
2139 finc.ReplaceAll(edir.Data(),gSystem->Getenv(edir.Data()));
2140 fileinc[0] = '\0';
2141 strncpy(fileinc,finc.Data(),kMAXPATHLEN);
2142 fileinc[kMAXPATHLEN-1] = '\0';
2143 }
2144 }
2145 }
2146
2147 // open (expand) file in temporary file ...
2148 if (fileinc[0] == '~') {
2149 // needs to expand
2150 int flen =
2151 strlen(fileinc) + strlen(gSystem->HomeDirectory()) + 10;
2152 char *ffull = new char[flen];
2153 snprintf(ffull, flen, "%s/%s", gSystem->HomeDirectory(), fileinc + 1);
2154 if (strlen(ffull) < kMAXPATHLEN - 1) strlcpy(fileinc, ffull,kMAXPATHLEN);
2155 delete [] ffull;
2156 }
2157 // Check if file exist and can be read ... ignore if not ...
2158 if (!gSystem->AccessPathName(fileinc, kReadPermission)) {
2159 FileExpand(fileinc, ftmp);
2160 } else {
2161 ::Warning("TAuthenticate::FileExpand",
2162 "file specified by 'include' cannot be open or read (%s)",
2163 fileinc);
2164 }
2165 }
2166 }
2167 fclose(fin);
2168}
2169
2170////////////////////////////////////////////////////////////////////////////////
2171/// Determine default authentication details for method 'sec' and user 'usr'.
2172/// Checks .rootrc family files. Returned string must be deleted by the user.
2173
2174char *TAuthenticate::GetDefaultDetails(int sec, int opt, const char *usr)
2175{
2176 char temp[kMAXPATHLEN] = { 0 };
2177 const char copt[2][5] = { "no", "yes" };
2178
2179 if (gDebug > 2)
2180 ::Info("TAuthenticate::GetDefaultDetails",
2181 "enter ... %d ...pt:%d ... '%s'", sec, opt, usr);
2182
2183 if (opt < 0 || opt > 1)
2184 opt = 1;
2185
2186 // UsrPwd
2187 if (sec == TAuthenticate::kClear) {
2188 if (!usr[0] || !strncmp(usr,"*",1))
2189 usr = gEnv->GetValue("UsrPwd.Login", "");
2190 snprintf(temp, kMAXPATHLEN, "pt:%s ru:%s cp:%s us:%s",
2191 gEnv->GetValue("UsrPwd.LoginPrompt", copt[opt]),
2192 gEnv->GetValue("UsrPwd.ReUse", "1"),
2193 gEnv->GetValue("UsrPwd.Crypt", "1"), usr);
2194 }
2195
2196 if (gDebug > 2)
2197 ::Info("TAuthenticate::GetDefaultDetails", "returning ... %s", temp);
2198
2199 return StrDup(temp);
2200}
2201
2202////////////////////////////////////////////////////////////////////////////////
2203/// Remove THostAuth instance from the list
2204
2206{
2207 if (!strncasecmp(opt,"P",1))
2208 GetProofAuthInfo()->Remove(ha);
2209 else
2210 GetAuthInfo()->Remove(ha);
2211 // ... destroy it
2212 delete ha;
2213}
2214
2215////////////////////////////////////////////////////////////////////////////////
2216/// Print info about the authentication sector.
2217/// If 'opt' contains 's' or 'S' prints information about established TSecContext,
2218/// else prints information about THostAuth (if 'opt' is 'p' or 'P', prints
2219/// Proof related information)
2220
2222{
2223 TString sopt(opt);
2224
2225 if (sopt.Contains("s",TString::kIgnoreCase)) {
2226
2227 // Print established security contexts
2228 TIter next(gROOT->GetListOfSecContexts());
2229 TSecContext *sc = 0;
2230 while ((sc = (TSecContext *)next()))
2231 sc->Print();
2232
2233 } else {
2234
2235 ::Info("::Print",
2236 " +--------------------------- BEGIN --------------------------------+");
2237 ::Info("::Print",
2238 " + +");
2239 if (sopt.Contains("p",TString::kIgnoreCase)) {
2240 ::Info("::Print",
2241 " + List fgProofAuthInfo has %4d members +",
2242 GetProofAuthInfo()->GetSize());
2243 ::Info("::Print",
2244 " + +");
2245 ::Info("::Print",
2246 " +------------------------------------------------------------------+");
2247 TIter next(GetProofAuthInfo());
2248 THostAuth *ai;
2249 while ((ai = (THostAuth *) next())) {
2250 ai->Print();
2251 }
2252 } else {
2253 ::Info("::Print",
2254 " + List fgAuthInfo has %4d members +",
2255 GetAuthInfo()->GetSize());
2256 ::Info("::Print",
2257 " + +");
2258 ::Info("::Print",
2259 " +------------------------------------------------------------------+");
2260 TIter next(GetAuthInfo());
2261 THostAuth *ai;
2262 while ((ai = (THostAuth *) next())) {
2263 ai->Print();
2264 ai->PrintEstablished();
2265 }
2266 }
2267 ::Info("::Print",
2268 " +---------------------------- END ---------------------------------+");
2269 }
2270}
2271
2272////////////////////////////////////////////////////////////////////////////////
2273/// Check if we have a valid established sec context in memory
2274/// Retrieves relevant info and negotiates with server.
2275/// options = "Opt,strlen(username),username.Data()"
2276/// message = kROOTD_USER, ...
2277
2278Int_t TAuthenticate::AuthExists(TString username, Int_t method, const char *options,
2279 Int_t *message, Int_t *rflag,
2280 CheckSecCtx_t checksecctx)
2281{
2282 // Welcome message, if requested ...
2283 if (gDebug > 2)
2284 Info("AuthExists","%d: enter: msg: %d options: '%s'",
2285 method,*message, options);
2286
2287 // Look for an existing security context matching this request
2288 Bool_t notHA = kFALSE;
2289
2290 // First in the local list
2291 TIter next(fHostAuth->Established());
2292 TRootSecContext *secctx;
2293 while ((secctx = (TRootSecContext *)next())) {
2294 if (secctx->GetMethod() == method) {
2295 if (fRemote == secctx->GetHost()) {
2296 if (checksecctx &&
2297 (*checksecctx)(username,secctx) == 1)
2298 break;
2299 }
2300 }
2301 }
2302
2303 // If nothing found, try the all list
2304 if (!secctx) {
2305 next = TIter(gROOT->GetListOfSecContexts());
2306 while ((secctx = (TRootSecContext *)next())) {
2307 if (secctx->GetMethod() == method) {
2308 if (fRemote == secctx->GetHost()) {
2309 if (checksecctx &&
2310 (*checksecctx)(username,secctx) == 1) {
2311 notHA = kTRUE;
2312 break;
2313 }
2314 }
2315 }
2316 }
2317 }
2318
2319 // If we have been given a valid sec context retrieve some info
2320 Int_t offset = -1;
2321 TString token;
2322 if (secctx) {
2323 offset = secctx->GetOffSet();
2324 token = secctx->GetToken();
2325 if (gDebug > 2)
2326 Info("AuthExists",
2327 "found valid TSecContext: offset: %d token: '%s'",
2328 offset, token.Data());
2329 }
2330
2331 // Prepare string to be sent to the server
2332 TString sstr;
2333 sstr.Form("%d %d %s", fgProcessID, offset, options);
2334
2335 // Send message
2336 if (fSocket->Send(sstr, *message) < 0)
2337 return -2;
2338
2339 Int_t reuse = *rflag;
2340 if (reuse == 1 && offset > -1) {
2341
2342 // Receive result of checking offset
2343 // But only for recent servers
2344 // NB: not backward compatible with dev version 4.00.02: switch
2345 // off 'reuse' for such servers to avoid hanging at this point.
2346 Int_t rproto = fSocket->GetRemoteProtocol();
2347 Bool_t oldsrv = ((fProtocol.BeginsWith("root") && rproto == 9) ||
2348 (fProtocol.BeginsWith("proof") && rproto == 8));
2349 Int_t stat = 1, kind;
2350 if (!oldsrv) {
2351 if (fSocket->Recv(stat, kind) < 0)
2352 return -2;
2353 if (kind != kROOTD_AUTH)
2354 Warning("AuthExists","protocol error: expecting %d got %d"
2355 " (value: %d)",kROOTD_AUTH,kind,stat);
2356 }
2357
2358 if (stat > 0) {
2359 if (gDebug > 2)
2360 Info("AuthExists","offset OK");
2361
2362 Int_t rsaKey = secctx->GetRSAKey();
2363 if (gDebug > 2)
2364 Info("AuthExists", "key type: %d", rsaKey);
2365
2366 if (rsaKey > -1) {
2367
2368 // Recent servers send a random tag in stat
2369 // It has to be signed too
2370 if (stat > 1) {
2371 // Create hex from tag
2372 char tag[9] = {0};
2373 snprintf(tag, 9, "%08x",stat);
2374 // Add to token
2375 token += tag;
2376 }
2377
2378 // Send token encrypted
2379 if (SecureSend(fSocket, 1, rsaKey, token) == -1) {
2380 Warning("AuthExists", "problems secure-sending token %s",
2381 "- may trigger problems in proofing Id ");
2382 return -2;
2383 }
2384 } else {
2385 // Send inverted
2386 for (int i = 0; i < token.Length(); i++) {
2387 char inv = ~token(i);
2388 token.Replace(i, 1, inv);
2389 }
2390 if (fSocket->Send(token, kMESS_STRING) < 0)
2391 return -2;
2392 }
2393 } else {
2394 if (gDebug > 0)
2395 Info("AuthExists","offset not OK - rerun authentication");
2396 // If the sec context was not valid, deactivate it ...
2397 if (secctx)
2398 secctx->DeActivate("");
2399 }
2400 }
2401
2402 Int_t stat, kind;
2403 if (fSocket->Recv(stat, kind) < 0)
2404 return -2;
2405 if (gDebug > 3)
2406 Info("AuthExists","%d: after msg %d: kind= %d, stat= %d",
2407 method,*message, kind, stat);
2408
2409 // Return flags
2410 *message = kind;
2411 *rflag = stat;
2412
2413 if (kind == kROOTD_ERR) {
2414 TString server = "sockd";
2416 server = "rootd";
2418 server = "proofd";
2419 if (stat == kErrConnectionRefused) {
2420 Error("AuthExists","%s@%s does not accept connections from %s@%s",
2421 server.Data(),fRemote.Data(),fUser.Data(),gSystem->HostName());
2422 return -2;
2423 } else if (stat == kErrNotAllowed) {
2424 if (gDebug > 0)
2425 Info("AuthExists",
2426 "%s@%s does not accept %s authentication from %s@%s",
2427 server.Data(),fRemote.Data(), fgAuthMeth[method].Data(),
2428 fUser.Data(),gSystem->HostName());
2429 } else
2430 AuthError("AuthExists", stat);
2431
2432 // If the sec context was not valid, deactivate it ...
2433 if (secctx)
2434 secctx->DeActivate("");
2435 return 0;
2436 }
2437
2438 if (kind == kROOTD_AUTH && stat >= 1) {
2439 if (!secctx)
2440 secctx =
2442 if (gDebug > 3) {
2443 if (stat == 1)
2444 Info("AuthExists", "valid authentication exists");
2445 if (stat == 2)
2446 Info("AuthExists", "valid authentication exists: offset changed");
2447 if (stat == 3)
2448 Info("AuthExists", "remote access authorized by /etc/hosts.equiv");
2449 if (stat == 4)
2450 Info("AuthExists", "no authentication required remotely");
2451 }
2452
2453 if (stat == 2) {
2454 int newOffSet;
2455 // Receive new offset ...
2456 if (fSocket->Recv(newOffSet, kind) < 0)
2457 return -2;
2458 // ... and save it
2459 secctx->SetOffSet(newOffSet);
2460 }
2461
2462 fSecContext = secctx;
2463 // Add it to local list for later use (if not already there)
2464 if (notHA)
2465 fHostAuth->Established()->Add(secctx);
2466 return 1;
2467 }
2468 return 0;
2469}
2470
2471////////////////////////////////////////////////////////////////////////////////
2472/// Initialize random machine using seed from /dev/urandom
2473/// (or current time if /dev/urandom not available).
2474
2476{
2477 static Bool_t notinit = kTRUE;
2478
2479 if (notinit) {
2480 const char *randdev = "/dev/urandom";
2481 Int_t fd;
2482 UInt_t seed;
2483 if ((fd = open(randdev, O_RDONLY)) != -1) {
2484 if (gDebug > 2)
2485 ::Info("InitRandom", "taking seed from %s", randdev);
2486 if (read(fd, &seed, sizeof(seed)) != sizeof(seed))
2487 ::Warning("InitRandom", "could not read seed from %s", randdev);
2488 close(fd);
2489 } else {
2490 if (gDebug > 2)
2491 ::Info("InitRandom", "%s not available: using time()", randdev);
2492 seed = time(0); //better use times() + win32 equivalent
2493 }
2494 srand(seed);
2495 notinit = kFALSE;
2496 }
2497}
2498
2499////////////////////////////////////////////////////////////////////////////////
2500/// Generate a valid pair of private/public RSA keys to protect for
2501/// authentication token exchange
2502
2504{
2505 if (gDebug > 2)
2506 Info("GenRSAKeys", "enter");
2507
2508 if (fgRSAInit == 1) {
2509 if (gDebug > 2)
2510 Info("GenRSAKeys", "Keys prviously generated - return");
2511 }
2512
2513 // This is for dynamic loads ...
2514 TString lib = "libRsa";
2515
2516 // This is the local RSA implementation
2517 if (!TRSA_fun::RSA_genprim()) {
2518 char *p;
2519 if ((p = gSystem->DynamicPathName(lib, kTRUE))) {
2520 delete [] p;
2521 gSystem->Load(lib);
2522 }
2523 }
2524
2525 // Init random machine
2527
2528#ifdef R__SSL
2529 if (fgRSAKey == 1) {
2530 // Generate also the SSL key
2531 if (gDebug > 2)
2532 Info("GenRSAKeys","SSL: Generate Blowfish key");
2533
2534 // Init SSL ...
2536
2537 // ... and its error strings
2539
2540 // Load Ciphers
2541 OpenSSL_add_all_ciphers();
2542
2543 // Number of bits for key
2544 Int_t nbits = gEnv->GetValue("SSL.BFBits",256);
2545
2546 // Minimum is 128
2547 nbits = (nbits >= 128) ? nbits : 128;
2548
2549 // Max to limit size of buffers to 15912 (internal limitation)
2550 nbits = (nbits <= 15912) ? nbits : 15912;
2551
2552 // Closer Number of chars
2553 Int_t klen = nbits / 8 ;
2554
2555 // Init random engine
2556 char *rbuf = GetRandString(0,klen);
2557 RAND_seed(rbuf,strlen(rbuf));
2558
2559 // This is what we export
2560 fgRSAPubExport[1].len = klen;
2561 fgRSAPubExport[1].keys = rbuf;
2562 if (gDebug > 2)
2563 Info("GenRSAKeys","SSL: BF key length: %d", fgRSAPubExport[1].len);
2564
2565 // Now set the key locally in BF form
2566 BF_set_key(&fgBFKey, klen, (const unsigned char *)rbuf);
2567 }
2568#endif
2569
2570 // Sometimes some bunch is not decrypted correctly
2571 // That's why we make retries to make sure that encryption/decryption
2572 // works as expected
2573 Bool_t notOk = 1;
2574 rsa_NUMBER p1, p2, rsa_n, rsa_e, rsa_d;
2575 Int_t l_n = 0, l_d = 0;
2576 char buf_n[rsa_STRLEN], buf_e[rsa_STRLEN], buf_d[rsa_STRLEN];
2577#if R__RSADE
2578 Int_t l_e;
2579 char buf[rsa_STRLEN];
2580#endif
2581
2582 Int_t nAttempts = 0;
2583 Int_t thePrimeLen = kPRIMELENGTH;
2584 Int_t thePrimeExp = kPRIMEEXP; // Prime probability = 1-0.5^thePrimeExp
2585 while (notOk && nAttempts < kMAXRSATRIES) {
2586
2587 nAttempts++;
2588 if (gDebug > 2 && nAttempts > 1) {
2589 Info("GenRSAKeys", "retry no. %d",nAttempts);
2590 srand(auth_rand());
2591 }
2592
2593 // Valid pair of primes
2594 p1 = TRSA_fun::RSA_genprim()(thePrimeLen, thePrimeExp);
2595 p2 = TRSA_fun::RSA_genprim()(thePrimeLen+1, thePrimeExp);
2596
2597 // Retry if equal
2598 Int_t nPrimes = 0;
2599 while (TRSA_fun::RSA_cmp()(&p1, &p2) == 0 && nPrimes < kMAXRSATRIES) {
2600 nPrimes++;
2601 if (gDebug > 2)
2602 Info("GenRSAKeys", "equal primes: regenerate (%d times)",nPrimes);
2603 srand(auth_rand());
2604 p1 = TRSA_fun::RSA_genprim()(thePrimeLen, thePrimeExp);
2605 p2 = TRSA_fun::RSA_genprim()(thePrimeLen+1, thePrimeExp);
2606 }
2607#if R__RSADEB
2608 if (gDebug > 3) {
2610 Info("GenRSAKeys", "local: p1: '%s' ", buf);
2612 Info("GenRSAKeys", "local: p2: '%s' ", buf);
2613 }
2614#endif
2615 // Generate keys
2616 if (TRSA_fun::RSA_genrsa()(p1, p2, &rsa_n, &rsa_e, &rsa_d)) {
2617 if (gDebug > 2 && nAttempts > 1)
2618 Info("GenRSAKeys"," genrsa: unable to generate keys (%d)",
2619 nAttempts);
2620 continue;
2621 }
2622
2623 // Get equivalent strings and determine their lengths
2624 TRSA_fun::RSA_num_sput()(&rsa_n, buf_n, rsa_STRLEN);
2625 l_n = strlen(buf_n);
2626 TRSA_fun::RSA_num_sput()(&rsa_e, buf_e, rsa_STRLEN);
2627#if R__RSADEB
2628 l_e = strlen(buf_e);
2629#endif
2630 TRSA_fun::RSA_num_sput()(&rsa_d, buf_d, rsa_STRLEN);
2631 l_d = strlen(buf_d);
2632
2633#if R__RSADEB
2634 if (gDebug > 3) {
2635 Info("GenRSAKeys", "local: n: '%s' length: %d", buf_n, l_n);
2636 Info("GenRSAKeys", "local: e: '%s' length: %d", buf_e, l_e);
2637 Info("GenRSAKeys", "local: d: '%s' length: %d", buf_d, l_d);
2638 }
2639#endif
2640 if (TRSA_fun::RSA_cmp()(&rsa_n, &rsa_e) <= 0)
2641 continue;
2642 if (TRSA_fun::RSA_cmp()(&rsa_n, &rsa_d) <= 0)
2643 continue;
2644
2645 // Now we try the keys
2646 char test[2 * rsa_STRLEN] = "ThisIsTheStringTest01203456-+/";
2647 Int_t lTes = 31;
2648 char *tdum = GetRandString(0, lTes - 1);
2649 strlcpy(test, tdum, lTes+1);
2650 delete [] tdum;
2651 char buf[2 * rsa_STRLEN];
2652 if (gDebug > 3)
2653 Info("GenRSAKeys", "local: test string: '%s' ", test);
2654
2655 // Private/Public
2656 strlcpy(buf, test, lTes+1);
2657
2658 // Try encryption with private key
2659 int lout = TRSA_fun::RSA_encode()(buf, lTes, rsa_n, rsa_e);
2660 if (gDebug > 3)
2661 Info("GenRSAKeys",
2662 "local: length of crypted string: %d bytes", lout);
2663
2664 // Try decryption with public key
2665 TRSA_fun::RSA_decode()(buf, lout, rsa_n, rsa_d);
2666 buf[lTes] = 0;
2667 if (gDebug > 3)
2668 Info("GenRSAKeys", "local: after private/public : '%s' ", buf);
2669
2670 if (strncmp(test, buf, lTes))
2671 continue;
2672
2673 // Public/Private
2674 strlcpy(buf, test, lTes+1);
2675
2676 // Try encryption with public key
2677 lout = TRSA_fun::RSA_encode()(buf, lTes, rsa_n, rsa_d);
2678 if (gDebug > 3)
2679 Info("GenRSAKeys", "local: length of crypted string: %d bytes ",
2680 lout);
2681
2682 // Try decryption with private key
2683 TRSA_fun::RSA_decode()(buf, lout, rsa_n, rsa_e);
2684 buf[lTes] = 0;
2685 if (gDebug > 3)
2686 Info("GenRSAKeys", "local: after public/private : '%s' ", buf);
2687
2688 if (strncmp(test, buf, lTes))
2689 continue;
2690
2691 notOk = 0;
2692 }
2693
2694 // Save Private key
2695 TRSA_fun::RSA_assign()(&fgRSAPriKey.n, &rsa_n);
2696 TRSA_fun::RSA_assign()(&fgRSAPriKey.e, &rsa_e);
2697
2698 // Save Public key
2699 TRSA_fun::RSA_assign()(&fgRSAPubKey.n, &rsa_n);
2700 TRSA_fun::RSA_assign()(&fgRSAPubKey.e, &rsa_d);
2701
2702#if R__RSADEB
2703 if (gDebug > 2) {
2704 // Determine their lengths
2705 Info("GenRSAKeys", "local: generated keys are:");
2706 Info("GenRSAKeys", "local: n: '%s' length: %d", buf_n, l_n);
2707 Info("GenRSAKeys", "local: e: '%s' length: %d", buf_e, l_e);
2708 Info("GenRSAKeys", "local: d: '%s' length: %d", buf_d, l_d);
2709 }
2710#endif
2711 // Export form
2712 if (fgRSAPubExport[0].keys) {
2713 delete [] fgRSAPubExport[0].keys;
2714 fgRSAPubExport[0].len = 0;
2715 }
2716 fgRSAPubExport[0].len = l_n + l_d + 4;
2717 fgRSAPubExport[0].keys = new char[fgRSAPubExport[0].len];
2718
2719 fgRSAPubExport[0].keys[0] = '#';
2720 memcpy(fgRSAPubExport[0].keys + 1, buf_n, l_n);
2721 fgRSAPubExport[0].keys[l_n + 1] = '#';
2722 memcpy(fgRSAPubExport[0].keys + l_n + 2, buf_d, l_d);
2723 fgRSAPubExport[0].keys[l_n + l_d + 2] = '#';
2724 fgRSAPubExport[0].keys[l_n + l_d + 3] = 0;
2725#if R__RSADEB
2726 if (gDebug > 2)
2727 Info("GenRSAKeys", "local: export pub: '%s'", fgRSAPubExport[0].keys);
2728#else
2729 if (gDebug > 2)
2730 Info("GenRSAKeys", "local: export pub length: %d bytes", fgRSAPubExport[0].len);
2731#endif
2732
2733 // Set availability flag
2734 fgRSAInit = 1;
2735
2736 return 0;
2737}
2738
2739////////////////////////////////////////////////////////////////////////////////
2740/// Allocates and fills a 0 terminated buffer of length len+1 with
2741/// len random characters.
2742/// Returns pointer to the buffer (to be deleted by the caller)
2743/// opt = 0 any non dangerous char
2744/// 1 letters and numbers (upper and lower case)
2745/// 2 hex characters (upper and lower case)
2746
2748{
2749 unsigned int iimx[4][4] = {
2750 {0x0, 0xffffff08, 0xafffffff, 0x2ffffffe}, // opt = 0
2751 {0x0, 0x3ff0000, 0x7fffffe, 0x7fffffe}, // opt = 1
2752 {0x0, 0x3ff0000, 0x7e, 0x7e}, // opt = 2
2753 {0x0, 0x3ffc000, 0x7fffffe, 0x7fffffe} // opt = 3
2754 };
2755
2756 const char *cOpt[4] = { "Any", "LetNum", "Hex", "Crypt" };
2757
2758 // Default option 0
2759 if (opt < 0 || opt > 2) {
2760 opt = 0;
2761 if (gDebug > 2)
2762 Info("GetRandString", "unknown option: %d : assume 0", opt);
2763 }
2764 if (gDebug > 2)
2765 Info("GetRandString", "enter ... len: %d %s", len, cOpt[opt]);
2766
2767 // Allocate buffer
2768 char *buf = new char[len + 1];
2769
2770 // Init random machine (if needed)
2772
2773 // randomize
2774 Int_t k = 0;
2775 Int_t i, j, l, m, frnd;
2776 while (k < len) {
2777 frnd = auth_rand();
2778 for (m = 7; m < 32; m += 7) {
2779 i = 0x7F & (frnd >> m);
2780 j = i / 32;
2781 l = i - j * 32;
2782 if ((iimx[opt][j] & (1 << l))) {
2783 buf[k] = i;
2784 k++;
2785 }
2786 if (k == len)
2787 break;
2788 }
2789 }
2790
2791 // null terminated
2792 buf[len] = 0;
2793 if (gDebug > 3)
2794 Info("GetRandString", "got '%s' ", buf);
2795
2796 return buf;
2797}
2798
2799////////////////////////////////////////////////////////////////////////////////
2800/// Encode null terminated str using the session private key indicated by enc
2801/// and sends it over the network
2802/// Returns number of bytes sent, or -1 in case of error.
2803/// enc = 1 for private encoding, enc = 2 for public encoding
2804
2806 Int_t key, const char *str)
2807{
2808 char buftmp[kMAXSECBUF];
2809 char buflen[20];
2810
2811 if (gDebug > 2)
2812 ::Info("TAuthenticate::SecureSend", "local: enter ... (enc: %d)", enc);
2813
2814 Int_t slen = strlen(str) + 1;
2815 Int_t ttmp = 0;
2816 Int_t nsen = -1;
2817
2818 if (key == 0) {
2819 strlcpy(buftmp, str, slen+1);
2820
2821 if (enc == 1)
2822 ttmp = TRSA_fun::RSA_encode()(buftmp, slen, fgRSAPriKey.n,
2823 fgRSAPriKey.e);
2824 else if (enc == 2)
2825 ttmp = TRSA_fun::RSA_encode()(buftmp, slen, fgRSAPubKey.n,
2826 fgRSAPubKey.e);
2827 else
2828 return nsen;
2829 } else if (key == 1) {
2830
2831#ifdef R__SSL
2832 ttmp = strlen(str);
2833 if ((ttmp % 8) > 0) // It should be a multiple of 8!
2834 ttmp = ((ttmp + 8)/8) * 8;
2835 unsigned char iv[8];
2836 memset((void *)&iv[0],0,8);
2837 BF_cbc_encrypt((const unsigned char *)str, (unsigned char *)buftmp,
2838 strlen(str), &fgBFKey, iv, BF_ENCRYPT);
2839#else
2840 if (gDebug > 0)
2841 ::Info("TAuthenticate::SecureSend","not compiled with SSL support:"
2842 " you should not have got here!");
2843#endif
2844 } else {
2845 if (gDebug > 0)
2846 ::Info("TAuthenticate::SecureSend","unknown key type (%d)",key);
2847 return nsen;
2848 }
2849
2850 snprintf(buflen,20,"%d",ttmp);
2851 if (sock->Send(buflen, kROOTD_ENCRYPT) < 0)
2852 return -1;
2853 nsen = sock->SendRaw(buftmp, ttmp);
2854 if (gDebug > 3)
2855 ::Info("TAuthenticate::SecureSend",
2856 "local: sent %d bytes (expected: %d)", nsen,ttmp);
2857
2858 return nsen;
2859}
2860
2861////////////////////////////////////////////////////////////////////////////////
2862/// Receive str from sock and decode it using key indicated by key type
2863/// Return number of received bytes or -1 in case of error.
2864/// dec = 1 for private decoding, dec = 2 for public decoding
2865
2867{
2868
2869 char buftmp[kMAXSECBUF];
2870 char buflen[20];
2871
2872 Int_t nrec = -1;
2873 // We must get a pointer ...
2874 if (!str)
2875 return nrec;
2876
2877 Int_t kind;
2878 if (sock->Recv(buflen, 20, kind) < 0)
2879 return -1;
2880 Int_t len = atoi(buflen);
2881 if (gDebug > 3)
2882 ::Info("TAuthenticate::SecureRecv", "got len '%s' %d (msg kind: %d)",
2883 buflen, len, kind);
2884 if (len == 0) {
2885 return len;
2886 }
2887 if (!strncmp(buflen, "-1", 2))
2888 return nrec;
2889
2890 // Receive buffer
2891 if ((nrec = sock->RecvRaw(buftmp, len)) < 0)
2892 return nrec;
2893 if (key == 0) {
2894 if (dec == 1)
2895 TRSA_fun::RSA_decode()(buftmp, len, fgRSAPriKey.n, fgRSAPriKey.e);
2896 else if (dec == 2)
2897 TRSA_fun::RSA_decode()(buftmp, len, fgRSAPubKey.n, fgRSAPubKey.e);
2898 else
2899 return -1;
2900
2901 // Prepare output
2902 const size_t strSize = strlen(buftmp) + 1;
2903 *str = new char[strSize];
2904 strlcpy(*str, buftmp, strSize);
2905
2906 } else if (key == 1) {
2907#ifdef R__SSL
2908 unsigned char iv[8];
2909 memset((void *)&iv[0],0,8);
2910 *str = new char[nrec + 1];
2911 BF_cbc_encrypt((const unsigned char *)buftmp, (unsigned char *)(*str),
2912 nrec, &fgBFKey, iv, BF_DECRYPT);
2913 (*str)[nrec] = '\0';
2914#else
2915 if (gDebug > 0)
2916 ::Info("TAuthenticate::SecureRecv","not compiled with SSL support:"
2917 " you should not have got here!");
2918#endif
2919 } else {
2920 if (gDebug > 0)
2921 ::Info("TAuthenticate::SecureRecv","unknown key type (%d)",key);
2922 return -1;
2923 }
2924
2925 nrec= strlen(*str);
2926
2927 return nrec;
2928}
2929
2930////////////////////////////////////////////////////////////////////////////////
2931/// Store RSA public keys from export string rsaPubExport.
2932
2933Int_t TAuthenticate::DecodeRSAPublic(const char *rsaPubExport, R__rsa_NUMBER &rsa_n,
2934 R__rsa_NUMBER &rsa_d, char **rsassl)
2935{
2936 if (!rsaPubExport)
2937 return -1;
2938
2939 if (gDebug > 2)
2940 ::Info("TAuthenticate::DecodeRSAPublic",
2941 "enter: string length: %ld bytes", (Long_t)strlen(rsaPubExport));
2942
2943 char str[kMAXPATHLEN] = { 0 };
2944 Int_t klen = strlen(rsaPubExport);
2945 if (klen > kMAXPATHLEN - 1) {
2946 ::Info("TAuthenticate::DecodeRSAPublic",
2947 "key too long (%d): truncate to %d",klen,kMAXPATHLEN);
2948 klen = kMAXPATHLEN - 1;
2949 }
2950 memcpy(str, rsaPubExport, klen);
2951 str[klen] ='\0';
2952
2953 Int_t keytype = -1;
2954
2955 if (klen > 0) {
2956
2957 // Skip spaces at beginning, if any
2958 int k = 0;
2959 while (str[k] == 32) k++;
2960
2961 if (str[k] == '#') {
2962
2963 keytype = 0;
2964
2965 // The format is #<hex_n>#<hex_d>#
2966 char *pd1 = strstr(str, "#");
2967 char *pd2 = pd1 ? strstr(pd1 + 1, "#") : (char *)0;
2968 char *pd3 = pd2 ? strstr(pd2 + 1, "#") : (char *)0;
2969 if (pd1 && pd2 && pd3) {
2970 // Get <hex_n> ...
2971 int l1 = (int) (pd2 - pd1 - 1);
2972 char *rsa_n_exp = new char[l1 + 1];
2973 strlcpy(rsa_n_exp, pd1 + 1, l1+1);
2974 if (gDebug > 2)
2975 ::Info("TAuthenticate::DecodeRSAPublic",
2976 "got %ld bytes for rsa_n_exp", (Long_t)strlen(rsa_n_exp));
2977 // Now <hex_d>
2978 int l2 = (int) (pd3 - pd2 - 1);
2979 char *rsa_d_exp = new char[l2 + 1];
2980 strlcpy(rsa_d_exp, pd2 + 1, 13);
2981 if (gDebug > 2)
2982 ::Info("TAuthenticate::DecodeRSAPublic",
2983 "got %ld bytes for rsa_d_exp", (Long_t)strlen(rsa_d_exp));
2984
2985 TRSA_fun::RSA_num_sget()(&rsa_n, rsa_n_exp);
2986 TRSA_fun::RSA_num_sget()(&rsa_d, rsa_d_exp);
2987
2988 delete[] rsa_n_exp;
2989 delete[] rsa_d_exp;
2990
2991 } else
2992 ::Info("TAuthenticate::DecodeRSAPublic","bad format for input string");
2993#ifdef R__SSL
2994 } else {
2995 // try SSL
2996 keytype = 1;
2997
2998 RSA *rsatmp;
2999
3000 // Bio for exporting the pub key
3001 BIO *bpub = BIO_new(BIO_s_mem());
3002
3003 // Write key from kbuf to BIO
3004 BIO_write(bpub,(void *)str,strlen(str));
3005
3006 // Read pub key from BIO
3007 if (!(rsatmp = PEM_read_bio_RSAPublicKey(bpub, 0, 0, 0))) {
3008 if (gDebug > 0)
3009 ::Info("TAuthenticate::DecodeRSAPublic",
3010 "unable to read pub key from bio");
3011 } else
3012 if (rsassl)
3013 *rsassl = (char *)rsatmp;
3014 else
3015 ::Info("TAuthenticate::DecodeRSAPublic",
3016 "no space allocated for output variable");
3017 BIO_free(bpub);
3018 }
3019#else
3020 } else {
3021 if (rsassl) { } // To avoid compiler complains
3022 if (gDebug > 0)
3023 ::Info("TAuthenticate::DecodeRSAPublic","not compiled with SSL support:"
3024 " you should not have got here!");
3025 }
3026#endif
3027 }
3028
3029 return keytype;
3030}
3031
3032////////////////////////////////////////////////////////////////////////////////
3033/// Store RSA public keys from export string rsaPubExport.
3034/// Returns type of stored key, or -1 is not recognized
3035
3036Int_t TAuthenticate::SetRSAPublic(const char *rsaPubExport, Int_t klen)
3037{
3038 if (gDebug > 2)
3039 ::Info("TAuthenticate::SetRSAPublic",
3040 "enter: string length %ld bytes", (Long_t)strlen(rsaPubExport));
3041
3042 Int_t rsakey = -1;
3043 if (!rsaPubExport)
3044 return rsakey;
3045
3046 if (klen > 0) {
3047
3048 // Skip spaces at beginning, if any
3049 int k0 = 0;
3050 while (rsaPubExport[k0] == 32) k0++;
3051 int k2 = klen - 1;
3052
3053 // Parse rsaPubExport
3054 // Type 0 is in the form
3055 //
3056 // #< gt 10 exa chars >#< gt 10 exa chars >#
3057 //
3058 rsakey = 1;
3059 if (rsaPubExport[k0] == '#' && rsaPubExport[k2] == '#') {
3060 char *p0 = (char *)&rsaPubExport[k0];
3061 char *p2 = (char *)&rsaPubExport[k2];
3062 char *p1 = strchr(p0+1,'#');
3063 if (p1 > p0 && p1 < p2) {
3064 Int_t l01 = (Int_t)(p1-p0)-1;
3065 Int_t l12 = (Int_t)(p2-p1)-1;
3066 if (l01 >= kPRIMELENGTH*2 && l12 >= kPRIMELENGTH*2) {
3067 // Require exadecimal chars in between
3068 char *c = p0+1;
3069 while (c < p1 && ((*c < 58 && *c > 47) || (*c < 91 && *c > 64)))
3070 c++;
3071 if (c == p1) {
3072 c++;
3073 while (c < p2 && ((*c < 58 && *c > 47) || (*c < 91 && *c > 64)))
3074 c++;
3075 if (c == p2)
3076 rsakey = 0;
3077 }
3078 }
3079 }
3080 }
3081 if (gDebug > 3)
3082 ::Info("TAuthenticate::SetRSAPublic"," Key type: %d",rsakey);
3083 if (rsakey == 0) {
3084
3085 // Decode input string
3086 R__rsa_NUMBER rsa_n, rsa_d;
3087 rsakey = TAuthenticate::DecodeRSAPublic(rsaPubExport,rsa_n,rsa_d);
3088
3089 // Save Public key
3090 TRSA_fun::RSA_assign()(&fgRSAPubKey.n, &rsa_n);
3091 TRSA_fun::RSA_assign()(&fgRSAPubKey.e, &rsa_d);
3092
3093 } else {
3094 rsakey = 1;
3095#ifdef R__SSL
3096 // Now set the key locally in BF form
3097 BF_set_key(&fgBFKey, klen, (const unsigned char *)rsaPubExport);
3098#else
3099 if (gDebug > 0)
3100 ::Info("TAuthenticate::SetRSAPublic",
3101 "not compiled with SSL support:"
3102 " you should not have got here!");
3103#endif
3104 }
3105 }
3106
3107 return rsakey;
3108}
3109
3110////////////////////////////////////////////////////////////////////////////////
3111/// Receives server RSA Public key
3112/// Sends local RSA public key encoded
3113
3115{
3116 // Receive server public key
3117 char serverPubKey[kMAXSECBUF];
3118 int kind, nr = 0;
3119 if ((nr = socket->Recv(serverPubKey, kMAXSECBUF, kind)) < 0)
3120 return nr;
3121 if (gDebug > 3)
3122 ::Info("TAuthenticate::SendRSAPublicKey",
3123 "received key from server %ld bytes", (Long_t)strlen(serverPubKey));
3124
3125 // Decode it
3126 R__rsa_NUMBER rsa_n, rsa_d;
3127#ifdef R__SSL
3128 char *tmprsa = 0;
3129 if (TAuthenticate::DecodeRSAPublic(serverPubKey,rsa_n,rsa_d,
3130 &tmprsa) != key) {
3131 if (tmprsa)
3132 RSA_free((RSA *)tmprsa);
3133 return -1;
3134 }
3135 RSA *RSASSLServer = (RSA *)tmprsa;
3136#else
3137 if (TAuthenticate::DecodeRSAPublic(serverPubKey,rsa_n,rsa_d) != key)
3138 return -1;
3139#endif
3140
3141 // Send local public key, encodes
3142 char buftmp[kMAXSECBUF] = {0};
3143 char buflen[20] = {0};
3144 Int_t slen = fgRSAPubExport[key].len;
3145 Int_t ttmp = 0;
3146 if (key == 0) {
3147 strlcpy(buftmp,fgRSAPubExport[key].keys,slen+1);
3148 ttmp = TRSA_fun::RSA_encode()(buftmp, slen, rsa_n, rsa_d);
3149 snprintf(buflen, 20, "%d", ttmp);
3150 } else if (key == 1) {
3151#ifdef R__SSL
3152 Int_t lcmax = RSA_size(RSASSLServer) - 11;
3153 Int_t kk = 0;
3154 Int_t ke = 0;
3155 Int_t ns = slen;
3156 while (ns > 0) {
3157 Int_t lc = (ns > lcmax) ? lcmax : ns ;
3158 if ((ttmp = RSA_public_encrypt(lc,
3159 (unsigned char *)&fgRSAPubExport[key].keys[kk],
3160 (unsigned char *)&buftmp[ke],
3161 RSASSLServer,RSA_PKCS1_PADDING)) < 0) {
3162 char errstr[120];
3164 ::Info("TAuthenticate::SendRSAPublicKey","SSL: error: '%s' ",errstr);
3165 }
3166 kk += lc;
3167 ke += ttmp;
3168 ns -= lc;
3169 }
3170 ttmp = ke;
3171 snprintf(buflen, 20, "%d", ttmp);
3172#else
3173 if (gDebug > 0)
3174 ::Info("TAuthenticate::SendRSAPublicKey","not compiled with SSL support:"
3175 " you should not have got here!");
3176 return -1;
3177#endif
3178 } else {
3179 if (gDebug > 0)
3180 ::Info("TAuthenticate::SendRSAPublicKey","unknown key type (%d)",key);
3181#ifdef R__SSL
3182 if (RSASSLServer)
3183 RSA_free(RSASSLServer);
3184#endif
3185 return -1;
3186 }
3187
3188 // Send length first
3189 if ((nr = socket->Send(buflen, kROOTD_ENCRYPT)) < 0)
3190 return nr;
3191 // Send Key. second ...
3192 Int_t nsen = socket->SendRaw(buftmp, ttmp);
3193 if (gDebug > 3)
3194 ::Info("TAuthenticate::SendRSAPublicKey",
3195 "local: sent %d bytes (expected: %d)", nsen,ttmp);
3196#ifdef R__SSL
3197 if (RSASSLServer)
3198 RSA_free(RSASSLServer);
3199#endif
3200 return nsen;
3201}
3202
3203////////////////////////////////////////////////////////////////////////////////
3204/// Read authentication directives from $ROOTAUTHRC, $HOME/.rootauthrc or
3205/// <Root_etc_dir>/system.rootauthrc and create related THostAuth objects.
3206/// Files are read only if they changed since last reading
3207/// If 'proofconf' is defined, check also file proofconf for directives
3208
3210{
3211 // rootauthrc family
3212 char *authrc = 0;
3213 if (gSystem->Getenv("ROOTAUTHRC") != 0) {
3214 authrc = StrDup(gSystem->Getenv("ROOTAUTHRC"));
3215 } else {
3216 if (fgReadHomeAuthrc)
3217 authrc = gSystem->ConcatFileName(gSystem->HomeDirectory(), ".rootauthrc");
3218 }
3219 if (authrc && gDebug > 2)
3220 ::Info("TAuthenticate::ReadRootAuthrc", "Checking file: %s", authrc);
3221 if (!authrc || gSystem->AccessPathName(authrc, kReadPermission)) {
3222 if (authrc && gDebug > 1)
3223 ::Info("TAuthenticate::ReadRootAuthrc",
3224 "file %s cannot be read (errno: %d)", authrc, errno);
3225 delete [] authrc;
3226 authrc = gSystem->ConcatFileName(TROOT::GetEtcDir(), "system.rootauthrc");
3227 if (gDebug > 2)
3228 ::Info("TAuthenticate::ReadRootAuthrc", "Checking system file: %s", authrc);
3229 if (gSystem->AccessPathName(authrc, kReadPermission)) {
3230 if (gDebug > 1)
3231 ::Info("TAuthenticate::ReadRootAuthrc",
3232 "file %s cannot be read (errno: %d)", authrc, errno);
3233 delete [] authrc;
3234 return 0;
3235 }
3236 }
3237
3238 // Check if file has changed since last read
3239 TString tRootAuthrc = authrc;
3240 if (tRootAuthrc == fgRootAuthrc) {
3241 struct stat si;
3242 stat(tRootAuthrc, &si);
3243 if ((UInt_t)si.st_mtime < fgLastAuthrc.Convert()) {
3244 if (gDebug > 1)
3245 ::Info("TAuthenticate::ReadRootAuthrc",
3246 "file %s already read", authrc);
3247 delete [] authrc;
3248 return 0;
3249 }
3250 }
3251
3252 // Save filename in static variable
3253 fgRootAuthrc = tRootAuthrc;
3255
3256 // THostAuth lists
3257 TList *authinfo = TAuthenticate::GetAuthInfo();
3258 TList *proofauthinfo = TAuthenticate::GetProofAuthInfo();
3259
3260 // Expand File into temporary file name and open it
3261 int expand = 1;
3262 TString filetmp = "rootauthrc";
3263 FILE *ftmp = gSystem->TempFileName(filetmp);
3264 if (gDebug > 2)
3265 ::Info("TAuthenticate::ReadRootAuthrc", "got tmp file: %s open at 0x%lx",
3266 filetmp.Data(), (Long_t)ftmp);
3267 if (ftmp == 0)
3268 expand = 0; // Problems opening temporary file: ignore 'include's ...
3269
3270 FILE *fd = 0;
3271 // If the temporary file is open, copy everything to the new file ...
3272 if (expand == 1) {
3273 TAuthenticate::FileExpand(authrc, ftmp);
3274 fd = ftmp;
3275 rewind(fd);
3276 } else {
3277 // Open file
3278 fd = fopen(authrc, "r");
3279 if (fd == 0) {
3280 if (gDebug > 2)
3281 ::Info("TAuthenticate::ReadRootAuthrc",
3282 "file %s cannot be open (errno: %d)", authrc, errno);
3283 delete [] authrc;
3284 return 0;
3285 }
3286 }
3287
3288 // Now scan file for meaningful directives
3289 TList tmpAuthInfo;
3290 char line[kMAXPATHLEN];
3291 Bool_t cont = kFALSE;
3292 TString proofserv;
3293 while (fgets(line, sizeof(line), fd) != 0) {
3294
3295 // Skip comment lines
3296 if (line[0] == '#')
3297 continue;
3298
3299 // Get rid of end of line '\n', if there ...
3300 if (line[strlen(line) - 1] == '\n')
3301 line[strlen(line) - 1] = '\0';
3302
3303 // Skip empty lines
3304 if (!line[0])
3305 continue;
3306
3307 // Now scan
3308 const size_t tmpSize = strlen(line) + 1;
3309 char *tmp = new char[tmpSize];
3310 if (!tmp) {
3311 ::Error("TAuthenticate::ReadRootAuthrc",
3312 "could not allocate temporary buffer");
3313 fclose(fd);
3314 return 0;
3315 }
3316 strlcpy(tmp, line, tmpSize);
3317 char *nxt = strtok(tmp," ");
3318
3319 if (!strcmp(nxt, "proofserv") || cont) {
3320
3321 // Building the list of data servers for proof (analyzed at the end)
3322 char *ph = 0;
3323 if (cont)
3324 ph = nxt;
3325 else
3326 ph = strtok(0," ");
3327 while (ph) {
3328 if (*ph != 92) {
3329 proofserv += TString((const char *)ph);
3330 proofserv += TString(" ");
3331 cont = kFALSE;
3332 } else {
3333 cont = kTRUE;
3334 }
3335 ph = strtok(0," ");
3336 }
3337
3338 } else {
3339
3340 TString hostsrv = nxt;
3341 TString host = hostsrv;
3342 TString server = "";
3343 if (hostsrv.Contains(":")) {
3344 server = hostsrv;
3345 host.Remove(host.Index(":"));
3346 server.Remove(0,server.Index(":")+1);
3347 }
3348 Int_t srvtyp = -1;
3349 if (server.Length()) {
3350 if (server == "0" || server.BeginsWith("sock"))
3351 srvtyp = TSocket::kSOCKD;
3352 else if (server == "1" || server.BeginsWith("root"))
3353 srvtyp = TSocket::kROOTD;
3354 else if (server == "2" || server.BeginsWith("proof"))
3355 srvtyp = TSocket::kPROOFD;
3356 }
3357
3358 // Line with host info directives
3359 TString user = "*";
3360
3361 nxt = strtok(0," ");
3362 if (!strncmp(nxt,"user",4)) {
3363 nxt = strtok(0," ");
3364 if (strncmp(nxt,"list",4) && strncmp(nxt,"method",6)) {
3365 user = TString(nxt);
3366 nxt = strtok(0," ");
3367 }
3368 }
3369
3370 // Get related THostAuth, if exists in the tmp list,
3371 TIter next(&tmpAuthInfo);
3372 THostAuth *ha;
3373 while ((ha = (THostAuth *)next())) {
3374 if (host == ha->GetHost() && user == ha->GetUser() &&
3375 srvtyp == ha->GetServer())
3376 break;
3377 }
3378 if (!ha) {
3379 // Create a new one
3380 ha = new THostAuth(host,srvtyp,user);
3381 tmpAuthInfo.Add(ha);
3382 }
3383
3384 if (!strncmp(nxt,"list",4)) {
3385 // list of methods for {host,usr}
3386 Int_t nm = 0, me[kMAXSEC] = {0};
3387 char *mth = strtok(0," ");
3388 while (mth) {
3389 Int_t met = -1;
3390 if (strlen(mth) > 1) {
3391 // Method passed as string: translate it to number
3392 met = GetAuthMethodIdx(mth);
3393 if (met == -1 && gDebug > 2)
3394 ::Info("TAuthenticate::ReadRootAuthrc",
3395 "unrecognized method (%s): ", mth);
3396 } else {
3397 met = atoi(mth);
3398 }
3399 if (met > -1 && met < kMAXSEC)
3400 me[nm++] = met;
3401 mth = strtok(0," ");
3402 }
3403 if (nm)
3404 ha->ReOrder(nm,me);
3405
3406 } else if (!strncmp(nxt,"method",6)) {
3407
3408 // details for {host,usr,method}
3409 char *mth = strtok(0," ");
3410 Int_t met = -1;
3411 if (strlen(mth) > 1) {
3412 // Method passed as string: translate it to number
3413 met = GetAuthMethodIdx(mth);
3414 if (met == -1 && gDebug > 2)
3415 ::Info("TAuthenticate::ReadRootAuthrc",
3416 "unrecognized method (%s): ", mth);
3417 } else {
3418 met = atoi(mth);
3419 }
3420 if (met > -1 && met < kMAXSEC) {
3421 const char *det = 0;
3422 nxt = strtok(0," ");
3423 if (nxt) {
3424 det = (const char *)strstr(line,nxt);
3425 }
3426 if (ha->HasMethod(met))
3427 ha->SetDetails(met,det);
3428 else
3429 ha->AddMethod(met,det);
3430 }
3431 }
3432 }
3433 if (tmp) delete [] tmp;
3434 }
3435 // Close file and remove it if temporary
3436 fclose(fd);
3437 if (expand == 1)
3438 gSystem->Unlink(filetmp);
3439 // Cleanup allocated memory
3440 delete [] authrc;
3441
3442 // Update authinfo with new info found
3443 TAuthenticate::MergeHostAuthList(authinfo,&tmpAuthInfo);
3444
3445 // Print those left, if requested ...
3446 if (gDebug > 2)
3448
3449 // Now create the list of THostAuth to be sent over to
3450 // the Master/Slaves, if requested ...
3451 TList tmpproofauthinfo;
3452 if (proofserv.Length() > 0) {
3453 char *tmps = new char[proofserv.Length()+1];
3454 strlcpy(tmps,proofserv.Data(),proofserv.Length()+1);
3455 char *nxt = strtok(tmps," ");
3456 while (nxt) {
3457 TString tmp((const char *)nxt);
3458 Int_t pdd = -1;
3459 // host
3460 TString host;
3461 if ((pdd = tmp.Index(":")) == -1) {
3462 host = tmp;
3463 } else {
3464 host = tmp;
3465 host.Resize(pdd);
3466 if (!host.Length())
3467 host = "*";
3468 tmp.Remove(0,pdd+1);
3469 }
3470 // user
3471 TString user;
3472 if ((pdd = tmp.Index(":")) == -1) {
3473 user = tmp;
3474 } else {
3475 user = tmp;
3476 user.Resize(pdd);
3477 if (!user.Length())
3478 user = "*";
3479 tmp.Remove(0,pdd+1);
3480 }
3481 // method(s)
3482 TString meth;
3483 Int_t nm = 0, me[kMAXSEC] = {0}, met = -1;
3484 while (tmp.Length() > 0) {
3485 meth = tmp;
3486 if ((pdd = tmp.Index(":")) > -1)
3487 meth.Resize(pdd);
3488 if (meth.Length() > 1) {
3489 // Method passed as string: translate it to number
3490 met = GetAuthMethodIdx(meth.Data());
3491 if (met == -1 && gDebug > 2)
3492 ::Info("TAuthenticate::ReadRootAuthrc",
3493 "unrecognized method (%s): ",meth.Data());
3494 } else if (meth.Length() == 1) {
3495 met = atoi(meth.Data());
3496 if (met > -1 && met < kMAXSEC)
3497 me[nm++] = met;
3498 }
3499 if (pdd > -1)
3500 tmp.Remove(0,pdd+1);
3501 else
3502 tmp.Resize(0);
3503 }
3504
3505 // Get related THostAuth, if exists, or create a new one
3506 THostAuth *ha = 0;
3507 THostAuth *hatmp = TAuthenticate::GetHostAuth(host,user);
3508 if (!hatmp) {
3509 ha = new THostAuth(host,user,nm,me,0);
3510 } else {
3511 // Create an empty THostAuth
3512 ha = new THostAuth(host,user);
3513 // Update with hatmp info
3514 ha->Update(hatmp);
3515 // ReOrder following new directives
3516 ha->ReOrder(nm,me);
3517 }
3518 // Add to the tmp list
3519 tmpproofauthinfo.Add(ha);
3520 // Go to next
3521 nxt = strtok(0," ");
3522 }
3523 delete [] tmps;
3524 }
3525
3526 // Update proofauthinfo with new info found
3527 TAuthenticate::MergeHostAuthList(proofauthinfo,&tmpproofauthinfo,"P");
3528 // Print those, if requested ...
3529 if (gDebug > 2)
3531
3532 return authinfo->GetSize();
3533}
3534
3535////////////////////////////////////////////////////////////////////////////////
3536/// Check if the authentication method can be attempted for the client.
3537
3539{
3540 Bool_t rc = kFALSE;
3541 const char netrc[2][20] = { "/.netrc", "/.rootnetrc" };
3542 TString user;
3543
3544 // Get user logon name
3546 if (pw) {
3547 user = TString(pw->fUser);
3548 delete pw;
3549 } else {
3550 ::Info("CheckProofAuth",
3551 "not properly logged on (getpwuid unable to find relevant info)!");
3552 out = "";
3553 return rc;
3554 }
3555
3556 // UsrPwd
3557 if (cSec == (Int_t) TAuthenticate::kClear) {
3558 Int_t i = 0;
3559 for (; i < 2; i++) {
3560 TString infofile = TString(gSystem->HomeDirectory())+TString(netrc[i]);
3561 if (!gSystem->AccessPathName(infofile, kReadPermission))
3562 rc = kTRUE;
3563 }
3564 if (rc)
3565 out.Form("pt:0 ru:1 us:%s",user.Data());
3566 }
3567
3568 if (gDebug > 3) {
3569 if (strlen(out) > 0)
3570 ::Info("CheckProofAuth",
3571 "meth: %d ... is available: details: %s", cSec, out.Data());
3572 else
3573 ::Info("CheckProofAuth",
3574 "meth: %d ... is NOT available", cSec);
3575 }
3576
3577 // return
3578 return rc;
3579}
3580
3581////////////////////////////////////////////////////////////////////////////////
3582/// Standard version of CheckSecCtx to be passed to TAuthenticate::AuthExists
3583/// Check if User is matches the one in Ctx
3584/// Returns: 1 if ok, 0 if not
3585/// Deactivates Ctx is not valid
3586
3587Int_t StdCheckSecCtx(const char *user, TRootSecContext *ctx)
3588{
3589 Int_t rc = 0;
3590
3591 if (ctx->IsActive()) {
3592 if (!strcmp(user,ctx->GetUser()) &&
3593 strncmp("AFS", ctx->GetID(), 3))
3594 rc = 1;
3595 }
3596 return rc;
3597}
3598
3599////////////////////////////////////////////////////////////////////////////////
3600/// Tool for updating fgAuthInfo or fgProofAuthInfo
3601/// 'nin' contains list of last input information through (re)reading
3602/// of a rootauthrc-alike file. 'nin' info has priority.
3603/// 'std' is cleaned from inactive members.
3604/// 'nin' members used to update existing members in 'std' are
3605/// removed from 'nin', do that they do not leak
3606/// opt = "P" for proofauthinfo.
3607
3609{
3610 // Remove inactive from the 'std'
3611 TIter nxstd(std);
3612 THostAuth *ha;
3613 while ((ha = (THostAuth *) nxstd())) {
3614 if (!ha->IsActive()) {
3615 std->Remove(ha);
3616 SafeDelete(ha);
3617 }
3618 }
3619
3620 // Merge 'nin' info in 'std'
3621 TIter nxnew(nin);
3622 THostAuth *hanew;
3623 while ((hanew = (THostAuth *)nxnew())) {
3624 if (hanew->NumMethods()) {
3625 TString hostsrv;
3626 hostsrv.Form("%s:%d",hanew->GetHost(),hanew->GetServer());
3627 THostAuth *hastd =
3628 TAuthenticate::HasHostAuth(hostsrv,hanew->GetUser(),opt);
3629 if (hastd) {
3630 // Update with new info
3631 hastd->Update(hanew);
3632 // Flag for removal
3633 hanew->DeActivate();
3634 } else {
3635 // Add new ThostAuth to std
3636 std->Add(hanew);
3637 }
3638 } else
3639 // Flag for removal empty objects
3640 hanew->DeActivate();
3641 }
3642
3643 // Cleanup memory before quitting
3644 nxnew.Reset();
3645 while ((hanew = (THostAuth *)nxnew())) {
3646 if (!hanew->IsActive()) {
3647 nin->Remove(hanew);
3648 SafeDelete(hanew);
3649 }
3650 }
3651
3652}
3653
3654////////////////////////////////////////////////////////////////////////////////
3655/// Tool for removing SecContext ctx from THostAuth listed in
3656/// fgAuthInfo or fgProofAuthInfo
3657
3659{
3660 THostAuth *ha = 0;
3661
3662 // authinfo first
3663 TIter nxai(GetAuthInfo());
3664 while ((ha = (THostAuth *)nxai())) {
3665 TIter next(ha->Established());
3666 TRootSecContext *lctx = 0;
3667 while ((lctx = (TRootSecContext *) next())) {
3668 if (lctx == ctx) {
3669 ha->Established()->Remove(ctx);
3670 break;
3671 }
3672 }
3673 }
3674
3675 // proofauthinfo second
3676 TIter nxpa(GetProofAuthInfo());
3677 while ((ha = (THostAuth *)nxpa())) {
3678 TIter next(ha->Established());
3679 TRootSecContext *lctx = 0;
3680 while ((lctx = (TRootSecContext *) next())) {
3681 if (lctx == ctx) {
3682 ha->Established()->Remove(ctx);
3683 break;
3684 }
3685 }
3686 }
3687
3688}
3689
3690////////////////////////////////////////////////////////////////////////////////
3691/// Authentication related stuff setup in TProofServ.
3692/// This is the place where the buffer send by the client / master is
3693/// decoded. It contains also password information, if the case requires.
3694/// Return 0 on success, -1 on failure.
3695
3697{
3698 static Bool_t done = kFALSE;
3699
3700 // Only once
3701 if (done)
3702 return 0;
3703 done = kTRUE;
3704
3705 // Localise the buffer and decode it
3706 const char *p = gSystem->Getenv("ROOTPROOFAUTHSETUP");
3707 if (!p) {
3708 if (gDebug > 2)
3709 Info("ProofAuthSetup","Buffer not found: nothing to do");
3710 return 0;
3711 }
3712 TString mbuf = TBase64::Decode(p);
3713
3714 // Create the message
3715 TMessage *mess = new TMessage((void*)mbuf.Data(), mbuf.Length()+sizeof(UInt_t));
3716
3717 // Extract the information
3718 TString user = "";
3719 TString passwd = "";
3720 Bool_t pwhash = kFALSE;
3721 Bool_t srppwd = kFALSE;
3722 Int_t rsakey = -1;
3723 *mess >> user >> passwd >> pwhash >> srppwd >> rsakey;
3724
3725 // Set Globals for later use
3730 const char *h = gSystem->Getenv("ROOTHOMEAUTHRC");
3731 if (h) {
3732 Bool_t rha = (Bool_t)(strtol(h, (char **)0, 10));
3734 }
3735
3736 // Extract the list of THostAuth
3737 TList *pha = (TList *)mess->ReadObject(TList::Class());
3738 if (!pha) {
3739 if (gDebug > 0)
3740 Info("ProofAuthSetup","List of THostAuth not found");
3741 return 0;
3742 }
3743
3744 Bool_t master = gROOT->IsProofServ();
3745 TIter next(pha);
3746 THostAuth *ha = 0;
3747 while ((ha = (THostAuth *)next())) {
3748
3749 // Check if there is already one compatible
3750 Int_t kExact = 0;
3751 THostAuth *haex = 0;
3752 Bool_t fromProofAI = kFALSE;
3753 if (master) {
3754 // Look first in the proof list
3755 haex = TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"P",&kExact);
3756 // If nothing found, look also in the standard list
3757 if (!haex) {
3758 haex =
3759 TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"R",&kExact);
3760 } else
3761 fromProofAI = kTRUE;
3762 } else {
3763 // For slaves look first in the standard list only
3764 haex = TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"R",&kExact);
3765 }
3766
3767 if (haex) {
3768 // If yes, action depends on whether it matches exactly or not
3769 if (kExact == 1) {
3770 // Update info in authinfo if Slave or in proofauthinfo
3771 // if Master and the entry was already in proofauthinfo
3772 if (!master || fromProofAI) {
3773 // update this existing one with the information found in
3774 // in the new one, if needed
3775 haex->Update(ha);
3776 // Delete temporary THostAuth
3777 SafeDelete(ha);
3778 } else
3779 // Master, entry not already in proofauthinfo,
3780 // Add it to the list
3782 } else {
3783 // update this new one with the information found in
3784 // in the existing one (if needed) and ...
3785 Int_t i = 0;
3786 for (; i < haex->NumMethods(); i++) {
3787 Int_t met = haex->GetMethod(i);
3788 if (!ha->HasMethod(met))
3789 ha->AddMethod(met,haex->GetDetails(met));
3790 }
3791 if (master)
3792 // ... add the new one to the list
3794 else
3795 // We add this one to the standard list
3797 }
3798 } else {
3799 if (master)
3800 // We add this one to the list for forwarding
3802 else
3803 // We add this one to the standard list
3805 }
3806 }
3807
3808 // We are done
3809 return 0;
3810}
3811
3812////////////////////////////////////////////////////////////////////////////////
3813/// Setup of authetication related stuff in PROOF run after a
3814/// successful authentication.
3815/// Return 0 on success, -1 on failure.
3816
3818{
3819 // Fill some useful info
3820 TSecContext *sc = sock->GetSecContext();
3821 TString user = sc->GetUser();
3822 Int_t remoteOffSet = sc->GetOffSet();
3823
3824 // send user name to remote host
3825 // for UsrPwd method send also passwd, rsa encoded
3826 TMessage pubkey;
3827 TString passwd = "";
3828 Bool_t pwhash = kFALSE;
3829 Bool_t srppwd = kFALSE;
3830
3831 Bool_t upwd = sc->IsA("UsrPwd");
3832
3833 TPwdCtx *pwdctx = 0;
3834 if (remoteOffSet > -1 && upwd)
3835 pwdctx = (TPwdCtx *)(sc->GetContext());
3836
3837 if (upwd && pwdctx) {
3838 passwd = pwdctx->GetPasswd();
3839 pwhash = pwdctx->IsPwHash();
3840 }
3841
3842 Int_t keytyp = ((TRootSecContext *)sc)->GetRSAKey();
3843
3844 // Prepare buffer
3845 TMessage mess;
3846 mess << user << passwd << pwhash << srppwd << keytyp;
3847
3848 // Add THostAuth info
3850
3851 // Get buffer as a base 64 string
3852 char *mbuf = mess.Buffer();
3853 Int_t mlen = mess.Length();
3854 TString messb64 = TBase64::Encode(mbuf, mlen);
3855
3856 if (gDebug > 2)
3857 ::Info("ProofAuthSetup","sending %d bytes", messb64.Length());
3858
3859 // Send it over
3860 if (remoteOffSet > -1) {
3861 if (TAuthenticate::SecureSend(sock, 1, keytyp, messb64.Data()) == -1) {
3862 ::Error("ProofAuthSetup","problems secure-sending message buffer");
3863 return -1;
3864 }
3865 } else {
3866 // There is no encryption key: send it plain
3867 char buflen[20];
3868 snprintf(buflen,20, "%d", messb64.Length());
3869 if (sock->Send(buflen, kMESS_ANY) < 0) {
3870 ::Error("ProofAuthSetup","plain: problems sending message length");
3871 return -1;
3872 }
3873 if (sock->SendRaw(messb64.Data(), messb64.Length()) < 0) {
3874 ::Error("ProofAuthSetup","problems sending message buffer");
3875 return -1;
3876 }
3877 }
3878
3879 // We are done
3880 return 0;
3881}
3882
3883////////////////////////////////////////////////////////////////////////////////
3884/// Static method returning supported client protocol.
3885
3887{
3889}
3890
3891//
3892// The code below is needed by TSlave and TProofServ for backward
3893// compatibility.
3894//
3895
3896////////////////////////////////////////////////////////////////////////////////
3897/// Sends the list of the relevant THostAuth objects to the master or
3898/// to the active slaves, typically data servers external to the proof
3899/// cluster. The list is of THostAuth to be sent is specified by
3900/// TAuthenticate::fgProofAuthInfo after directives found in the
3901/// .rootauthrc family files ('proofserv' key)
3902/// Returns -1 if a problem sending THostAuth has occured, -2 in case
3903/// of problems closing the transmission.
3904
3906{
3907 Int_t retval = 0, ns = 0;
3908
3909 if (!s) {
3910 Error("SendHostAuth","invalid input: socket undefined");
3911 return -1;
3912 }
3913
3914
3916 THostAuth *ha;
3917 while ((ha = (THostAuth *)next())) {
3918 TString buf;
3919 ha->AsString(buf);
3920 if((ns = s->Send(buf, kPROOF_HOSTAUTH)) < 1) {
3921 retval = -1;
3922 break;
3923 }
3924 if (gDebug > 2)
3925 Info("SendHostAuth","sent %d bytes (%s)",ns,buf.Data());
3926 }
3927
3928 // End of transmission ...
3929 if ((ns = s->Send("END", kPROOF_HOSTAUTH)) < 1)
3930 retval = -2;
3931 if (gDebug > 2)
3932 Info("SendHostAuth","sent %d bytes for closing",ns);
3933
3934 return retval;
3935}
3936
3937////////////////////////////////////////////////////////////////////////////////
3938/// Receive from client/master directives for authentications, create
3939/// related THostAuth and add them to the TAuthenticate::ProofAuthInfo
3940/// list. Opt = "M" or "m" if Master, "S" or "s" if Proof slave.
3941/// The 'proofconf' file is read only if Master
3942
3944{
3945 if (!s) {
3946 Error("RecvHostAuth","invalid input: socket undefined");
3947 return -1;
3948 }
3949
3950 // Check if Master
3951 Bool_t master = !strncasecmp(opt,"M",1) ? kTRUE : kFALSE;
3952
3953 // First read directives from <rootauthrc>, <proofconf> and alike files
3955
3956 // Receive buffer
3957 Int_t kind;
3958 char buf[kMAXSECBUF];
3959 Int_t nr = s->Recv(buf, kMAXSECBUF, kind);
3960 if (nr < 0 || kind != kPROOF_HOSTAUTH) {
3961 Error("RecvHostAuth", "received: kind: %d (%d bytes)", kind, nr);
3962 return -1;
3963 }
3964 if (gDebug > 2)
3965 Info("RecvHostAuth","received %d bytes (%s)",nr,buf);
3966
3967 while (strcmp(buf, "END")) {
3968 // Clean buffer
3969 Int_t nc = (nr >= kMAXSECBUF) ? kMAXSECBUF - 1 : nr ;
3970 buf[nc] = '\0';
3971
3972 // Create THostAuth
3973 THostAuth *ha = new THostAuth((const char *)&buf);
3974
3975 // Check if there is already one compatible
3976 Int_t kExact = 0;
3977 THostAuth *haex = 0;
3978 Bool_t fromProofAI = kFALSE;
3979 if (master) {
3980 // Look first in the proof list
3981 haex = TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"P",&kExact);
3982 // If nothing found, look also in the standard list
3983 if (!haex) {
3984 haex =
3985 TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"R",&kExact);
3986 } else
3987 fromProofAI = kTRUE;
3988 } else {
3989 // For slaves look first in the standard list only
3990 haex = TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"R",&kExact);
3991 }
3992
3993 if (haex) {
3994 // If yes, action depends on whether it matches exactly or not
3995 if (kExact == 1) {
3996 // Update info in authinfo if Slave or in proofauthinfo
3997 // if master and the entry was already in proofauthinfo
3998 if (!master || fromProofAI) {
3999 // update this existing one with the information found in
4000 // in the new one, if needed
4001 haex->Update(ha);
4002 // Delete temporary THostAuth
4003 SafeDelete(ha);
4004 } else
4005 // master, entry not already in proofauthinfo,
4006 // Add it to the list
4008 } else {
4009 // update this new one with the information found in
4010 // in the existing one (if needed) and ...
4011 Int_t i = 0;
4012 for (; i < haex->NumMethods(); i++) {
4013 Int_t met = haex->GetMethod(i);
4014 if (!ha->HasMethod(met))
4015 ha->AddMethod(met,haex->GetDetails(met));
4016 }
4017 if (master)
4018 // ... add the new one to the list
4020 else
4021 // We add this one to the standard list
4023 }
4024 } else {
4025 if (master)
4026 // We add this one to the list for forwarding
4028 else
4029 // We add this one to the standard list
4031 }
4032
4033
4034 // Get the next one
4035 nr = s->Recv(buf, kMAXSECBUF, kind);
4036 if (nr < 0 || kind != kPROOF_HOSTAUTH) {
4037 Info("RecvHostAuth","Error: received: kind: %d (%d bytes)", kind, nr);
4038 return -1;
4039 }
4040 if (gDebug > 2)
4041 Info("RecvHostAuth","received %d bytes (%s)",nr,buf);
4042 }
4043
4044 return 0;
4045}
4046
4047extern "C" {
4048
4049////////////////////////////////////////////////////////////////////////////////
4050/// Setup of authetication in PROOF run after successful opening
4051/// of the socket. Provided for backward compatibility.
4052/// Return 0 on success, -1 on failure.
4053
4055 Bool_t /* master */, TString ord, TString conf)
4056{
4057
4058 // Fill some useful info
4059 TSecContext *sc = sock->GetSecContext();
4060 TString user = sc->GetUser();
4061 Int_t proofdProto = sock->GetRemoteProtocol();
4062 Int_t remoteOffSet = sc->GetOffSet();
4063
4064 // send user name to remote host
4065 // for UsrPwd method send also passwd, rsa encoded
4066 TMessage pubkey;
4067 TString passwd = "";
4068 Bool_t pwhash = kFALSE;
4069 Bool_t srppwd = kFALSE;
4070
4071 Bool_t upwd = sc->IsA("UsrPwd");
4072
4073 TPwdCtx *pwdctx = 0;
4074 if (remoteOffSet > -1 && upwd)
4075 pwdctx = (TPwdCtx *)(sc->GetContext());
4076
4077 if (upwd && pwdctx) {
4078
4079 // Send offset to identify remotely the public part of RSA key
4080 if (sock->Send(remoteOffSet, kROOTD_RSAKEY) != 2*sizeof(Int_t)) {
4081 Error("OldAuthSetup", "failed to send offset in RSA key");
4082 return -1;
4083 }
4084
4085 if (pwdctx) {
4086 passwd = pwdctx->GetPasswd();
4087 pwhash = pwdctx->IsPwHash();
4088 }
4089
4090 Int_t keytyp = ((TRootSecContext *)sc)->GetRSAKey();
4091 if (TAuthenticate::SecureSend(sock, 1, keytyp, passwd.Data()) == -1) {
4092 if (remoteOffSet > -1)
4093 Warning("OldAuthSetup","problems secure-sending pass hash %s",
4094 "- may result in failures");
4095 // If non RSA encoding available try passwd inversion
4096 if (upwd) {
4097 for (int i = 0; i < passwd.Length(); i++) {
4098 char inv = ~passwd(i);
4099 passwd.Replace(i, 1, inv);
4100 }
4101 TMessage mess;
4102 mess << passwd;
4103 if (sock->Send(mess) < 0) {
4104 Error("OldAuthSetup", "failed to send inverted password");
4105 return -1;
4106 }
4107 }
4108 }
4109
4110 } else {
4111
4112 // Send notification of no offset to be sent ...
4113 if (sock->Send(-2, kROOTD_RSAKEY) != 2*sizeof(Int_t)) {
4114 Error("OldAuthSetup", "failed to send no offset notification in RSA key");
4115 return -1;
4116 }
4117 }
4118
4119 // Send ordinal (and config) info to slave (or master)
4120 TMessage mess;
4121 mess << user << pwhash << srppwd << ord << conf;
4122
4123 if (sock->Send(mess) < 0) {
4124 Error("OldAuthSetup", "failed to send ordinal and config info");
4125 return -1;
4126 }
4127
4128 if (proofdProto > 6) {
4129 // Now we send authentication details to access, e.g., data servers
4130 // not in the proof cluster and to be propagated to slaves.
4131 // This is triggered by the 'proofserv <dserv1> <dserv2> ...'
4132 // line in .rootauthrc
4133 if (SendHostAuth(sock) < 0) {
4134 Error("OldAuthSetup", "failed to send HostAuth info");
4135 return -1;
4136 }
4137 }
4138
4139 // We are done
4140 return 0;
4141}
4142
4143////////////////////////////////////////////////////////////////////////////////
4144/// Authentication related setup in TProofServ run after successful
4145/// startup. Provided for backward compatibility.
4146/// Return 0 on success, -1 on failure.
4147
4149 TString &user, TString &ord, TString &conf)
4150{
4151 // First receive, decode and store the public part of RSA key
4152 Int_t retval, kind;
4153 if (sock->Recv(retval, kind) != 2*sizeof(Int_t)) {
4154 //other side has closed connection
4155 Info("OldProofServAuthSetup",
4156 "socket has been closed due to protocol mismatch - Exiting");
4157 return -1;
4158 }
4159
4160 Int_t rsakey = 0;
4162 if (kind == kROOTD_RSAKEY) {
4163
4164 if (retval > -1) {
4165 if (gSystem->Getenv("ROOTKEYFILE")) {
4166
4167 TString keyfile = gSystem->Getenv("ROOTKEYFILE");
4168 keyfile += retval;
4169
4170 FILE *fKey = 0;
4171 char pubkey[kMAXPATHLEN] = { 0 };
4172 if (!gSystem->AccessPathName(keyfile.Data(), kReadPermission)) {
4173 if ((fKey = fopen(keyfile.Data(), "r"))) {
4174 Int_t klen = fread((void *)pubkey,1,sizeof(pubkey),fKey);
4175 if (klen <= 0) {
4176 Error("OldProofServAuthSetup",
4177 "failed to read public key from '%s'", keyfile.Data());
4178 fclose(fKey);
4179 return -1;
4180 }
4181 pubkey[klen] = 0;
4182 // Set RSA key
4183 rsakey = TAuthenticate::SetRSAPublic(pubkey,klen);
4184 fclose(fKey);
4185 } else {
4186 Error("OldProofServAuthSetup", "failed to open '%s'", keyfile.Data());
4187 return -1;
4188 }
4189 }
4190 }
4191
4192 // Receive passwd
4193 char *pwd = 0;
4194 if (TAuthenticate::SecureRecv(sock, 2, rsakey, &pwd) < 0) {
4195 Error("OldProofServAuthSetup", "failed to receive password");
4196 return -1;
4197 }
4198 passwd = pwd;
4199 delete[] pwd;
4200
4201 } else if (retval == -1) {
4202
4203 // Receive inverted passwd
4204 TMessage *mess;
4205 if ((sock->Recv(mess) <= 0) || !mess) {
4206 Error("OldProofServAuthSetup", "failed to receive inverted password");
4207 return -1;
4208 }
4209 (*mess) >> passwd;
4210 delete mess;
4211
4212 for (Int_t i = 0; i < passwd.Length(); i++) {
4213 char inv = ~passwd(i);
4214 passwd.Replace(i, 1, inv);
4215 }
4216
4217 }
4218 }
4219
4220 // Receive final information
4221 TMessage *mess;
4222 if ((sock->Recv(mess) <= 0) || !mess) {
4223 Error("OldProofServAuthSetup", "failed to receive ordinal and config info");
4224 return -1;
4225 }
4226
4227 // Decode it
4228 Bool_t pwhash, srppwd;
4229 if (master) {
4230 if (protocol < 4) {
4231 (*mess) >> user >> pwhash >> srppwd >> conf;
4232 ord = "0";
4233 } else {
4234 (*mess) >> user >> pwhash >> srppwd >> ord >> conf;
4235 }
4236 } else {
4237 if (protocol < 4) {
4238 Int_t iord;
4239 (*mess) >> user >> pwhash >> srppwd >> iord;
4240 ord = "0.";
4241 ord += iord;
4242 } else {
4243 (*mess) >> user >> pwhash >> srppwd >> ord >> conf;
4244 }
4245 }
4246 delete mess;
4247
4248 // Set Globals for later use
4253 const char *h = gSystem->Getenv("ROOTHOMEAUTHRC");
4254 if (h) {
4255 Bool_t rha = (Bool_t)(strtol(h, (char **)0, 10));
4257 }
4258
4259 // Read user or system authentication directives and
4260 // receive auth info transmitted from the client
4261 Int_t harc = master ? RecvHostAuth(sock, "M") : RecvHostAuth(sock, "S");
4262
4263 if (harc < 0) {
4264 Error("OldProofServAuthSetup", "failed to receive HostAuth info");
4265 return -1;
4266 }
4267
4268 // We are done
4269 return 0;
4270}
4271
4272} // 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
@ kROOTD_RSAKEY
@ kROOTD_ENCRYPT
@ kROOTD_PASS
@ kMESS_STRING
@ kMESS_ANY
@ kROOTD_USER
@ kROOTD_BYE
@ kROOTD_NEGOTIA
@ kROOTD_AUTH
@ kPROOF_HOSTAUTH
@ kROOTD_ERR
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:547
#define c(i)
Definition RSha256.hxx:101
#define h(i)
Definition RSha256.hxx:106
const Ssiz_t kNPOS
Definition RtypesCore.h:115
int Int_t
Definition RtypesCore.h:45
const Bool_t kFALSE
Definition RtypesCore.h:92
long Long_t
Definition RtypesCore.h:54
bool Bool_t
Definition RtypesCore.h:63
const Bool_t kTRUE
Definition RtypesCore.h:91
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:364
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 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...
Int_t OldSlaveAuthSetup(TSocket *sock, Bool_t, TString ord, TString conf)
Setup of authetication in PROOF run after successful opening of the socket.
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
R__EXTERN TVirtualMutex * gAuthenticateMutex
Int_t(* Krb5Auth_t)(TAuthenticate *auth, TString &user, TString &det, Int_t version)
Int_t(* SecureAuth_t)(TAuthenticate *auth, const char *user, const char *passwd, const char *remote, TString &det, Int_t version)
Int_t(* GlobusAuth_t)(TAuthenticate *auth, TString &user, TString &det)
Int_t(* CheckSecCtx_t)(const char *subj, TRootSecContext *ctx)
R__EXTERN TEnv * gEnv
Definition TEnv.h:171
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:220
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:187
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:231
char name[80]
Definition TGX11.cxx:110
Int_t gDebug
Definition TROOT.cxx:590
#define gROOT
Definition TROOT.h:406
char * Form(const char *fmt,...)
void Printf(const char *fmt,...)
char * StrDup(const char *str)
Duplicate the string str.
Definition TString.cxx:2510
typedef void((*Func_t)())
@ kReadPermission
Definition TSystem.h:47
Bool_t R_ISREG(Int_t mode)
Definition TSystem.h:118
Bool_t R_ISDIR(Int_t mode)
Definition TSystem.h:115
R__EXTERN TSystem * gSystem
Definition TSystem.h:559
@ kS_IWUSR
Definition TSystem.h:103
@ kS_IRUSR
Definition TSystem.h:102
#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
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
static Bool_t fgPwHash
ESecurity fSecurity
THostAuth * fHostAuth
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
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)
RFIO authentication (no longer supported)
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 (no longer supported)
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 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 (no longer supported)
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 const char * GetRSAPubExport(Int_t key=0)
Static method returning the RSA public keys.
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
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
TString fProtocol
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
static TString fgPasswd
static TString fgAuthMeth[kMAXSEC]
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.
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 (no longer supported)
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 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
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
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...
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:131
static TString Encode(const char *data)
Transform data into a null terminated base64 string.
Definition TBase64.cxx:107
TObject * ReadObject(const TClass *cl) override
Read object from I/O buffer.
void WriteObject(const TObject *obj, Bool_t cacheReuse=kTRUE) override
Write object to I/O buffer.
Int_t Length() const
Definition TBuffer.h:100
char * Buffer() const
Definition TBuffer.h:96
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
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:289
UInt_t Convert(Bool_t toGMT=kFALSE) const
Convert fDatime from TDatime format to the standard time_t format.
Definition TDatime.cxx:182
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...
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.
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 ...).
virtual void Print(Option_t *option="") const
Print object content.
void SetServer(Int_t server)
Definition THostAuth.h:97
void ReOrder(Int_t nmet, Int_t *fmet)
Reorder nmet methods according fmet[nmet].
void RemoveMethod(Int_t level)
Remove method 'meth' from the list, if there ...
void DeActivate()
Definition THostAuth.h:84
void AddMethod(Int_t level, const char *details=0)
Add method to the list.
void CountFailure(Int_t level)
Count failures for 'method'.
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.
Bool_t HasMethod(Int_t level, Int_t *pos=0)
Return kTRUE if method 'level' is in the list.
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...
void Update(THostAuth *ha)
Update info with the one in ha Remaining methods, if any, get lower priority.
const char * GetDetails(Int_t level)
Return authentication details for specified level or "" if the specified level does not exist for thi...
void SetLast(Int_t level)
Set 'method' to be the last used (if in the list ...).
void PrintEstablished() const
Print info about established authentication vis-a-vis of this Host.
void CountSuccess(Int_t level)
Count successes for 'method'.
This class represents an Internet Protocol (IP) address.
const char * GetHostName() const
Bool_t IsValid() const
const char * GetHostAddress() const
Returns the IP address string "%d.%d.%d.%d".
void Reset()
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:822
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:879
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:893
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:867
Long_t ExecPlugin(int nargs, const T &... params)
Int_t LoadPlugin()
Load the plugin library for this handler.
Bool_t IsPwHash() const
const char * GetPasswd() const
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:866
static const TString & GetEtcDir()
Get the sysconfig directory in the installation. Static utility function.
Definition TROOT.cxx:2969
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 Opt contains "C" or "c",...
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:818
static Int_t GetClientProtocol()
Static method returning supported client protocol.
Definition TSocket.cxx:1469
Int_t GetRemoteProtocol() const
Definition TSocket.h:126
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:898
TSecContext * GetSecContext() const
Definition TSocket.h:127
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:52
@ kROOTD
Definition TSocket.h:52
@ kPROOFD
Definition TSocket.h:52
Int_t GetPort() const
Definition TSocket.h:115
Int_t GetServType() const
Definition TSocket.h:117
virtual Int_t Send(const TMessage &mess)
Send a TMessage object.
Definition TSocket.cxx:522
Basic string class.
Definition TString.h:136
Ssiz_t Length() const
Definition TString.h:410
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition TString.cxx:2197
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition TString.h:682
const char * Data() const
Definition TString.h:369
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:692
void Resize(Ssiz_t n)
Resize the string. Truncate or add blanks as necessary.
Definition TString.cxx:1115
@ kIgnoreCase
Definition TString.h:268
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:615
Bool_t IsNull() const
Definition TString.h:407
TString & Remove(Ssiz_t pos)
Definition TString.h:673
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:2331
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2309
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:624
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:639
virtual int GetPid()
Get process id.
Definition TSystem.cxx:708
virtual const char * Getenv(const char *env)
Get environment variable.
Definition TSystem.cxx:1661
virtual char * ConcatFileName(const char *dir, const char *name)
Concatenate a directory and a file name. User must delete returned string.
Definition TSystem.cxx:1069
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition TSystem.cxx:1853
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:1396
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:1294
virtual FILE * TempFileName(TString &base, const char *dir=nullptr)
Create a secure temporary file by appending a unique 6 letter string to base.
Definition TSystem.cxx:1495
virtual void DispatchOneEvent(Bool_t pendingOnly=kFALSE)
Dispatch a single event.
Definition TSystem.cxx:430
virtual const char * HostName()
Return the system's host name.
Definition TSystem.cxx:304
virtual Int_t GetEffectiveUid()
Returns the effective user id.
Definition TSystem.cxx:1568
virtual TInetAddress GetHostByName(const char *server)
Get Internet Protocol (IP) address of host.
Definition TSystem.cxx:2295
virtual const char * HomeDirectory(const char *userName=nullptr)
Return the user's home directory.
Definition TSystem.cxx:886
virtual int Unlink(const char *name)
Unlink, i.e.
Definition TSystem.cxx:1379
virtual UserGroup_t * GetUserInfo(Int_t uid)
Returns all user info in the UserGroup_t structure.
Definition TSystem.cxx:1597
char * DynamicPathName(const char *lib, Bool_t quiet=kFALSE)
Find a dynamic library called lib using the system search paths.
Definition TSystem.cxx:2016
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.
TPaveText * pt
TLine * line
Definition first.py:1
Definition test.py:1
#define kMAXPATHLEN
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:127
TString fUser
Definition TSystem.h:141
auto * m
Definition textangle.C:8
auto * l
Definition textangle.C:4
auto * t1
Definition textangle.C:20