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