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