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
43#include "rsafun.h"
44
45#ifndef R__LYNXOS
46#include <sys/stat.h>
47#endif
48#include <errno.h>
49#include <sys/types.h>
50#include <time.h>
51#if !defined(R__WIN32) && !defined(R__MACOSX) && !defined(R__FBSD) && \
52 !defined(R__OBSD)
53#include <crypt.h>
54#endif
55#ifdef WIN32
56# include <io.h>
57#endif /* WIN32 */
58#if defined(R__LINUX) || defined(R__FBSD) || defined(R__OBSD)
59# include <unistd.h>
60#endif
61#include <stdlib.h>
62#ifndef WIN32
63# include <sys/time.h>
64#endif /* WIN32 */
65
66#if defined(R__MACOSX)
67extern "C" char *crypt(const char *, const char *);
68#endif
69
70#ifdef R__SSL
71// SSL specific headers
72# include <openssl/bio.h>
73# include <openssl/err.h>
74# include <openssl/pem.h>
75# include <openssl/rand.h>
76# include <openssl/rsa.h>
77# include <openssl/ssl.h>
78# include <openssl/blowfish.h>
79#endif
80
81struct R__rsa_KEY: rsa_KEY { R__rsa_KEY(): rsa_KEY() {} };
82struct R__rsa_KEY_export: rsa_KEY_export {};
83struct R__rsa_NUMBER: rsa_NUMBER {};
84
85#ifdef R__SSL
86 static BF_KEY fgBFKey; // Blowfish symmetric key
87#endif
88
89// Statics initialization
91TString TAuthenticate::fgAuthMeth[] = { "UsrPwd", "Unsupported", "Unsupported",
92 "Unsupported", "Unsupported", "Unsupported" };
96TDatime TAuthenticate::fgLastAuthrc; // Time of last reading of fgRootAuthrc
102Bool_t TAuthenticate::fgReadHomeAuthrc = kTRUE; // on/off search for $HOME/.rootauthrc
103TString TAuthenticate::fgRootAuthrc; // Path to last rootauthrc-like file read
104Int_t TAuthenticate::fgRSAKey = -1; // Default RSA key type to be used
107R__rsa_KEY_export R__fgRSAPubExport[2] = {{}, {}};
114Int_t TAuthenticate::fgAuthTO = -2; // Timeout value
115
116// ID of the main thread as unique identifier
118
120
121// Standard version of Sec Context match checking
122Int_t StdCheckSecCtx(const char *, TRootSecContext *);
123
124
126
127////////////////////////////////////////////////////////////////////////////////
128/// rand() implementation using /udev/random or /dev/random, if available
129
130static int auth_rand()
131{
132#ifndef WIN32
133 int frnd = open("/dev/urandom", O_RDONLY);
134 if (frnd < 0) frnd = open("/dev/random", O_RDONLY);
135 int r;
136 if (frnd >= 0) {
137 ssize_t rs = read(frnd, (void *) &r, sizeof(int));
138 close(frnd);
139 if (r < 0) r = -r;
140 if (rs == sizeof(int)) return r;
141 }
142 Printf("+++ERROR+++ : auth_rand: neither /dev/urandom nor /dev/random are available or readable!");
143 struct timeval tv;
144 if (gettimeofday(&tv,0) == 0) {
145 int t1, t2;
146 memcpy((void *)&t1, (void *)&tv.tv_sec, sizeof(int));
147 memcpy((void *)&t2, (void *)&tv.tv_usec, sizeof(int));
148 r = t1 + t2;
149 if (r < 0) r = -r;
150 return r;
151 }
152 return -1;
153#else
154 // No special random device available: use rand()
155 return rand();
156#endif
157}
158
159////////////////////////////////////////////////////////////////////////////////
160/// Create authentication object.
161
162TAuthenticate::TAuthenticate(TSocket *sock, const char *remote,
163 const char *proto, const char *user)
164{
165 if (gDebug > 2 && gAuthenticateMutex)
166 Info("Authenticate", "locking mutex (pid: %d)",gSystem->GetPid());
168
169 // In PROOF decode the buffer sent by the client, if any
170 if (gROOT->IsProofServ())
172
173 // Use the ID of the starting thread as unique identifier
174 if (fgProcessID < 0)
176
177 if (fgAuthTO == -2)
178 fgAuthTO = gEnv->GetValue("Auth.Timeout",-1);
179
180 fSocket = sock;
181 fRemote = remote;
182 fHostAuth = 0;
183 fVersion = 5; // The latest, by default
184 fSecContext = 0;
185
186 if (gDebug > 2)
187 Info("TAuthenticate", "Enter: local host: %s, user is: %s (proto: %s)",
188 gSystem->HostName(), user, proto);
189
190 // Set protocol string.
191 // Check if version should be different ...
192 char *pdd;
193 Int_t servtype = TSocket::kSOCKD;
194 if (proto && strlen(proto) > 0) {
195 char *sproto = StrDup(proto);
196 if ((pdd = strstr(sproto, ":")) != 0) {
197 int rproto = atoi(pdd + 1);
198 *pdd = '\0';
199 if (strstr(sproto, "root") != 0) {
200 if (rproto < 12 ) {
201 fVersion = 4;
202 if (rproto < 11 ) {
203 fVersion = 3;
204 if (rproto < 9 ) {
205 fVersion = 2;
206 if (rproto < 8) {
207 fVersion = 1;
208 if (rproto < 6)
209 fVersion = 0;
210 }
211 }
212 }
213 }
214 servtype = TSocket::kROOTD;
215 }
216 if (strstr(sproto, "proof") != 0) {
217 if (rproto < 11) {
218 fVersion = 4;
219 if (rproto < 10) {
220 fVersion = 3;
221 if (rproto < 8) {
222 fVersion = 2;
223 if (rproto < 7)
224 fVersion = 1;
225 }
226 }
227 }
228 servtype = TSocket::kPROOFD;
229 }
230 if (gDebug > 3)
231 Info("TAuthenticate",
232 "service: %s (remote protocol: %d): fVersion: %d", sproto,
233 rproto, fVersion);
234 }
235 fProtocol = sproto;
236 delete [] sproto;
237 }
238
239 // Check or get user name
240 fUser = "";
241 TString checkUser;
242 if (user && strlen(user) > 0) {
243 fUser = user;
244 checkUser = user;
245 } else {
247 if (u)
248 checkUser = u->fUser;
249 delete u;
250 }
251 fPasswd = "";
252 fPwHash = kFALSE;
253
254 // Type of RSA key
255 if (fgRSAKey < 0) {
256 fgRSAKey = 0; // Default key
257#ifdef R__SSL
258 // Another choice possible: check user preferences
259 if (gEnv->GetValue("RSA.KeyType",0) == 1)
260 fgRSAKey = 1;
261#endif
262 }
263 // This is the key actually used: we propose the default
264 // to the server, and behave according to its reply
266 if (gDebug > 3)
267 Info("TAuthenticate","RSA key: default type %d", fgRSAKey);
268
269 // RSA key generation (one per session)
270 if (!fgRSAInit) {
271 GenRSAKeys();
272 fgRSAInit = 1;
273 }
274
275 // Check and save the host FQDN ...
276 TString fqdn;
278 if (addr.IsValid())
279 fqdn = addr.GetHostName();
280 TString fqdnsrv;
281 fqdnsrv.Form("%s:%d",fqdn.Data(),servtype);
282
283 // Read directives from files; re-read if files have changed
285
286 if (gDebug > 3) {
287 Info("TAuthenticate",
288 "number of HostAuth Instantiations in memory: %d",
289 GetAuthInfo()->GetSize());
292 }
293
294 // Check the list of auth info for already loaded info about this host
295 fHostAuth = GetHostAuth(fqdnsrv, checkUser);
296
297 //
298 // If generic THostAuth (i.e. with wild card or user == any)
299 // make a personalized memory copy of this THostAuth
300 if (strchr(fHostAuth->GetHost(),'*') || strchr(fHostAuth->GetHost(),'*') ||
301 fHostAuth->GetServer() == -1 ) {
303 fHostAuth->SetHost(fqdn);
304 fHostAuth->SetUser(checkUser);
305 fHostAuth->SetServer(servtype);
306 }
307
308 // If a specific method has been requested via the protocol
309 // set it as first
310 Int_t sec = -1;
311 TString tmp = fProtocol;
312 tmp.ReplaceAll("root",4,"",0);
313 tmp.ReplaceAll("proof",5,"",0);
314 tmp.ReplaceAll("sock",4,"",0);
315 if (!strncmp(tmp.Data(),"up",2))
316 sec = 0;
317 else if (!strncmp(tmp.Data(),"s",1))
318 sec = 1;
319 else if (!strncmp(tmp.Data(),"k",1))
320 sec = 2;
321 else if (!strncmp(tmp.Data(),"g",1))
322 sec = 3;
323 else if (!strncmp(tmp.Data(),"h",1))
324 sec = 4;
325 else if (!strncmp(tmp.Data(),"ug",2))
326 sec = 5;
327 if (sec > -1 && sec < kMAXSEC) {
328 if (fHostAuth->HasMethod(sec)) {
329 fHostAuth->SetFirst(sec);
330 } else {
331 char *dtmp = GetDefaultDetails(sec, 1, checkUser);
332 TString det(dtmp);
333 fHostAuth->AddFirst(sec, det);
334 if (dtmp)
335 delete [] dtmp;
336 }
337 }
338
339 // This is what we have in memory
340 if (gDebug > 3) {
341 TIter next(fHostAuth->Established());
342 TRootSecContext *ctx;
343 while ((ctx = (TRootSecContext *) next()))
344 ctx->Print("0");
345 }
346}
347
348////////////////////////////////////////////////////////////////////////////////
349/// Called in connection with a timer timeout
350
352{
353 Info("CatchTimeOut", "%d sec timeout expired (protocol: %s)",
354 fgAuthTO, fgAuthMeth[fSecurity].Data());
355
356 fTimeOut = 1;
357 if (fSocket)
358 fSocket->Close("force");
359
360 return;
361}
362
363////////////////////////////////////////////////////////////////////////////////
364/// Authenticate to remote rootd or proofd server. Return kTRUE if
365/// authentication succeeded.
366
368{
369 if (gDebug > 2 && gAuthenticateMutex)
370 Info("Authenticate", "locking mutex (pid: %d)",gSystem->GetPid());
372
373 Bool_t rc = kFALSE;
374 Int_t st = -1;
375 Int_t remMeth = 0, rMth[kMAXSEC], tMth[kMAXSEC] = {0};
376 Int_t meth = 0;
377 char noSupport[80] = { 0 };
378 char triedMeth[80] = { 0 };
379 Int_t ntry = 0;
380
381 TString user, passwd;
382 Bool_t pwhash;
383
384 if (gDebug > 2)
385 Info("Authenticate", "enter: fUser: %s", fUser.Data());
386
387 //
388 // Setup timeout timer, if required
389 TTimer *alarm = 0;
390 if (fgAuthTO > 0) {
391 alarm = new TTimer(0, kFALSE);
392 alarm->SetInterruptSyscalls();
393 // The method CatchTimeOut will be called at timeout
394 alarm->Connect("Timeout()", "TAuthenticate", this, "CatchTimeOut()");
395 }
396
397negotia:
398 st = -1;
399 tMth[meth] = 1;
400 ntry++;
401 if (gDebug > 2)
402 Info("Authenticate", "try #: %d", ntry);
403
404 user = "";
405 passwd = "";
406 pwhash = kFALSE;
407
408 // Security level from the list (if not in cleanup mode ...)
411 if (gDebug > 2)
412 Info("Authenticate",
413 "trying authentication: method:%d, default details:%s",
415
416 // Keep track of tried methods in a list
417 if (triedMeth[0] != '\0')
418 (void) strlcat(triedMeth, " ", sizeof(triedMeth) - 1);
419
420 (void) strlcat(triedMeth, fgAuthMeth[fSecurity].Data(), sizeof(triedMeth) - 1);
421
422 // Set environments
424
425 st = -1;
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) {
991 net = gSystem->ConcatFileName(gSystem->HomeDirectory(), ".netrc");
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);
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 needsalt = 0;
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 delete [] tmpsalt;
1645 }
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%lx", fexp, (Long_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 ...
2534
2535 // ... and its 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
2693 TRSA_fun::RSA_assign()(&fgRSAPriKey.n, &rsa_n);
2694 TRSA_fun::RSA_assign()(&fgRSAPriKey.e, &rsa_e);
2695
2696 // Save Public key
2697 TRSA_fun::RSA_assign()(&fgRSAPubKey.n, &rsa_n);
2698 TRSA_fun::RSA_assign()(&fgRSAPubKey.e, &rsa_d);
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)
2893 TRSA_fun::RSA_decode()(buftmp, len, fgRSAPriKey.n, fgRSAPriKey.e);
2894 else if (dec == 2)
2895 TRSA_fun::RSA_decode()(buftmp, len, fgRSAPubKey.n, fgRSAPubKey.e);
2896 else
2897 return -1;
2898
2899 // Prepare output
2900 const size_t strSize = strlen(buftmp) + 1;
2901 *str = new char[strSize];
2902 strlcpy(*str, buftmp, strSize);
2903
2904 } else if (key == 1) {
2905#ifdef R__SSL
2906 unsigned char iv[8];
2907 memset((void *)&iv[0],0,8);
2908 *str = new char[nrec + 1];
2909 BF_cbc_encrypt((const unsigned char *)buftmp, (unsigned char *)(*str),
2910 nrec, &fgBFKey, iv, BF_DECRYPT);
2911 (*str)[nrec] = '\0';
2912#else
2913 if (gDebug > 0)
2914 ::Info("TAuthenticate::SecureRecv","not compiled with SSL support:"
2915 " you should not have got here!");
2916#endif
2917 } else {
2918 if (gDebug > 0)
2919 ::Info("TAuthenticate::SecureRecv","unknown key type (%d)",key);
2920 return -1;
2921 }
2922
2923 nrec= strlen(*str);
2924
2925 return nrec;
2926}
2927
2928////////////////////////////////////////////////////////////////////////////////
2929/// Store RSA public keys from export string rsaPubExport.
2930
2931Int_t TAuthenticate::DecodeRSAPublic(const char *rsaPubExport, R__rsa_NUMBER &rsa_n,
2932 R__rsa_NUMBER &rsa_d, char **rsassl)
2933{
2934 if (!rsaPubExport)
2935 return -1;
2936
2937 if (gDebug > 2)
2938 ::Info("TAuthenticate::DecodeRSAPublic",
2939 "enter: string length: %ld bytes", (Long_t)strlen(rsaPubExport));
2940
2941 char str[kMAXPATHLEN] = { 0 };
2942 Int_t klen = strlen(rsaPubExport);
2943 if (klen > kMAXPATHLEN - 1) {
2944 ::Info("TAuthenticate::DecodeRSAPublic",
2945 "key too long (%d): truncate to %d",klen,kMAXPATHLEN);
2946 klen = kMAXPATHLEN - 1;
2947 }
2948 memcpy(str, rsaPubExport, klen);
2949 str[klen] ='\0';
2950
2951 Int_t keytype = -1;
2952
2953 if (klen > 0) {
2954
2955 // Skip spaces at beginning, if any
2956 int k = 0;
2957 while (str[k] == 32) k++;
2958
2959 if (str[k] == '#') {
2960
2961 keytype = 0;
2962
2963 // The format is #<hex_n>#<hex_d>#
2964 char *pd1 = strstr(str, "#");
2965 char *pd2 = pd1 ? strstr(pd1 + 1, "#") : (char *)0;
2966 char *pd3 = pd2 ? strstr(pd2 + 1, "#") : (char *)0;
2967 if (pd1 && pd2 && pd3) {
2968 // Get <hex_n> ...
2969 int l1 = (int) (pd2 - pd1 - 1);
2970 char *rsa_n_exp = new char[l1 + 1];
2971 strlcpy(rsa_n_exp, pd1 + 1, l1+1);
2972 if (gDebug > 2)
2973 ::Info("TAuthenticate::DecodeRSAPublic",
2974 "got %ld bytes for rsa_n_exp", (Long_t)strlen(rsa_n_exp));
2975 // Now <hex_d>
2976 int l2 = (int) (pd3 - pd2 - 1);
2977 char *rsa_d_exp = new char[l2 + 1];
2978 strlcpy(rsa_d_exp, pd2 + 1, 13);
2979 if (gDebug > 2)
2980 ::Info("TAuthenticate::DecodeRSAPublic",
2981 "got %ld bytes for rsa_d_exp", (Long_t)strlen(rsa_d_exp));
2982
2983 TRSA_fun::RSA_num_sget()(&rsa_n, rsa_n_exp);
2984 TRSA_fun::RSA_num_sget()(&rsa_d, rsa_d_exp);
2985
2986 delete[] rsa_n_exp;
2987 delete[] rsa_d_exp;
2988
2989 } else
2990 ::Info("TAuthenticate::DecodeRSAPublic","bad format for input string");
2991#ifdef R__SSL
2992 } else {
2993 // try SSL
2994 keytype = 1;
2995
2996 RSA *rsatmp;
2997
2998 // Bio for exporting the pub key
2999 BIO *bpub = BIO_new(BIO_s_mem());
3000
3001 // Write key from kbuf to BIO
3002 BIO_write(bpub,(void *)str,strlen(str));
3003
3004 // Read pub key from BIO
3005 if (!(rsatmp = PEM_read_bio_RSAPublicKey(bpub, 0, 0, 0))) {
3006 if (gDebug > 0)
3007 ::Info("TAuthenticate::DecodeRSAPublic",
3008 "unable to read pub key from bio");
3009 } else
3010 if (rsassl)
3011 *rsassl = (char *)rsatmp;
3012 else
3013 ::Info("TAuthenticate::DecodeRSAPublic",
3014 "no space allocated for output variable");
3015 BIO_free(bpub);
3016 }
3017#else
3018 } else {
3019 if (rsassl) { } // To avoid compiler complains
3020 if (gDebug > 0)
3021 ::Info("TAuthenticate::DecodeRSAPublic","not compiled with SSL support:"
3022 " you should not have got here!");
3023 }
3024#endif
3025 }
3026
3027 return keytype;
3028}
3029
3030////////////////////////////////////////////////////////////////////////////////
3031/// Store RSA public keys from export string rsaPubExport.
3032/// Returns type of stored key, or -1 is not recognized
3033
3034Int_t TAuthenticate::SetRSAPublic(const char *rsaPubExport, Int_t klen)
3035{
3036 if (gDebug > 2)
3037 ::Info("TAuthenticate::SetRSAPublic",
3038 "enter: string length %ld bytes", (Long_t)strlen(rsaPubExport));
3039
3040 Int_t rsakey = -1;
3041 if (!rsaPubExport)
3042 return rsakey;
3043
3044 if (klen > 0) {
3045
3046 // Skip spaces at beginning, if any
3047 int k0 = 0;
3048 while (rsaPubExport[k0] == 32) k0++;
3049 int k2 = klen - 1;
3050
3051 // Parse rsaPubExport
3052 // Type 0 is in the form
3053 //
3054 // #< gt 10 exa chars >#< gt 10 exa chars >#
3055 //
3056 rsakey = 1;
3057 if (rsaPubExport[k0] == '#' && rsaPubExport[k2] == '#') {
3058 char *p0 = (char *)&rsaPubExport[k0];
3059 char *p2 = (char *)&rsaPubExport[k2];
3060 char *p1 = strchr(p0+1,'#');
3061 if (p1 > p0 && p1 < p2) {
3062 Int_t l01 = (Int_t)(p1-p0)-1;
3063 Int_t l12 = (Int_t)(p2-p1)-1;
3064 if (l01 >= kPRIMELENGTH*2 && l12 >= kPRIMELENGTH*2) {
3065 // Require exadecimal chars in between
3066 char *c = p0+1;
3067 while (c < p1 && ((*c < 58 && *c > 47) || (*c < 91 && *c > 64)))
3068 c++;
3069 if (c == p1) {
3070 c++;
3071 while (c < p2 && ((*c < 58 && *c > 47) || (*c < 91 && *c > 64)))
3072 c++;
3073 if (c == p2)
3074 rsakey = 0;
3075 }
3076 }
3077 }
3078 }
3079 if (gDebug > 3)
3080 ::Info("TAuthenticate::SetRSAPublic"," Key type: %d",rsakey);
3081 if (rsakey == 0) {
3082
3083 // Decode input string
3084 R__rsa_NUMBER rsa_n, rsa_d;
3085 rsakey = TAuthenticate::DecodeRSAPublic(rsaPubExport,rsa_n,rsa_d);
3086
3087 // Save Public key
3088 TRSA_fun::RSA_assign()(&fgRSAPubKey.n, &rsa_n);
3089 TRSA_fun::RSA_assign()(&fgRSAPubKey.e, &rsa_d);
3090
3091 } else {
3092 rsakey = 1;
3093#ifdef R__SSL
3094 // Now set the key locally in BF form
3095 BF_set_key(&fgBFKey, klen, (const unsigned char *)rsaPubExport);
3096#else
3097 if (gDebug > 0)
3098 ::Info("TAuthenticate::SetRSAPublic",
3099 "not compiled with SSL support:"
3100 " you should not have got here!");
3101#endif
3102 }
3103 }
3104
3105 return rsakey;
3106}
3107
3108////////////////////////////////////////////////////////////////////////////////
3109/// Receives server RSA Public key
3110/// Sends local RSA public key encoded
3111
3113{
3114 // Receive server public key
3115 char serverPubKey[kMAXSECBUF];
3116 int kind, nr = 0;
3117 if ((nr = socket->Recv(serverPubKey, kMAXSECBUF, kind)) < 0)
3118 return nr;
3119 if (gDebug > 3)
3120 ::Info("TAuthenticate::SendRSAPublicKey",
3121 "received key from server %ld bytes", (Long_t)strlen(serverPubKey));
3122
3123 // Decode it
3124 R__rsa_NUMBER rsa_n, rsa_d;
3125#ifdef R__SSL
3126 char *tmprsa = 0;
3127 if (TAuthenticate::DecodeRSAPublic(serverPubKey,rsa_n,rsa_d,
3128 &tmprsa) != key) {
3129 if (tmprsa)
3130 RSA_free((RSA *)tmprsa);
3131 return -1;
3132 }
3133 RSA *RSASSLServer = (RSA *)tmprsa;
3134#else
3135 if (TAuthenticate::DecodeRSAPublic(serverPubKey,rsa_n,rsa_d) != key)
3136 return -1;
3137#endif
3138
3139 // Send local public key, encodes
3140 char buftmp[kMAXSECBUF] = {0};
3141 char buflen[20] = {0};
3142 Int_t slen = fgRSAPubExport[key].len;
3143 Int_t ttmp = 0;
3144 if (key == 0) {
3145 strlcpy(buftmp,fgRSAPubExport[key].keys,slen+1);
3146 ttmp = TRSA_fun::RSA_encode()(buftmp, slen, rsa_n, rsa_d);
3147 snprintf(buflen, 20, "%d", ttmp);
3148 } else if (key == 1) {
3149#ifdef R__SSL
3150 Int_t lcmax = RSA_size(RSASSLServer) - 11;
3151 Int_t kk = 0;
3152 Int_t ke = 0;
3153 Int_t ns = slen;
3154 while (ns > 0) {
3155 Int_t lc = (ns > lcmax) ? lcmax : ns ;
3156 if ((ttmp = RSA_public_encrypt(lc,
3157 (unsigned char *)&fgRSAPubExport[key].keys[kk],
3158 (unsigned char *)&buftmp[ke],
3159 RSASSLServer,RSA_PKCS1_PADDING)) < 0) {
3160 char errstr[120];
3162 ::Info("TAuthenticate::SendRSAPublicKey","SSL: error: '%s' ",errstr);
3163 }
3164 kk += lc;
3165 ke += ttmp;
3166 ns -= lc;
3167 }
3168 ttmp = ke;
3169 snprintf(buflen, 20, "%d", ttmp);
3170#else
3171 if (gDebug > 0)
3172 ::Info("TAuthenticate::SendRSAPublicKey","not compiled with SSL support:"
3173 " you should not have got here!");
3174 return -1;
3175#endif
3176 } else {
3177 if (gDebug > 0)
3178 ::Info("TAuthenticate::SendRSAPublicKey","unknown key type (%d)",key);
3179#ifdef R__SSL
3180 if (RSASSLServer)
3181 RSA_free(RSASSLServer);
3182#endif
3183 return -1;
3184 }
3185
3186 // Send length first
3187 if ((nr = socket->Send(buflen, kROOTD_ENCRYPT)) < 0)
3188 return nr;
3189 // Send Key. second ...
3190 Int_t nsen = socket->SendRaw(buftmp, ttmp);
3191 if (gDebug > 3)
3192 ::Info("TAuthenticate::SendRSAPublicKey",
3193 "local: sent %d bytes (expected: %d)", nsen,ttmp);
3194#ifdef R__SSL
3195 if (RSASSLServer)
3196 RSA_free(RSASSLServer);
3197#endif
3198 return nsen;
3199}
3200
3201////////////////////////////////////////////////////////////////////////////////
3202/// Read authentication directives from $ROOTAUTHRC, $HOME/.rootauthrc or
3203/// <Root_etc_dir>/system.rootauthrc and create related THostAuth objects.
3204/// Files are read only if they changed since last reading
3205/// If 'proofconf' is defined, check also file proofconf for directives
3206
3208{
3209 // rootauthrc family
3210 char *authrc = 0;
3211 if (gSystem->Getenv("ROOTAUTHRC") != 0) {
3212 authrc = StrDup(gSystem->Getenv("ROOTAUTHRC"));
3213 } else {
3214 if (fgReadHomeAuthrc)
3215 authrc = gSystem->ConcatFileName(gSystem->HomeDirectory(), ".rootauthrc");
3216 }
3217 if (authrc && gDebug > 2)
3218 ::Info("TAuthenticate::ReadRootAuthrc", "Checking file: %s", authrc);
3219 if (!authrc || gSystem->AccessPathName(authrc, kReadPermission)) {
3220 if (authrc && gDebug > 1)
3221 ::Info("TAuthenticate::ReadRootAuthrc",
3222 "file %s cannot be read (errno: %d)", authrc, errno);
3223 delete [] authrc;
3224 authrc = gSystem->ConcatFileName(TROOT::GetEtcDir(), "system.rootauthrc");
3225 if (gDebug > 2)
3226 ::Info("TAuthenticate::ReadRootAuthrc", "Checking system file: %s", authrc);
3227 if (gSystem->AccessPathName(authrc, kReadPermission)) {
3228 if (gDebug > 1)
3229 ::Info("TAuthenticate::ReadRootAuthrc",
3230 "file %s cannot be read (errno: %d)", authrc, errno);
3231 delete [] authrc;
3232 return 0;
3233 }
3234 }
3235
3236 // Check if file has changed since last read
3237 TString tRootAuthrc = authrc;
3238 if (tRootAuthrc == fgRootAuthrc) {
3239 struct stat si;
3240 stat(tRootAuthrc, &si);
3241 if ((UInt_t)si.st_mtime < fgLastAuthrc.Convert()) {
3242 if (gDebug > 1)
3243 ::Info("TAuthenticate::ReadRootAuthrc",
3244 "file %s already read", authrc);
3245 delete [] authrc;
3246 return 0;
3247 }
3248 }
3249
3250 // Save filename in static variable
3251 fgRootAuthrc = tRootAuthrc;
3253
3254 // THostAuth lists
3255 TList *authinfo = TAuthenticate::GetAuthInfo();
3256 TList *proofauthinfo = TAuthenticate::GetProofAuthInfo();
3257
3258 // Expand File into temporary file name and open it
3259 int expand = 1;
3260 TString filetmp = "rootauthrc";
3261 FILE *ftmp = gSystem->TempFileName(filetmp);
3262 if (gDebug > 2)
3263 ::Info("TAuthenticate::ReadRootAuthrc", "got tmp file: %s open at 0x%lx",
3264 filetmp.Data(), (Long_t)ftmp);
3265 if (ftmp == 0)
3266 expand = 0; // Problems opening temporary file: ignore 'include's ...
3267
3268 FILE *fd = 0;
3269 // If the temporary file is open, copy everything to the new file ...
3270 if (expand == 1) {
3271 TAuthenticate::FileExpand(authrc, ftmp);
3272 fd = ftmp;
3273 rewind(fd);
3274 } else {
3275 // Open file
3276 fd = fopen(authrc, "r");
3277 if (fd == 0) {
3278 if (gDebug > 2)
3279 ::Info("TAuthenticate::ReadRootAuthrc",
3280 "file %s cannot be open (errno: %d)", authrc, errno);
3281 delete [] authrc;
3282 return 0;
3283 }
3284 }
3285
3286 // Now scan file for meaningful directives
3287 TList tmpAuthInfo;
3288 char line[kMAXPATHLEN];
3289 Bool_t cont = kFALSE;
3290 TString proofserv;
3291 while (fgets(line, sizeof(line), fd) != 0) {
3292
3293 // Skip comment lines
3294 if (line[0] == '#')
3295 continue;
3296
3297 // Get rid of end of line '\n', if there ...
3298 if (line[strlen(line) - 1] == '\n')
3299 line[strlen(line) - 1] = '\0';
3300
3301 // Skip empty lines
3302 if (!line[0])
3303 continue;
3304
3305 // Now scan
3306 const size_t tmpSize = strlen(line) + 1;
3307 char *tmp = new char[tmpSize];
3308 if (!tmp) {
3309 ::Error("TAuthenticate::ReadRootAuthrc",
3310 "could not allocate temporary buffer");
3311 fclose(fd);
3312 return 0;
3313 }
3314 strlcpy(tmp, line, tmpSize);
3315 char *nxt = strtok(tmp," ");
3316
3317 if (!strcmp(nxt, "proofserv") || cont) {
3318
3319 // Building the list of data servers for proof (analyzed at the end)
3320 char *ph = 0;
3321 if (cont)
3322 ph = nxt;
3323 else
3324 ph = strtok(0," ");
3325 while (ph) {
3326 if (*ph != 92) {
3327 proofserv += TString((const char *)ph);
3328 proofserv += TString(" ");
3329 cont = kFALSE;
3330 } else {
3331 cont = kTRUE;
3332 }
3333 ph = strtok(0," ");
3334 }
3335
3336 } else {
3337
3338 TString hostsrv = nxt;
3339 TString host = hostsrv;
3340 TString server = "";
3341 if (hostsrv.Contains(":")) {
3342 server = hostsrv;
3343 host.Remove(host.Index(":"));
3344 server.Remove(0,server.Index(":")+1);
3345 }
3346 Int_t srvtyp = -1;
3347 if (server.Length()) {
3348 if (server == "0" || server.BeginsWith("sock"))
3349 srvtyp = TSocket::kSOCKD;
3350 else if (server == "1" || server.BeginsWith("root"))
3351 srvtyp = TSocket::kROOTD;
3352 else if (server == "2" || server.BeginsWith("proof"))
3353 srvtyp = TSocket::kPROOFD;
3354 }
3355
3356 // Line with host info directives
3357 TString user = "*";
3358
3359 nxt = strtok(0," ");
3360 if (!strncmp(nxt,"user",4)) {
3361 nxt = strtok(0," ");
3362 if (strncmp(nxt,"list",4) && strncmp(nxt,"method",6)) {
3363 user = TString(nxt);
3364 nxt = strtok(0," ");
3365 }
3366 }
3367
3368 // Get related THostAuth, if exists in the tmp list,
3369 TIter next(&tmpAuthInfo);
3370 THostAuth *ha;
3371 while ((ha = (THostAuth *)next())) {
3372 if (host == ha->GetHost() && user == ha->GetUser() &&
3373 srvtyp == ha->GetServer())
3374 break;
3375 }
3376 if (!ha) {
3377 // Create a new one
3378 ha = new THostAuth(host,srvtyp,user);
3379 tmpAuthInfo.Add(ha);
3380 }
3381
3382 if (!strncmp(nxt,"list",4)) {
3383 // list of methods for {host,usr}
3384 Int_t nm = 0, me[kMAXSEC] = {0};
3385 char *mth = strtok(0," ");
3386 while (mth) {
3387 Int_t met = -1;
3388 if (strlen(mth) > 1) {
3389 // Method passed as string: translate it to number
3390 met = GetAuthMethodIdx(mth);
3391 if (met == -1 && gDebug > 2)
3392 ::Info("TAuthenticate::ReadRootAuthrc",
3393 "unrecognized method (%s): ", mth);
3394 } else {
3395 met = atoi(mth);
3396 }
3397 if (met > -1 && met < kMAXSEC)
3398 me[nm++] = met;
3399 mth = strtok(0," ");
3400 }
3401 if (nm)
3402 ha->ReOrder(nm,me);
3403
3404 } else if (!strncmp(nxt,"method",6)) {
3405
3406 // details for {host,usr,method}
3407 char *mth = strtok(0," ");
3408 Int_t met = -1;
3409 if (strlen(mth) > 1) {
3410 // Method passed as string: translate it to number
3411 met = GetAuthMethodIdx(mth);
3412 if (met == -1 && gDebug > 2)
3413 ::Info("TAuthenticate::ReadRootAuthrc",
3414 "unrecognized method (%s): ", mth);
3415 } else {
3416 met = atoi(mth);
3417 }
3418 if (met > -1 && met < kMAXSEC) {
3419 const char *det = 0;
3420 nxt = strtok(0," ");
3421 if (nxt) {
3422 det = (const char *)strstr(line,nxt);
3423 }
3424 if (ha->HasMethod(met))
3425 ha->SetDetails(met,det);
3426 else
3427 ha->AddMethod(met,det);
3428 }
3429 }
3430 }
3431 if (tmp) delete [] tmp;
3432 }
3433 // Close file and remove it if temporary
3434 fclose(fd);
3435 if (expand == 1)
3436 gSystem->Unlink(filetmp);
3437 // Cleanup allocated memory
3438 delete [] authrc;
3439
3440 // Update authinfo with new info found
3441 TAuthenticate::MergeHostAuthList(authinfo,&tmpAuthInfo);
3442
3443 // Print those left, if requested ...
3444 if (gDebug > 2)
3446
3447 // Now create the list of THostAuth to be sent over to
3448 // the Master/Slaves, if requested ...
3449 TList tmpproofauthinfo;
3450 if (proofserv.Length() > 0) {
3451 char *tmps = new char[proofserv.Length()+1];
3452 strlcpy(tmps,proofserv.Data(),proofserv.Length()+1);
3453 char *nxt = strtok(tmps," ");
3454 while (nxt) {
3455 TString tmp((const char *)nxt);
3456 Int_t pdd = -1;
3457 // host
3458 TString host;
3459 if ((pdd = tmp.Index(":")) == -1) {
3460 host = tmp;
3461 } else {
3462 host = tmp;
3463 host.Resize(pdd);
3464 if (!host.Length())
3465 host = "*";
3466 tmp.Remove(0,pdd+1);
3467 }
3468 // user
3469 TString user;
3470 if ((pdd = tmp.Index(":")) == -1) {
3471 user = tmp;
3472 } else {
3473 user = tmp;
3474 user.Resize(pdd);
3475 if (!user.Length())
3476 user = "*";
3477 tmp.Remove(0,pdd+1);
3478 }
3479 // method(s)
3480 TString meth;
3481 Int_t nm = 0, me[kMAXSEC] = {0}, met = -1;
3482 while (tmp.Length() > 0) {
3483 meth = tmp;
3484 if ((pdd = tmp.Index(":")) > -1)
3485 meth.Resize(pdd);
3486 if (meth.Length() > 1) {
3487 // Method passed as string: translate it to number
3488 met = GetAuthMethodIdx(meth.Data());
3489 if (met == -1 && gDebug > 2)
3490 ::Info("TAuthenticate::ReadRootAuthrc",
3491 "unrecognized method (%s): ",meth.Data());
3492 } else if (meth.Length() == 1) {
3493 met = atoi(meth.Data());
3494 if (met > -1 && met < kMAXSEC)
3495 me[nm++] = met;
3496 }
3497 if (pdd > -1)
3498 tmp.Remove(0,pdd+1);
3499 else
3500 tmp.Resize(0);
3501 }
3502
3503 // Get related THostAuth, if exists, or create a new one
3504 THostAuth *ha = 0;
3505 THostAuth *hatmp = TAuthenticate::GetHostAuth(host,user);
3506 if (!hatmp) {
3507 ha = new THostAuth(host,user,nm,me,0);
3508 } else {
3509 // Create an empty THostAuth
3510 ha = new THostAuth(host,user);
3511 // Update with hatmp info
3512 ha->Update(hatmp);
3513 // ReOrder following new directives
3514 ha->ReOrder(nm,me);
3515 }
3516 // Add to the tmp list
3517 tmpproofauthinfo.Add(ha);
3518 // Go to next
3519 nxt = strtok(0," ");
3520 }
3521 delete [] tmps;
3522 }
3523
3524 // Update proofauthinfo with new info found
3525 TAuthenticate::MergeHostAuthList(proofauthinfo,&tmpproofauthinfo,"P");
3526 // Print those, if requested ...
3527 if (gDebug > 2)
3529
3530 return authinfo->GetSize();
3531}
3532
3533////////////////////////////////////////////////////////////////////////////////
3534/// Check if the authentication method can be attempted for the client.
3535
3537{
3538 Bool_t rc = kFALSE;
3539 const char netrc[2][20] = { "/.netrc", "/.rootnetrc" };
3540 TString user;
3541
3542 // Get user logon name
3544 if (pw) {
3545 user = TString(pw->fUser);
3546 delete pw;
3547 } else {
3548 ::Info("CheckProofAuth",
3549 "not properly logged on (getpwuid unable to find relevant info)!");
3550 out = "";
3551 return rc;
3552 }
3553
3554 // UsrPwd
3555 if (cSec == (Int_t) TAuthenticate::kClear) {
3556 Int_t i = 0;
3557 for (; i < 2; i++) {
3558 TString infofile = TString(gSystem->HomeDirectory())+TString(netrc[i]);
3559 if (!gSystem->AccessPathName(infofile, kReadPermission))
3560 rc = kTRUE;
3561 }
3562 if (rc)
3563 out.Form("pt:0 ru:1 us:%s",user.Data());
3564 }
3565
3566 if (gDebug > 3) {
3567 if (strlen(out) > 0)
3568 ::Info("CheckProofAuth",
3569 "meth: %d ... is available: details: %s", cSec, out.Data());
3570 else
3571 ::Info("CheckProofAuth",
3572 "meth: %d ... is NOT available", cSec);
3573 }
3574
3575 // return
3576 return rc;
3577}
3578
3579////////////////////////////////////////////////////////////////////////////////
3580/// Standard version of CheckSecCtx to be passed to TAuthenticate::AuthExists
3581/// Check if User is matches the one in Ctx
3582/// Returns: 1 if ok, 0 if not
3583/// Deactivates Ctx is not valid
3584
3585Int_t StdCheckSecCtx(const char *user, TRootSecContext *ctx)
3586{
3587 Int_t rc = 0;
3588
3589 if (ctx->IsActive()) {
3590 if (!strcmp(user,ctx->GetUser()) &&
3591 strncmp("AFS", ctx->GetID(), 3))
3592 rc = 1;
3593 }
3594 return rc;
3595}
3596
3597////////////////////////////////////////////////////////////////////////////////
3598/// Tool for updating fgAuthInfo or fgProofAuthInfo
3599/// 'nin' contains list of last input information through (re)reading
3600/// of a rootauthrc-alike file. 'nin' info has priority.
3601/// 'std' is cleaned from inactive members.
3602/// 'nin' members used to update existing members in 'std' are
3603/// removed from 'nin', do that they do not leak
3604/// opt = "P" for proofauthinfo.
3605
3607{
3608 // Remove inactive from the 'std'
3609 TIter nxstd(std);
3610 THostAuth *ha;
3611 while ((ha = (THostAuth *) nxstd())) {
3612 if (!ha->IsActive()) {
3613 std->Remove(ha);
3614 SafeDelete(ha);
3615 }
3616 }
3617
3618 // Merge 'nin' info in 'std'
3619 TIter nxnew(nin);
3620 THostAuth *hanew;
3621 while ((hanew = (THostAuth *)nxnew())) {
3622 if (hanew->NumMethods()) {
3623 TString hostsrv;
3624 hostsrv.Form("%s:%d",hanew->GetHost(),hanew->GetServer());
3625 THostAuth *hastd =
3626 TAuthenticate::HasHostAuth(hostsrv,hanew->GetUser(),opt);
3627 if (hastd) {
3628 // Update with new info
3629 hastd->Update(hanew);
3630 // Flag for removal
3631 hanew->DeActivate();
3632 } else {
3633 // Add new ThostAuth to std
3634 std->Add(hanew);
3635 }
3636 } else
3637 // Flag for removal empty objects
3638 hanew->DeActivate();
3639 }
3640
3641 // Cleanup memory before quitting
3642 nxnew.Reset();
3643 while ((hanew = (THostAuth *)nxnew())) {
3644 if (!hanew->IsActive()) {
3645 nin->Remove(hanew);
3646 SafeDelete(hanew);
3647 }
3648 }
3649
3650}
3651
3652////////////////////////////////////////////////////////////////////////////////
3653/// Tool for removing SecContext ctx from THostAuth listed in
3654/// fgAuthInfo or fgProofAuthInfo
3655
3657{
3658 THostAuth *ha = 0;
3659
3660 // authinfo first
3661 TIter nxai(GetAuthInfo());
3662 while ((ha = (THostAuth *)nxai())) {
3663 TIter next(ha->Established());
3664 TRootSecContext *lctx = 0;
3665 while ((lctx = (TRootSecContext *) next())) {
3666 if (lctx == ctx) {
3667 ha->Established()->Remove(ctx);
3668 break;
3669 }
3670 }
3671 }
3672
3673 // proofauthinfo second
3674 TIter nxpa(GetProofAuthInfo());
3675 while ((ha = (THostAuth *)nxpa())) {
3676 TIter next(ha->Established());
3677 TRootSecContext *lctx = 0;
3678 while ((lctx = (TRootSecContext *) next())) {
3679 if (lctx == ctx) {
3680 ha->Established()->Remove(ctx);
3681 break;
3682 }
3683 }
3684 }
3685
3686}
3687
3688////////////////////////////////////////////////////////////////////////////////
3689/// Authentication related stuff setup in TProofServ.
3690/// This is the place where the buffer send by the client / master is
3691/// decoded. It contains also password information, if the case requires.
3692/// Return 0 on success, -1 on failure.
3693
3695{
3696 static Bool_t done = kFALSE;
3697
3698 // Only once
3699 if (done)
3700 return 0;
3701 done = kTRUE;
3702
3703 // Localise the buffer and decode it
3704 const char *p = gSystem->Getenv("ROOTPROOFAUTHSETUP");
3705 if (!p) {
3706 if (gDebug > 2)
3707 Info("ProofAuthSetup","Buffer not found: nothing to do");
3708 return 0;
3709 }
3710 TString mbuf = TBase64::Decode(p);
3711
3712 // Create the message
3713 TMessage *mess = new TMessage((void*)mbuf.Data(), mbuf.Length()+sizeof(UInt_t));
3714
3715 // Extract the information
3716 TString user = "";
3717 TString passwd = "";
3718 Bool_t pwhash = kFALSE;
3719 Bool_t srppwd = kFALSE;
3720 Int_t rsakey = -1;
3721 *mess >> user >> passwd >> pwhash >> srppwd >> rsakey;
3722
3723 // Set Globals for later use
3728 const char *h = gSystem->Getenv("ROOTHOMEAUTHRC");
3729 if (h) {
3730 Bool_t rha = (Bool_t)(strtol(h, (char **)0, 10));
3732 }
3733
3734 // Extract the list of THostAuth
3735 TList *pha = (TList *)mess->ReadObject(TList::Class());
3736 if (!pha) {
3737 if (gDebug > 0)
3738 Info("ProofAuthSetup","List of THostAuth not found");
3739 return 0;
3740 }
3741
3742 Bool_t master = gROOT->IsProofServ();
3743 TIter next(pha);
3744 THostAuth *ha = 0;
3745 while ((ha = (THostAuth *)next())) {
3746
3747 // Check if there is already one compatible
3748 Int_t kExact = 0;
3749 THostAuth *haex = 0;
3750 Bool_t fromProofAI = kFALSE;
3751 if (master) {
3752 // Look first in the proof list
3753 haex = TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"P",&kExact);
3754 // If nothing found, look also in the standard list
3755 if (!haex) {
3756 haex =
3757 TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"R",&kExact);
3758 } else
3759 fromProofAI = kTRUE;
3760 } else {
3761 // For slaves look first in the standard list only
3762 haex = TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"R",&kExact);
3763 }
3764
3765 if (haex) {
3766 // If yes, action depends on whether it matches exactly or not
3767 if (kExact == 1) {
3768 // Update info in authinfo if Slave or in proofauthinfo
3769 // if Master and the entry was already in proofauthinfo
3770 if (!master || fromProofAI) {
3771 // update this existing one with the information found in
3772 // in the new one, if needed
3773 haex->Update(ha);
3774 // Delete temporary THostAuth
3775 SafeDelete(ha);
3776 } else
3777 // Master, entry not already in proofauthinfo,
3778 // Add it to the list
3780 } else {
3781 // update this new one with the information found in
3782 // in the existing one (if needed) and ...
3783 Int_t i = 0;
3784 for (; i < haex->NumMethods(); i++) {
3785 Int_t met = haex->GetMethod(i);
3786 if (!ha->HasMethod(met))
3787 ha->AddMethod(met,haex->GetDetails(met));
3788 }
3789 if (master)
3790 // ... add the new one to the list
3792 else
3793 // We add this one to the standard list
3795 }
3796 } else {
3797 if (master)
3798 // We add this one to the list for forwarding
3800 else
3801 // We add this one to the standard list
3803 }
3804 }
3805
3806 // We are done
3807 return 0;
3808}
3809
3810////////////////////////////////////////////////////////////////////////////////
3811/// Setup of authetication related stuff in PROOF run after a
3812/// successful authentication.
3813/// Return 0 on success, -1 on failure.
3814
3816{
3817 // Fill some useful info
3818 TSecContext *sc = sock->GetSecContext();
3819 TString user = sc->GetUser();
3820 Int_t remoteOffSet = sc->GetOffSet();
3821
3822 // send user name to remote host
3823 // for UsrPwd method send also passwd, rsa encoded
3824 TMessage pubkey;
3825 TString passwd = "";
3826 Bool_t pwhash = kFALSE;
3827 Bool_t srppwd = kFALSE;
3828
3829 Bool_t upwd = sc->IsA("UsrPwd");
3830
3831 TPwdCtx *pwdctx = 0;
3832 if (remoteOffSet > -1 && upwd)
3833 pwdctx = (TPwdCtx *)(sc->GetContext());
3834
3835 if (upwd && pwdctx) {
3836 passwd = pwdctx->GetPasswd();
3837 pwhash = pwdctx->IsPwHash();
3838 }
3839
3840 Int_t keytyp = ((TRootSecContext *)sc)->GetRSAKey();
3841
3842 // Prepare buffer
3843 TMessage mess;
3844 mess << user << passwd << pwhash << srppwd << keytyp;
3845
3846 // Add THostAuth info
3848
3849 // Get buffer as a base 64 string
3850 char *mbuf = mess.Buffer();
3851 Int_t mlen = mess.Length();
3852 TString messb64 = TBase64::Encode(mbuf, mlen);
3853
3854 if (gDebug > 2)
3855 ::Info("ProofAuthSetup","sending %d bytes", messb64.Length());
3856
3857 // Send it over
3858 if (remoteOffSet > -1) {
3859 if (TAuthenticate::SecureSend(sock, 1, keytyp, messb64.Data()) == -1) {
3860 ::Error("ProofAuthSetup","problems secure-sending message buffer");
3861 return -1;
3862 }
3863 } else {
3864 // There is no encryption key: send it plain
3865 char buflen[20];
3866 snprintf(buflen,20, "%d", messb64.Length());
3867 if (sock->Send(buflen, kMESS_ANY) < 0) {
3868 ::Error("ProofAuthSetup","plain: problems sending message length");
3869 return -1;
3870 }
3871 if (sock->SendRaw(messb64.Data(), messb64.Length()) < 0) {
3872 ::Error("ProofAuthSetup","problems sending message buffer");
3873 return -1;
3874 }
3875 }
3876
3877 // We are done
3878 return 0;
3879}
3880
3881////////////////////////////////////////////////////////////////////////////////
3882/// Static method returning supported client protocol.
3883
3885{
3887}
3888
3889//
3890// The code below is needed by TSlave and TProofServ for backward
3891// compatibility.
3892//
3893
3894////////////////////////////////////////////////////////////////////////////////
3895/// Sends the list of the relevant THostAuth objects to the master or
3896/// to the active slaves, typically data servers external to the proof
3897/// cluster. The list is of THostAuth to be sent is specified by
3898/// TAuthenticate::fgProofAuthInfo after directives found in the
3899/// .rootauthrc family files ('proofserv' key)
3900/// Returns -1 if a problem sending THostAuth has occured, -2 in case
3901/// of problems closing the transmission.
3902
3904{
3905 Int_t retval = 0, ns = 0;
3906
3907 if (!s) {
3908 Error("SendHostAuth","invalid input: socket undefined");
3909 return -1;
3910 }
3911
3912
3914 THostAuth *ha;
3915 while ((ha = (THostAuth *)next())) {
3916 TString buf;
3917 ha->AsString(buf);
3918 if((ns = s->Send(buf, kPROOF_HOSTAUTH)) < 1) {
3919 retval = -1;
3920 break;
3921 }
3922 if (gDebug > 2)
3923 Info("SendHostAuth","sent %d bytes (%s)",ns,buf.Data());
3924 }
3925
3926 // End of transmission ...
3927 if ((ns = s->Send("END", kPROOF_HOSTAUTH)) < 1)
3928 retval = -2;
3929 if (gDebug > 2)
3930 Info("SendHostAuth","sent %d bytes for closing",ns);
3931
3932 return retval;
3933}
3934
3935////////////////////////////////////////////////////////////////////////////////
3936/// Receive from client/master directives for authentications, create
3937/// related THostAuth and add them to the TAuthenticate::ProofAuthInfo
3938/// list. Opt = "M" or "m" if Master, "S" or "s" if Proof slave.
3939/// The 'proofconf' file is read only if Master
3940
3942{
3943 if (!s) {
3944 Error("RecvHostAuth","invalid input: socket undefined");
3945 return -1;
3946 }
3947
3948 // Check if Master
3949 Bool_t master = !strncasecmp(opt,"M",1) ? kTRUE : kFALSE;
3950
3951 // First read directives from <rootauthrc>, <proofconf> and alike files
3953
3954 // Receive buffer
3955 Int_t kind;
3956 char buf[kMAXSECBUF];
3957 Int_t nr = s->Recv(buf, kMAXSECBUF, kind);
3958 if (nr < 0 || kind != kPROOF_HOSTAUTH) {
3959 Error("RecvHostAuth", "received: kind: %d (%d bytes)", kind, nr);
3960 return -1;
3961 }
3962 if (gDebug > 2)
3963 Info("RecvHostAuth","received %d bytes (%s)",nr,buf);
3964
3965 while (strcmp(buf, "END")) {
3966 // Clean buffer
3967 Int_t nc = (nr >= kMAXSECBUF) ? kMAXSECBUF - 1 : nr ;
3968 buf[nc] = '\0';
3969
3970 // Create THostAuth
3971 THostAuth *ha = new THostAuth((const char *)&buf);
3972
3973 // Check if there is already one compatible
3974 Int_t kExact = 0;
3975 THostAuth *haex = 0;
3976 Bool_t fromProofAI = kFALSE;
3977 if (master) {
3978 // Look first in the proof list
3979 haex = TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"P",&kExact);
3980 // If nothing found, look also in the standard list
3981 if (!haex) {
3982 haex =
3983 TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"R",&kExact);
3984 } else
3985 fromProofAI = kTRUE;
3986 } else {
3987 // For slaves look first in the standard list only
3988 haex = TAuthenticate::GetHostAuth(ha->GetHost(),ha->GetUser(),"R",&kExact);
3989 }
3990
3991 if (haex) {
3992 // If yes, action depends on whether it matches exactly or not
3993 if (kExact == 1) {
3994 // Update info in authinfo if Slave or in proofauthinfo
3995 // if master and the entry was already in proofauthinfo
3996 if (!master || fromProofAI) {
3997 // update this existing one with the information found in
3998 // in the new one, if needed
3999 haex->Update(ha);
4000 // Delete temporary THostAuth
4001 SafeDelete(ha);
4002 } else
4003 // master, entry not already in proofauthinfo,
4004 // Add it to the list
4006 } else {
4007 // update this new one with the information found in
4008 // in the existing one (if needed) and ...
4009 Int_t i = 0;
4010 for (; i < haex->NumMethods(); i++) {
4011 Int_t met = haex->GetMethod(i);
4012 if (!ha->HasMethod(met))
4013 ha->AddMethod(met,haex->GetDetails(met));
4014 }
4015 if (master)
4016 // ... add the new one to the list
4018 else
4019 // We add this one to the standard list
4021 }
4022 } else {
4023 if (master)
4024 // We add this one to the list for forwarding
4026 else
4027 // We add this one to the standard list
4029 }
4030
4031
4032 // Get the next one
4033 nr = s->Recv(buf, kMAXSECBUF, kind);
4034 if (nr < 0 || kind != kPROOF_HOSTAUTH) {
4035 Info("RecvHostAuth","Error: received: kind: %d (%d bytes)", kind, nr);
4036 return -1;
4037 }
4038 if (gDebug > 2)
4039 Info("RecvHostAuth","received %d bytes (%s)",nr,buf);
4040 }
4041
4042 return 0;
4043}
4044
4045extern "C" {
4046
4047////////////////////////////////////////////////////////////////////////////////
4048/// Setup of authetication in PROOF run after successful opening
4049/// of the socket. Provided for backward compatibility.
4050/// Return 0 on success, -1 on failure.
4051
4053 Bool_t /* master */, TString ord, TString conf)
4054{
4055
4056 // Fill some useful info
4057 TSecContext *sc = sock->GetSecContext();
4058 TString user = sc->GetUser();
4059 Int_t proofdProto = sock->GetRemoteProtocol();
4060 Int_t remoteOffSet = sc->GetOffSet();
4061
4062 // send user name to remote host
4063 // for UsrPwd method send also passwd, rsa encoded
4064 TMessage pubkey;
4065 TString passwd = "";
4066 Bool_t pwhash = kFALSE;
4067 Bool_t srppwd = kFALSE;
4068
4069 Bool_t upwd = sc->IsA("UsrPwd");
4070
4071 TPwdCtx *pwdctx = 0;
4072 if (remoteOffSet > -1 && upwd)
4073 pwdctx = (TPwdCtx *)(sc->GetContext());
4074
4075 if (upwd && pwdctx) {
4076
4077 // Send offset to identify remotely the public part of RSA key
4078 if (sock->Send(remoteOffSet, kROOTD_RSAKEY) != 2*sizeof(Int_t)) {
4079 Error("OldAuthSetup", "failed to send offset in RSA key");
4080 return -1;
4081 }
4082
4083 if (pwdctx) {
4084 passwd = pwdctx->GetPasswd();
4085 pwhash = pwdctx->IsPwHash();
4086 }
4087
4088 Int_t keytyp = ((TRootSecContext *)sc)->GetRSAKey();
4089 if (TAuthenticate::SecureSend(sock, 1, keytyp, passwd.Data()) == -1) {
4090 if (remoteOffSet > -1)
4091 Warning("OldAuthSetup","problems secure-sending pass hash %s",
4092 "- may result in failures");
4093 // If non RSA encoding available try passwd inversion
4094 if (upwd) {
4095 for (int i = 0; i < passwd.Length(); i++) {
4096 char inv = ~passwd(i);
4097 passwd.Replace(i, 1, inv);
4098 }
4099 TMessage mess;
4100 mess << passwd;
4101 if (sock->Send(mess) < 0) {
4102 Error("OldAuthSetup", "failed to send inverted password");
4103 return -1;
4104 }
4105 }
4106 }
4107
4108 } else {
4109
4110 // Send notification of no offset to be sent ...
4111 if (sock->Send(-2, kROOTD_RSAKEY) != 2*sizeof(Int_t)) {
4112 Error("OldAuthSetup", "failed to send no offset notification in RSA key");
4113 return -1;
4114 }
4115 }
4116
4117 // Send ordinal (and config) info to slave (or master)
4118 TMessage mess;
4119 mess << user << pwhash << srppwd << ord << conf;
4120
4121 if (sock->Send(mess) < 0) {
4122 Error("OldAuthSetup", "failed to send ordinal and config info");
4123 return -1;
4124 }
4125
4126 if (proofdProto > 6) {
4127 // Now we send authentication details to access, e.g., data servers
4128 // not in the proof cluster and to be propagated to slaves.
4129 // This is triggered by the 'proofserv <dserv1> <dserv2> ...'
4130 // line in .rootauthrc
4131 if (SendHostAuth(sock) < 0) {
4132 Error("OldAuthSetup", "failed to send HostAuth info");
4133 return -1;
4134 }
4135 }
4136
4137 // We are done
4138 return 0;
4139}
4140
4141////////////////////////////////////////////////////////////////////////////////
4142/// Authentication related setup in TProofServ run after successful
4143/// startup. Provided for backward compatibility.
4144/// Return 0 on success, -1 on failure.
4145
4147 TString &user, TString &ord, TString &conf)
4148{
4149 // First receive, decode and store the public part of RSA key
4150 Int_t retval, kind;
4151 if (sock->Recv(retval, kind) != 2*sizeof(Int_t)) {
4152 //other side has closed connection
4153 Info("OldProofServAuthSetup",
4154 "socket has been closed due to protocol mismatch - Exiting");
4155 return -1;
4156 }
4157
4158 Int_t rsakey = 0;
4160 if (kind == kROOTD_RSAKEY) {
4161
4162 if (retval > -1) {
4163 if (gSystem->Getenv("ROOTKEYFILE")) {
4164
4165 TString keyfile = gSystem->Getenv("ROOTKEYFILE");
4166 keyfile += retval;
4167
4168 FILE *fKey = 0;
4169 char pubkey[kMAXPATHLEN] = { 0 };
4170 if (!gSystem->AccessPathName(keyfile.Data(), kReadPermission)) {
4171 if ((fKey = fopen(keyfile.Data(), "r"))) {
4172 Int_t klen = fread((void *)pubkey,1,sizeof(pubkey),fKey);
4173 if (klen <= 0) {
4174 Error("OldProofServAuthSetup",
4175 "failed to read public key from '%s'", keyfile.Data());
4176 fclose(fKey);
4177 return -1;
4178 }
4179 pubkey[klen] = 0;
4180 // Set RSA key
4181 rsakey = TAuthenticate::SetRSAPublic(pubkey,klen);
4182 fclose(fKey);
4183 } else {
4184 Error("OldProofServAuthSetup", "failed to open '%s'", keyfile.Data());
4185 return -1;
4186 }
4187 }
4188 }
4189
4190 // Receive passwd
4191 char *pwd = 0;
4192 if (TAuthenticate::SecureRecv(sock, 2, rsakey, &pwd) < 0) {
4193 Error("OldProofServAuthSetup", "failed to receive password");
4194 return -1;
4195 }
4196 passwd = pwd;
4197 delete[] pwd;
4198
4199 } else if (retval == -1) {
4200
4201 // Receive inverted passwd
4202 TMessage *mess;
4203 if ((sock->Recv(mess) <= 0) || !mess) {
4204 Error("OldProofServAuthSetup", "failed to receive inverted password");
4205 return -1;
4206 }
4207 (*mess) >> passwd;
4208 delete mess;
4209
4210 for (Int_t i = 0; i < passwd.Length(); i++) {
4211 char inv = ~passwd(i);
4212 passwd.Replace(i, 1, inv);
4213 }
4214
4215 }
4216 }
4217
4218 // Receive final information
4219 TMessage *mess;
4220 if ((sock->Recv(mess) <= 0) || !mess) {
4221 Error("OldProofServAuthSetup", "failed to receive ordinal and config info");
4222 return -1;
4223 }
4224
4225 // Decode it
4226 Bool_t pwhash, srppwd;
4227 if (master) {
4228 if (protocol < 4) {
4229 (*mess) >> user >> pwhash >> srppwd >> conf;
4230 ord = "0";
4231 } else {
4232 (*mess) >> user >> pwhash >> srppwd >> ord >> conf;
4233 }
4234 } else {
4235 if (protocol < 4) {
4236 Int_t iord;
4237 (*mess) >> user >> pwhash >> srppwd >> iord;
4238 ord = "0.";
4239 ord += iord;
4240 } else {
4241 (*mess) >> user >> pwhash >> srppwd >> ord >> conf;
4242 }
4243 }
4244 delete mess;
4245
4246 // Set Globals for later use
4251 const char *h = gSystem->Getenv("ROOTHOMEAUTHRC");
4252 if (h) {
4253 Bool_t rha = (Bool_t)(strtol(h, (char **)0, 10));
4255 }
4256
4257 // Read user or system authentication directives and
4258 // receive auth info transmitted from the client
4259 Int_t harc = master ? RecvHostAuth(sock, "M") : RecvHostAuth(sock, "S");
4260
4261 if (harc < 0) {
4262 Error("OldProofServAuthSetup", "failed to receive HostAuth info");
4263 return -1;
4264 }
4265
4266 // We are done
4267 return 0;
4268}
4269
4270} // extern "C"
const Int_t kAUTH_SSALT_MSK
Definition: AuthConst.h:30
const Int_t kAUTH_CRYPT_MSK
Definition: AuthConst.h:29
const Int_t kMAXSECBUF
Definition: AuthConst.h:27
const Int_t kAUTH_REUSE_MSK
Definition: AuthConst.h:28
const Int_t kPRIMEEXP
Definition: AuthConst.h:34
const Int_t kPRIMELENGTH
Definition: AuthConst.h:33
const Int_t kMAXRSATRIES
Definition: AuthConst.h:32
const Int_t kAUTH_RSATY_MSK
Definition: AuthConst.h:31
const Int_t kMAXSEC
Definition: AuthConst.h:26
void Class()
Definition: Class.C:29
@ kROOTD_RSAKEY
Definition: MessageTypes.h: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:543
#define c(i)
Definition: RSha256.hxx:101
#define h(i)
Definition: RSha256.hxx:106
const Ssiz_t kNPOS
Definition: RtypesCore.h:113
int Int_t
Definition: RtypesCore.h:43
const Bool_t kFALSE
Definition: RtypesCore.h:90
long Long_t
Definition: RtypesCore.h:52
bool Bool_t
Definition: RtypesCore.h:61
R__EXTERN Int_t gDebug
Definition: RtypesCore.h:117
const Bool_t kTRUE
Definition: RtypesCore.h:89
const char Option_t
Definition: RtypesCore.h:64
#define ClassImp(name)
Definition: Rtypes.h:361
@ kMAXPATHLEN
Definition: Rtypes.h:58
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:171
void Info(const char *location, const char *msgfmt,...)
void Error(const char *location, const char *msgfmt,...)
void Warning(const char *location, const char *msgfmt,...)
char name[80]
Definition: TGX11.cxx:109
#define gROOT
Definition: TROOT.h:406
char * Form(const char *fmt,...)
void Printf(const char *fmt,...)
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2490
typedef void((*Func_t)())
@ kReadPermission
Definition: TSystem.h:46
Bool_t R_ISREG(Int_t mode)
Definition: TSystem.h:117
Bool_t R_ISDIR(Int_t mode)
Definition: TSystem.h:114
R__EXTERN TSystem * gSystem
Definition: TSystem.h:556
@ kS_IWUSR
Definition: TSystem.h:102
@ kS_IRUSR
Definition: TSystem.h:101
#define R__LOCKGUARD2(mutex)
const char * proto
Definition: civetweb.c:16604
#define SSL_load_error_strings
Definition: civetweb.c:2018
#define SSL_library_init
Definition: civetweb.c:2010
#define ERR_get_error
Definition: civetweb.c:2086
#define snprintf
Definition: civetweb.c:1540
#define ERR_error_string
Definition: civetweb.c:2087
static void RemoveHostAuth(THostAuth *ha, Option_t *opt="")
Remove THostAuth instance from the list.
static Int_t SetRSAPublic(const char *rsapubexport, Int_t klen)
Store RSA public keys from export string rsaPubExport.
static TPluginHandler * fgPasswdDialog
static Int_t fgProcessID
static void SetGlobalSRPPwd(Bool_t srppwd)
Set global SRP passwd flag to be used for authentication to rootd or proofd.
static Bool_t fgPromptUser
TRootSecContext * fSecContext
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:99
char * Buffer() const
Definition: TBuffer.h:95
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition: TDatime.h:37
void Set()
Set Date/Time to current time as reported by the system.
Definition: TDatime.cxx:288
UInt_t Convert(Bool_t toGMT=kFALSE) const
Convert fDatime from TDatime format to the standard time_t format.
Definition: TDatime.cxx:181
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition: TEnv.cxx:491
const char * GetUser() const
Definition: THostAuth.h:94
Int_t NumMethods() const
Definition: THostAuth.h:69
const char * GetHost() const
Definition: THostAuth.h:92
TRootSecContext * CreateSecContext(const char *user, const char *host, Int_t meth, Int_t offset, const char *details, const char *token, TDatime expdate=kROOTTZERO, void *ctx=0, Int_t key=-1)
Create a Security context and add it to local list Return pointer to it to be stored in TAuthenticate...
Definition: THostAuth.cxx:723
Int_t GetServer() const
Definition: THostAuth.h:93
void SetUser(const char *user)
Definition: THostAuth.h:98
void SetDetails(Int_t level, const char *details)
Set authentication details for specified level.
Definition: THostAuth.cxx:403
void SetHost(const char *host)
Definition: THostAuth.h:96
void SetFirst(Int_t level)
Set 'method' to be the first used (if in the list ...).
Definition: THostAuth.cxx:583
virtual void Print(Option_t *option="") const
Print object content.
Definition: THostAuth.cxx:424
void SetServer(Int_t server)
Definition: THostAuth.h:97
void ReOrder(Int_t nmet, Int_t *fmet)
Reorder nmet methods according fmet[nmet].
Definition: THostAuth.cxx:473
void RemoveMethod(Int_t level)
Remove method 'meth' from the list, if there ...
Definition: THostAuth.cxx:310
void DeActivate()
Definition: THostAuth.h:84
void AddMethod(Int_t level, const char *details=0)
Add method to the list.
Definition: THostAuth.cxx:277
void CountFailure(Int_t level)
Count failures for 'method'.
Definition: THostAuth.cxx:708
Int_t GetMethod(Int_t idx) const
Definition: THostAuth.h:70
Bool_t IsActive() const
Definition: THostAuth.h:83
void AsString(TString &out) const
Return a static string with all info in a serialized form.
Definition: THostAuth.cxx:741
Bool_t HasMethod(Int_t level, Int_t *pos=0)
Return kTRUE if method 'level' is in the list.
Definition: THostAuth.cxx:387
TList * Established() const
Definition: THostAuth.h:100
void AddFirst(Int_t level, const char *details=0)
Add new method in first position If already in the list, set as first method 'level' with authenticat...
Definition: THostAuth.cxx:651
void Update(THostAuth *ha)
Update info with the one in ha Remaining methods, if any, get lower priority.
Definition: THostAuth.cxx:533
const char * GetDetails(Int_t level)
Return authentication details for specified level or "" if the specified level does not exist for thi...
Definition: THostAuth.cxx:371
void SetLast(Int_t level)
Set 'method' to be the last used (if in the list ...).
Definition: THostAuth.cxx:615
void PrintEstablished() const
Print info about established authentication vis-a-vis of this Host.
Definition: THostAuth.cxx:448
void CountSuccess(Int_t level)
Count successes for 'method'.
Definition: THostAuth.cxx:694
This class represents an Internet Protocol (IP) address.
Definition: TInetAddress.h:36
const char * GetHostName() const
Definition: TInetAddress.h:71
Bool_t IsValid() const
Definition: TInetAddress.h:76
const char * GetHostAddress() const
Returns the IP address string "%d.%d.%d.%d".
void Reset()
Definition: TCollection.h:252
A doubly linked list.
Definition: TList.h:44
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:821
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:877
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:891
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:865
Long_t ExecPlugin(int nargs, const T &... params)
Int_t LoadPlugin()
Load the plugin library for this handler.
Bool_t IsPwHash() const
Definition: TSecContext.h: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:866
static const TString & GetEtcDir()
Get the sysconfig directory in the installation. Static utility function.
Definition: TROOT.cxx:2939
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:817
static Int_t GetClientProtocol()
Static method returning supported client protocol.
Definition: TSocket.cxx:1468
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:897
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:131
Ssiz_t Length() const
Definition: TString.h:405
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2177
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition: TString.h:677
const char * Data() const
Definition: TString.h:364
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:687
void Resize(Ssiz_t n)
Resize the string. Truncate or add blanks as necessary.
Definition: TString.cxx:1095
@ kIgnoreCase
Definition: TString.h:263
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:610
Bool_t IsNull() const
Definition: TString.h:402
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
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:2311
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2289
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
virtual int GetPid()
Get process id.
Definition: TSystem.cxx:705
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1658
virtual char * ConcatFileName(const char *dir, const char *name)
Concatenate a directory and a file name. User must delete returned string.
Definition: TSystem.cxx:1066
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition: TSystem.cxx:1850
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:1393
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:1291
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:1492
virtual void DispatchOneEvent(Bool_t pendingOnly=kFALSE)
Dispatch a single event.
Definition: TSystem.cxx:427
virtual const char * HostName()
Return the system's host name.
Definition: TSystem.cxx:301
virtual Int_t GetEffectiveUid()
Returns the effective user id.
Definition: TSystem.cxx:1565
virtual TInetAddress GetHostByName(const char *server)
Get Internet Protocol (IP) address of host.
Definition: TSystem.cxx:2292
virtual const char * HomeDirectory(const char *userName=nullptr)
Return the user's home directory.
Definition: TSystem.cxx:883
virtual int Unlink(const char *name)
Unlink, i.e.
Definition: TSystem.cxx:1376
virtual UserGroup_t * GetUserInfo(Int_t uid)
Returns all user info in the UserGroup_t structure.
Definition: TSystem.cxx:1594
char * DynamicPathName(const char *lib, Bool_t quiet=kFALSE)
Find a dynamic library called lib using the system search paths.
Definition: TSystem.cxx:2013
Handles synchronous and a-synchronous timer events.
Definition: TTimer.h:51
virtual void Start(Long_t milliSec=-1, Bool_t singleShot=kFALSE)
Starts the timer with a milliSec timeout.
Definition: TTimer.cxx:211
void SetInterruptSyscalls(Bool_t set=kTRUE)
When the argument is true the a-synchronous timer (SIGALRM) signal handler is set so that interrupted...
Definition: TTimer.cxx:197
virtual void Stop()
Definition: TTimer.h:93
This class implements a mutex interface.
Definition: TVirtualMutex.h:34
TPaveText * pt
TLine * line
EvaluateInfo init(std::vector< RooRealProxy > parameters, std::vector< ArrayWrapper * > wrappers, std::vector< double * > arrays, size_t begin, size_t batchSize)
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:126
TString fUser
Definition: TSystem.h:140
auto * m
Definition: textangle.C:8
auto * l
Definition: textangle.C:4
auto * t1
Definition: textangle.C:20