Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TAuthenticate.cxx
Go to the documentation of this file.
1// @(#)root/auth:$Id: f2cfa663e232707e1201467b5805ff1d13575326 $
2// Author: Fons Rademakers 26/11/2000
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12//////////////////////////////////////////////////////////////////////////
13// //
14// TAuthenticate //
15// //
16// An authentication module for ROOT based network services, like rootd // //
17// //
18//////////////////////////////////////////////////////////////////////////
19
20#include "RConfigure.h"
21
22#include "TAuthenticate.h"
23#include "TApplication.h"
24#include "THostAuth.h"
25#include "TRootSecContext.h"
26#include "TPluginManager.h"
27#include "TNetFile.h"
28#include "TPSocket.h"
29#include "TMessage.h"
30#include "TSystem.h"
31#include "TError.h"
32#include "Getline.h"
33#include "TROOT.h"
34#include "TEnv.h"
35#include "TList.h"
36#include "NetErrors.h"
37#include "TRegexp.h"
38#include "TVirtualMutex.h"
39#include "TTimer.h"
40#include "TBase64.h"
41#include "strlcpy.h"
42#include "snprintf.h"
43
44#include "rsafun.h"
45
46#ifndef R__LYNXOS
47#include <sys/stat.h>
48#endif
49#include <cerrno>
50#include <sys/types.h>
51#include <ctime>
52#if !defined(R__WIN32) && !defined(R__MACOSX) && !defined(R__FBSD) && \
53 !defined(R__OBSD)
54#include <crypt.h>
55#endif
56#ifdef WIN32
57# include <io.h>
58#endif /* WIN32 */
59#if defined(R__LINUX) || defined(R__FBSD) || defined(R__OBSD)
60# include <unistd.h>
61#endif
62#include <cstdlib>
63#ifndef WIN32
64# include <sys/time.h>
65#endif /* WIN32 */
66
67#if defined(R__MACOSX)
68extern "C" char *crypt(const char *, const char *);
69#endif
70
71#ifdef R__SSL
72// SSL specific headers
73# include <openssl/bio.h>
74# include <openssl/err.h>
75# include <openssl/pem.h>
76# include <openssl/rand.h>
77# include <openssl/rsa.h>
78# include <openssl/ssl.h>
79# include <openssl/blowfish.h>
80#endif
81
85
86#ifdef R__SSL
87 static BF_KEY fgBFKey; // Blowfish symmetric key
88#endif
89
90// Statics initialization
92TString TAuthenticate::fgAuthMeth[] = { "UsrPwd", "Unsupported", "Unsupported",
93 "Unsupported", "Unsupported", "Unsupported" };
97TDatime 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
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
125
126////////////////////////////////////////////////////////////////////////////////
127/// rand() implementation using /udev/random or /dev/random, if available
128
129static int auth_rand()
130{
131#ifndef WIN32
132 int frnd = open("/dev/urandom", O_RDONLY);
133 if (frnd < 0) frnd = open("/dev/random", O_RDONLY);
134 int r;
135 if (frnd >= 0) {
136 ssize_t rs = read(frnd, (void *) &r, sizeof(int));
137 close(frnd);
138 if (r < 0) r = -r;
139 if (rs == sizeof(int)) return r;
140 }
141 Printf("+++ERROR+++ : auth_rand: neither /dev/urandom nor /dev/random are available or readable!");
142 struct timeval tv;
143 if (gettimeofday(&tv,0) == 0) {
144 int t1, t2;
145 memcpy((void *)&t1, (void *)&tv.tv_sec, sizeof(int));
146 memcpy((void *)&t2, (void *)&tv.tv_usec, sizeof(int));
147 r = t1 + t2;
148 if (r < 0) r = -r;
149 return r;
150 }
151 return -1;
152#else
153 // No special random device available: use rand()
154 return rand();
155#endif
156}
157
158////////////////////////////////////////////////////////////////////////////////
159/// Create authentication object.
160
162 const char *proto, const char *user)
163{
164 if (gDebug > 2 && gAuthenticateMutex)
165 Info("Authenticate", "locking mutex (pid: %d)",gSystem->GetPid());
167
168 // Use the ID of the starting thread as unique identifier
169 if (fgProcessID < 0)
171
172 if (fgAuthTO == -2)
173 fgAuthTO = gEnv->GetValue("Auth.Timeout",-1);
174
175 fSocket = sock;
176 fRemote = remote;
177 fHostAuth = 0;
178 fVersion = 5; // The latest, by default
179 fSecContext = 0;
180
181 if (gDebug > 2)
182 Info("TAuthenticate", "Enter: local host: %s, user is: %s (proto: %s)",
183 gSystem->HostName(), user, proto);
184
185 // Set protocol string.
186 // Check if version should be different ...
187 char *pdd;
189 if (proto && strlen(proto) > 0) {
190 char *sproto = StrDup(proto);
191 if ((pdd = strstr(sproto, ":")) != 0) {
192 int rproto = atoi(pdd + 1);
193 *pdd = '\0';
194 if (strstr(sproto, "root") != 0) {
195 if (rproto < 12 ) {
196 fVersion = 4;
197 if (rproto < 11 ) {
198 fVersion = 3;
199 if (rproto < 9 ) {
200 fVersion = 2;
201 if (rproto < 8) {
202 fVersion = 1;
203 if (rproto < 6)
204 fVersion = 0;
205 }
206 }
207 }
208 }
210 }
211 if (gDebug > 3)
212 Info("TAuthenticate",
213 "service: %s (remote protocol: %d): fVersion: %d", sproto,
215 }
217 delete [] sproto;
218 }
219
220 // Check or get user name
221 fUser = "";
223 if (user && strlen(user) > 0) {
224 fUser = user;
225 checkUser = user;
226 } else {
228 if (u)
229 checkUser = u->fUser;
230 delete u;
231 }
232 fPasswd = "";
233 fPwHash = kFALSE;
234
235 // Type of RSA key
236 if (fgRSAKey < 0) {
237 fgRSAKey = 0; // Default key
238#ifdef R__SSL
239 // Another choice possible: check user preferences
240 if (gEnv->GetValue("RSA.KeyType",0) == 1)
241 fgRSAKey = 1;
242#endif
243 }
244 // This is the key actually used: we propose the default
245 // to the server, and behave according to its reply
247 if (gDebug > 3)
248 Info("TAuthenticate","RSA key: default type %d", fgRSAKey);
249
250 // RSA key generation (one per session)
251 if (!fgRSAInit) {
252 GenRSAKeys();
253 fgRSAInit = 1;
254 }
255
256 // Check and save the host FQDN ...
259 if (addr.IsValid())
260 fqdn = addr.GetHostName();
262 fqdnsrv.Form("%s:%d",fqdn.Data(),servtype);
263
264 // Read directives from files; re-read if files have changed
266
267 if (gDebug > 3) {
268 Info("TAuthenticate",
269 "number of HostAuth Instantiations in memory: %d",
270 GetAuthInfo()->GetSize());
273 }
274
275 // Check the list of auth info for already loaded info about this host
277
278 //
279 // If generic THostAuth (i.e. with wild card or user == any)
280 // make a personalized memory copy of this THostAuth
281 if (strchr(fHostAuth->GetHost(),'*') || strchr(fHostAuth->GetHost(),'*') ||
282 fHostAuth->GetServer() == -1 ) {
287 }
288
289 // If a specific method has been requested via the protocol
290 // set it as first
291 Int_t sec = -1;
292 TString tmp = fProtocol;
293 tmp.ReplaceAll("root",4,"",0);
294 tmp.ReplaceAll("sock",4,"",0);
295 if (!strncmp(tmp.Data(),"up",2))
296 sec = 0;
297 else if (!strncmp(tmp.Data(),"s",1))
298 sec = 1;
299 else if (!strncmp(tmp.Data(),"k",1))
300 sec = 2;
301 else if (!strncmp(tmp.Data(),"g",1))
302 sec = 3;
303 else if (!strncmp(tmp.Data(),"h",1))
304 sec = 4;
305 else if (!strncmp(tmp.Data(),"ug",2))
306 sec = 5;
307 if (sec > -1 && sec < kMAXSEC) {
308 if (fHostAuth->HasMethod(sec)) {
310 } else {
311 char *dtmp = GetDefaultDetails(sec, 1, checkUser);
314 if (dtmp)
315 delete [] dtmp;
316 }
317 }
318
319 // This is what we have in memory
320 if (gDebug > 3) {
321 TIter next(fHostAuth->Established());
322 TRootSecContext *ctx;
323 while ((ctx = (TRootSecContext *) next()))
324 ctx->Print("0");
325 }
326}
327
328////////////////////////////////////////////////////////////////////////////////
329/// Called in connection with a timer timeout
330
332{
333 Info("CatchTimeOut", "%d sec timeout expired (protocol: %s)",
334 fgAuthTO, fgAuthMeth[fSecurity].Data());
335
336 fTimeOut = 1;
337 if (fSocket)
338 fSocket->Close("force");
339
340 return;
341}
342
343////////////////////////////////////////////////////////////////////////////////
344/// Authenticate to remote rootd server. Return kTRUE if
345/// authentication succeeded.
346
348{
349 if (gDebug > 2 && gAuthenticateMutex)
350 Info("Authenticate", "locking mutex (pid: %d)",gSystem->GetPid());
352
353 Bool_t rc = kFALSE;
354 Int_t st = -1;
355 Int_t remMeth = 0, rMth[kMAXSEC], tMth[kMAXSEC] = {0};
356 Int_t meth = 0;
357 char noSupport[80] = { 0 };
358 char triedMeth[80] = { 0 };
359 Int_t ntry = 0;
360
361 TString user, passwd;
363
364 if (gDebug > 2)
365 Info("Authenticate", "enter: fUser: %s", fUser.Data());
366
367 //
368 // Setup timeout timer, if required
369 TTimer *alarm = 0;
370 if (fgAuthTO > 0) {
371 alarm = new TTimer(0, kFALSE);
372 alarm->SetInterruptSyscalls();
373 // The method CatchTimeOut will be called at timeout
374 alarm->Connect("Timeout()", "TAuthenticate", this, "CatchTimeOut()");
375 }
376
377negotia:
378 st = -1;
379 tMth[meth] = 1;
380 ntry++;
381 if (gDebug > 2)
382 Info("Authenticate", "try #: %d", ntry);
383
384 user = "";
385 passwd = "";
386 pwhash = kFALSE;
387
388 // Security level from the list (if not in cleanup mode ...)
391 if (gDebug > 2)
392 Info("Authenticate",
393 "trying authentication: method:%d, default details:%s",
395
396 // Keep track of tried methods in a list
397 if (triedMeth[0] != '\0')
398 (void) strlcat(triedMeth, " ", sizeof(triedMeth) - 1);
399
400 (void) strlcat(triedMeth, fgAuthMeth[fSecurity].Data(), sizeof(triedMeth) - 1);
401
402 // Set environments
404
405 //
406 // Reset timeout variables and start timer
407 fTimeOut = 0;
408 if (fgAuthTO > 0 && alarm) {
409 alarm->Start(fgAuthTO*1000, kTRUE);
410 }
411
412 // Auth calls depend of fSec
413 if (fSecurity == kClear) {
414
415 rc = kFALSE;
416
417 // UsrPwd Authentication
418 user = fgDefaultUser;
419 if (user != "")
421 if (passwd == "") {
422 if (fgPromptUser) {
423 char *u = PromptUser(fRemote);
424 user = u;
425 delete[] u;
426 }
428 }
429 fUser = user;
430 fPasswd = passwd;
431
432 if (!rc) {
433
434 if (fUser != "root")
435 st = ClearAuth(user, passwd, pwhash);
436 } else {
437 Error("Authenticate",
438 "unable to get user name for UsrPwd authentication");
439 }
440
441 }
442
443 // Stop timer
444 if (alarm) alarm->Stop();
445
446 // Flag timeout condition
447 st = (fTimeOut > 0) ? -3 : st;
448
449 //
450 // Analyse the result now ...
451 // Type of action after the analysis:
452 // 0 = return, 1 = negotiation, 2 = send kROOTD_BYE + 3,
453 // 3 = print failure and return
454 Int_t action = 0;
456 Int_t remloc = nmet - ntry;
457 if (gDebug > 0)
458 Info("Authenticate","remloc: %d, ntry: %d, meth: %d, fSecurity: %d",
460 Int_t kind, stat;
461 switch (st) {
462
463 case 1:
464 //
465 // Success
467 if (gDebug > 2)
469 if (fSecContext->IsActive())
472 rc = kTRUE;
473 break;
474
475 case 0:
476 //
477 // Failure
479 if (fVersion < 2) {
480 //
481 // Negotiation not supported by old daemons ...
482 if (gDebug > 2)
483 Info("Authenticate",
484 "negotiation not supported remotely: try next method, if any");
485 if (meth < nmet - 1) {
486 meth++;
487 action = 1;
488 } else {
489 action = 2;
490 }
491 rc = kFALSE;
492 break;
493 }
494 //
495 // Attempt negotiation ...
496 if (fSocket->Recv(stat, kind) < 0) {
497 action = 0;
498 rc = kFALSE;
499 }
500 if (gDebug > 2)
501 Info("Authenticate",
502 "after failed attempt: kind= %d, stat= %d", kind, stat);
503 if (kind == kROOTD_ERR) {
504 action = 2;
505 rc = kFALSE;
506 } else if (kind == kROOTD_NEGOTIA) {
507 if (stat > 0) {
508 int len = 3 * stat;
509 char *answer = new char[len];
510 int nrec = fSocket->Recv(answer, len, kind); // returns user
511 if (nrec < 0) {
512 delete[] answer; // delete buffer while it exit switch() scope
513 action = 0;
514 rc = kFALSE;
515 break;
516 }
517 if (kind != kMESS_STRING)
518 Warning("Authenticate",
519 "strings with accepted methods not received (%d:%d)",
520 kind, nrec);
521 remMeth =
522 sscanf(answer, "%d %d %d %d %d %d", &rMth[0], &rMth[1],
523 &rMth[2], &rMth[3], &rMth[4], &rMth[5]);
524 if (gDebug > 0 && remloc > 0)
525 Info("Authenticate",
526 "remotely allowed methods not yet tried: %s",
527 answer);
528 delete[] answer;
529 } else if (stat == 0) {
530 Info("Authenticate",
531 "no more methods accepted remotely to be tried");
532 action = 3;
533 rc = kFALSE;
534 break;
535 }
536 // If no more local methods, return
537 if (remloc < 1) {
538 action = 2;
539 rc = kFALSE;
540 break;
541 }
542 // Look if a non-tried method matches
543 int i, j;
544 std::string available{};
546 for (i = 0; i < remMeth; i++) {
547 for (j = 0; j < nmet; j++) {
548 if (fHostAuth->GetMethod(j) == rMth[i] && tMth[j] == 0) {
549 meth = j;
550 action = 1;
552 break;
553 }
554 if (i == 0)
555 available += " " + std::to_string(fHostAuth->GetMethod(j));
556 }
557 if (methfound) break;
558 }
559 if (methfound) break;
560 //
561 // No method left to be tried: notify and exit
562 if (gDebug > 0)
563 Warning("Authenticate", "no match with those locally available: %s", available.c_str());
564 action = 2;
565 rc = kFALSE;
566 break;
567 } else { // unknown message code at this stage
568 action = 3;
569 rc = kFALSE;
570 break;
571 }
572 break;
573
574 case -1:
575 //
576 // Method not supported
578 if (gDebug > 2)
579 Info("Authenticate",
580 "method not even started: insufficient or wrong info: %s",
581 "try with next method, if any");
583 nmet--;
584 if (nmet > 0) {
585 action = 1;
586 } else
587 action = 2;
588
589 break;
590
591 case -2:
592 //
593 // Remote host does not accepts connections from local host
595 if (fVersion <= 2)
596 if (gDebug > 2)
597 Warning("Authenticate",
598 "status code -2 not expected from old daemons");
599 rc = kFALSE;
600 break;
601
602 case -3:
603 //
604 // Timeout: we set the method as last one, should the caller
605 // decide to retry, if it will attempt first something else.
606 // (We can not retry directly, because the server will not be
607 // synchronized ...)
609 if (gDebug > 2)
610 Info("Authenticate", "got a timeout");
612 if (meth < nmet - 1) {
613 fTimeOut = 2;
614 } else
615 fTimeOut = 1;
616 rc = kFALSE;
617 break;
618
619 default:
621 if (gDebug > 2)
622 Info("Authenticate", "unknown status code: %d - assume failure",st);
623 rc = kFALSE;
624 action = 0;
625 break;
626 }
627
628 switch (action) {
629 case 1:
630 goto negotia;
631 // No break but we go away anyhow
632 case 2:
633 fSocket->Send("0", kROOTD_BYE);
634 // fallthrough
635 case 3:
636 if (strlen(noSupport) > 0)
637 Info("Authenticate", "attempted methods %s are not supported"
638 " by remote server version", noSupport);
639 Info("Authenticate",
640 "failure: list of attempted methods: %s", triedMeth);
641 AuthError("Authenticate",-1);
642 rc = kFALSE;
643 break;
644 default:
645 break;
646 }
647
648 // Cleanup timer
650
651 return rc;
652
653}
654
655////////////////////////////////////////////////////////////////////////////////
656/// Set default authentication environment. The values are inferred
657/// from fSecurity and fDetails.
658
660{
662
663 if (gDebug > 2)
664 Info("SetEnvironment",
665 "setting environment: fSecurity:%d, fDetails:%s", fSecurity,
666 fDetails.Data());
667
668 // Defaults
672
673 // Decode fDetails, is non empty ...
674 if (fDetails != "") {
675 char usdef[kMAXPATHLEN] = { 0 };
676 char pt[5] = { 0 }, ru[5] = { 0 };
677 Int_t hh = 0, mm = 0;
678 char us[kMAXPATHLEN] = {0}, cp[kMAXPATHLEN] = {0};
679 const char *ptr;
680
682 if ((ptr = strstr(fDetails, "pt:")) != 0) {
683 sscanf(ptr + 3, "%4s %8191s", pt, usdef);
684 } else {
685 if (!strncasecmp(gEnv->GetValue(usrPromptDef,""),"no",2) ||
686 !strncmp(gEnv->GetValue(usrPromptDef,""),"0",1))
687 strncpy(pt,"0",2);
688 else
689 strncpy(pt,"1",2);
690 }
692 if ((ptr = strstr(fDetails, "ru:")) != 0) {
693 sscanf(ptr + 3, "%4s %8191s", ru, usdef);
694 } else {
695 if (!strncasecmp(gEnv->GetValue(usrReUseDef,""),"no",2) ||
696 !strncmp(gEnv->GetValue(usrReUseDef,""),"0",1))
697 strncpy(ru,"0",2);
698 else
699 strncpy(ru,"1",2);
700 }
703 Int_t pd = 0;
704 if ((pd = hours.Index(":")) > -1) {
706 hours.Resize(pd);
707 minutes.Replace(0,pd+1,"");
708 hh = atoi(hours.Data());
709 mm = atoi(minutes.Data());
710 } else {
711 hh = atoi(hours.Data());
712 mm = 0;
713 }
714
715 // Now action depends on method ...
716 if (fSecurity == kClear) {
717 if ((ptr = strstr(fDetails, "us:")) != 0)
718 sscanf(ptr + 3, "%8191s %8191s", us, usdef);
719 if ((ptr = strstr(fDetails, "cp:")) != 0)
720 sscanf(ptr + 3, "%8191s %8191s", cp, usdef);
721 if (gDebug > 2)
722 Info("SetEnvironment", "details:%s, pt:%s, ru:%s, us:%s cp:%s",
723 fDetails.Data(), pt, ru, us, cp);
724 } else {
725 if ((ptr = strstr(fDetails, "us:")) != 0)
726 sscanf(ptr + 3, "%8191s %8191s", us, usdef);
727 if (gDebug > 2)
728 Info("SetEnvironment", "details:%s, pt:%s, ru:%s, us:%s",
729 fDetails.Data(), pt, ru, us);
730 }
731
732 // Set Prompt flag
733 if (!strncasecmp(pt, "yes",3) || !strncmp(pt, "1", 1))
735
736 // Set Expiring date
737 fgExpDate = TDatime();
738 fgExpDate.Set(fgExpDate.Convert() + hh*3600 + mm*60);
739
740 // UnSet Crypt flag for UsrPwd, if requested
741 if (fSecurity == kClear) {
743 if (!strncmp(cp, "no", 2) || !strncmp(cp, "0", 1))
745 }
746 // Build UserDefaults
747 usdef[0] = '\0';
748 // give highest priority to command-line specification
749 if (fUser == "") {
750 if (strlen(us) > 0) snprintf(usdef, kMAXPATHLEN, "%s", us);
751 } else {
753 }
754
755 if (strlen(usdef) > 0) {
757 } else {
758 if (fgUser != "") {
760 } else {
762 if (u)
763 fgDefaultUser = u->fUser;
764 delete u;
765 }
766 }
767 if (fgDefaultUser == "anonymous" || fgDefaultUser == "rootd" ||
768 fgUser != "" || fUser != "") {
769 // when set by user don't prompt for it anymore
771 }
772
773 if (gDebug > 2)
774 Info("SetEnvironment", "usdef:%s", fgDefaultUser.Data());
775 }
776}
777
778////////////////////////////////////////////////////////////////////////////////
779/// Try to get user name and passwd from several sources.
780
783{
784 if (srppwd) {
785 Error("GetUserPasswd", "SRP no longer supported by ROOT");
786 return 1;
787 }
788
789 if (gDebug > 3)
790 Info("GetUserPasswd", "Enter: User: '%s' Hash:%d SRP:%d",
791 user.Data(),(Int_t)pwhash,(Int_t)false);
792
793 // Get user and passwd set via static functions SetUser and SetPasswd.
794 if (user == "" && fgUser != "")
795 user = fgUser;
796
797 if (fgUser != "" && user == fgUser) {
798 if (passwd == "" && fgPasswd != "") {
801 }
802 }
803
804 if (gDebug > 3)
805 Info("GetUserPasswd", "In memory: User: '%s' Hash:%d",
806 user.Data(),(Int_t)pwhash);
807
808 // Check system info for user if still not defined
809 if (user == "") {
811 if (u)
812 user = u->fUser;
813 delete u;
814 if (gDebug > 3)
815 Info("GetUserPasswd", "In memory: User: '%s' Hash:%d",
816 user.Data(),(Int_t)pwhash);
817 }
818
819 // Check ~/.rootnetrc and ~/.netrc files if user was not set via
820 // the static SetUser() method.
821 if (user == "" || passwd == "") {
822 if (gDebug > 3)
823 Info("GetUserPasswd", "Checking .netrc family ...");
824 CheckNetrc(user, passwd, pwhash, /* srppwd */ false);
825 }
826 if (gDebug > 3)
827 Info("GetUserPasswd", "From .netrc family: User: '%s' Hash:%d",
828 user.Data(),(Int_t)pwhash);
829
830 // If user also not set via ~/.rootnetrc or ~/.netrc ask user.
831 if (user == "") {
832 char *p = PromptUser(fRemote);
833 user = p;
834 delete [] p;
835 if (user == "") {
836 Error("GetUserPasswd", "user name not set");
837 return 1;
838 }
839 }
840
841 return 0;
842}
843
844////////////////////////////////////////////////////////////////////////////////
845/// Try to get user name and passwd from the ~/.rootnetrc or
846/// ~/.netrc files. For more info see the version with 4 arguments.
847/// This version is maintained for backward compatability reasons.
848
850{
851 Bool_t hash = false;
852 return CheckNetrc(user, passwd, hash, /* srppwd */ false);
853}
854
855////////////////////////////////////////////////////////////////////////////////
856/// Try to get user name and passwd from the ~/.rootnetrc or
857/// ~/.netrc files. First ~/.rootnetrc is tried, after that ~/.netrc.
858/// These files will only be used when their access masks are 0600.
859/// Returns kTRUE if user and passwd were found for the machine
860/// specified in the URL. If kFALSE, user and passwd are "".
861/// The boolean pwhash is set to kTRUE if the returned passwd is to
862/// be understood as password hash, i.e. if the 'password-hash' keyword
863/// is found in the 'machine' lines; not implemented for 'secure'
864/// and the .netrc file.
865/// The format of these files are:
866///
867/// # this is a comment line
868/// machine `<machine fqdn>` login `<user>` password `<passwd>`
869/// machine `<machine fqdn>` login `<user>` password-hash `<passwd>`
870///
871/// and in addition ~/.rootnetrc also supports:
872///
873/// secure `<machine fqdn>` login `<user>` password `<passwd>`
874///
875/// `<machine fqdn>` may be a domain name or contain the wild card '*'.
876///
877/// for the secure protocols. All lines must start in the first column.
878
881{
882 if (srppwd) {
883 Error("CheckNetrc", "SRP no longer supported by ROOT");
884 return 1;
885 }
886
888 Bool_t first = kTRUE;
890
891 passwd = "";
892 pwhash = kFALSE;
893
894 char *net =
895 gSystem->ConcatFileName(gSystem->HomeDirectory(), ".rootnetrc");
896
897 // Determine FQDN of the host ...
899 if (addr.IsValid())
900 remote = addr.GetHostName();
901
902again:
903 // Only use file when its access rights are 0600
904 FileStat_t buf;
905 if (gSystem->GetPathInfo(net, buf) == 0) {
906#ifdef WIN32
907 // Since Win32 does not have proper protections use file always
908 bool mode0600 = true;
909#else
910 bool mode0600 = (buf.fMode & 0777) == (kS_IRUSR | kS_IWUSR);
911#endif
912 if (R_ISREG(buf.fMode) && !R_ISDIR(buf.fMode) && mode0600) {
913 FILE *fd = fopen(net, "r");
914 char line[256];
915 while (fgets(line, sizeof(line), fd) != 0) {
916 if (line[0] == '#')
917 continue;
918 char word[6][64];
919 int nword = sscanf(line, "%63s %63s %63s %63s %63s %63s",
920 word[0], word[1], word[2], word[3], word[4], word[5]);
921 if (nword != 6)
922 continue;
923 if (strcmp(word[0], "machine"))
924 continue;
925 if (strcmp(word[2], "login"))
926 continue;
927 if (strcmp(word[4], "password") && strcmp(word[4], "password-hash"))
928 continue;
929
930 // Treat the host name found in file as a regular expression
931 // with '*' as a wild card
932 TString href(word[1]);
933 href.ReplaceAll("*",".*");
934 TRegexp rg(href);
935 if (remote.Index(rg) != kNPOS) {
936 if (user == "") {
937 user = word[3];
938 passwd = word[5];
939 if (!strcmp(word[4], "password-hash"))
940 pwhash = kTRUE;
941 result = kTRUE;
942 break;
943 } else {
944 if (!strcmp(word[3], user.Data())) {
945 passwd = word[5];
946 if (!strcmp(word[4], "password-hash"))
947 pwhash = kTRUE;
948 result = kTRUE;
949 break;
950 }
951 }
952 }
953 }
954 fclose(fd);
955 } else
956 Warning("CheckNetrc",
957 "file %s exists but has not 0600 permission", net);
958 }
959 delete [] net;
960
961 if (first && !result) {
963 first = kFALSE;
964 goto again;
965 }
966
967 return result;
968 }
969
970////////////////////////////////////////////////////////////////////////////////
971/// Static method returning the global user.
972
974{
975 return fgUser;
976}
977
978////////////////////////////////////////////////////////////////////////////////
979/// Static method returning the global password hash flag.
980
985
986////////////////////////////////////////////////////////////////////////////////
987/// Static method returning the global SRP password flag.
988
990{
991 return false;
992}
993
994////////////////////////////////////////////////////////////////////////////////
995/// Static method returning default expiring date for new validity contexts
996
1001
1002////////////////////////////////////////////////////////////////////////////////
1003/// Static method returning the default user information.
1004
1006{
1007 return fgDefaultUser;
1008}
1009
1010////////////////////////////////////////////////////////////////////////////////
1011/// Static method returning the principal to be used to init Krb5 tickets.
1012
1014{
1015 ::Error("Krb5Auth", "Kerberos5 is no longer supported by ROOT");
1016 return nullptr;
1017}
1018
1019////////////////////////////////////////////////////////////////////////////////
1020/// Static method returning the authentication reuse settings.
1021
1026
1027////////////////////////////////////////////////////////////////////////////////
1028/// Static method returning the prompt user settings.
1029
1034
1035////////////////////////////////////////////////////////////////////////////////
1036/// Static method returning the method corresponding to idx.
1037
1039{
1041
1042 if (idx < 0 || idx > kMAXSEC-1) {
1043 ::Error("Authenticate::GetAuthMethod", "idx out of bounds (%d)", idx);
1044 idx = 0;
1045 }
1046 return fgAuthMeth[idx];
1047}
1048
1049////////////////////////////////////////////////////////////////////////////////
1050/// Static method returning the method index (which can be used to find
1051/// the method in GetAuthMethod()). Returns -1 in case meth is not found.
1052
1054{
1056
1057 if (meth && meth[0]) {
1058 for (Int_t i = 0; i < kMAXSEC; i++) {
1059 if (!fgAuthMeth[i].CompareTo(meth, TString::kIgnoreCase))
1060 return i;
1061 }
1062 }
1063
1064 return -1;
1065}
1066
1067////////////////////////////////////////////////////////////////////////////////
1068/// Static method to prompt for the user name to be used for authentication
1069/// to rootd. User is asked to type user name.
1070/// Returns user name (which must be deleted by caller) or 0.
1071/// If non-interactive run returns default user.
1072
1074{
1076
1077 const char *user;
1078 if (fgDefaultUser != "")
1079 user = fgDefaultUser;
1080 else
1081 user = gSystem->Getenv("USER");
1082#ifdef R__WIN32
1083 if (!user)
1084 user = gSystem->Getenv("USERNAME");
1085#endif
1086 if (isatty(0) == 0 || isatty(1) == 0) {
1087 ::Warning("TAuthenticate::PromptUser",
1088 "not tty: cannot prompt for user, returning default");
1089 if (strlen(user))
1090 return StrDup(user);
1091 else
1092 return StrDup("None");
1093 }
1094
1095 const char *usrIn = Getline(Form("Name (%s:%s): ", remote, user));
1096 if (usrIn[0]) {
1097 TString usr(usrIn);
1098 usr.Remove(usr.Length() - 1); // get rid of \n
1099 if (!usr.IsNull())
1100 return StrDup(usr);
1101 else
1102 return StrDup(user);
1103 }
1104 return 0;
1105}
1106
1107////////////////////////////////////////////////////////////////////////////////
1108/// Static method to prompt for the user's passwd to be used for
1109/// authentication to rootd. Uses non-echoing command line
1110/// to get passwd. Returns passwd (which must de deleted by caller) or 0.
1111/// If non-interactive run returns -1
1112
1114{
1115 if (isatty(0) == 0 || isatty(1) == 0) {
1116 ::Warning("TAuthenticate::PromptPasswd",
1117 "not tty: cannot prompt for passwd, returning -1");
1118 static char noint[4] = {"-1"};
1119 return StrDup(noint);
1120 }
1121
1122 char buf[128] = "";
1123 const char *pw = buf;
1124 // Get the plugin for the passwd dialog box, if needed
1125 if (!gROOT->IsBatch() && (fgPasswdDialog == (TPluginHandler *)(-1)) &&
1126 gEnv->GetValue("Auth.UsePasswdDialogBox", 1) == 1) {
1127 if ((fgPasswdDialog =
1128 gROOT->GetPluginManager()->FindHandler("TGPasswdDialog"))) {
1129 if (fgPasswdDialog->LoadPlugin() == -1) {
1130 fgPasswdDialog = 0;
1131 ::Warning("TAuthenticate",
1132 "could not load plugin for the password dialog box");
1133 }
1134 }
1135 }
1136 if (fgPasswdDialog && (fgPasswdDialog != (TPluginHandler *)(-1))) {
1137
1138 // Use graphic dialog
1139 fgPasswdDialog->ExecPlugin(3, prompt, buf, 128);
1140
1141 // Wait until the user is done
1142 while (gROOT->IsInterrupted())
1144
1145 } else {
1146 Gl_config("noecho", 1);
1147 pw = Getline(prompt);
1148 Gl_config("noecho", 0);
1149 }
1150
1151 // Final checks
1152 if (pw[0]) {
1153 TString spw(pw);
1154 if (spw.EndsWith("\n"))
1155 spw.Remove(spw.Length() - 1); // get rid of \n
1156 char *rpw = StrDup(spw.Data());
1157 return rpw;
1158 }
1159 return 0;
1160}
1161
1162////////////////////////////////////////////////////////////////////////////////
1163/// Static method returning the globus authorization hook (no longer supported)
1164
1166{
1167 return nullptr;
1168}
1169
1170////////////////////////////////////////////////////////////////////////////////
1171/// Static method returning the RSA public keys.
1172
1174{
1175 key = (key >= 0 && key <= 1) ? key : 0;
1176 return fgRSAPubExport[key].keys;
1177}
1178
1179////////////////////////////////////////////////////////////////////////////////
1180/// Static method returning the RSA initialization flag.
1181
1183{
1184 return fgRSAInit;
1185}
1186
1187////////////////////////////////////////////////////////////////////////////////
1188/// Static method setting the default type of RSA key.
1189
1191{
1192 if (key >= 0 && key <= 1)
1193 fgRSAKey = key;
1194}
1195
1196////////////////////////////////////////////////////////////////////////////////
1197/// Static method setting RSA initialization flag.
1198
1200{
1201 fgRSAInit = init;
1202}
1203
1204////////////////////////////////////////////////////////////////////////////////
1205/// Static method returning the list with authentication details.
1206
1208{
1210
1211 if (!fgAuthInfo)
1212 fgAuthInfo = new TList;
1213 return fgAuthInfo;
1214}
1215
1216////////////////////////////////////////////////////////////////////////////////
1217/// Print error string depending on error code.
1218
1220{
1222
1223 // Make sure it is in range
1224 err = (err < kErrError) ? ((err > -1) ? err : -1) : kErrError;
1225
1226 Int_t erc = err;
1228 TString lasterr = "";
1229 if (err == -1) {
1230 forceprint = kTRUE;
1231 erc = fgLastError;
1232 lasterr = "(last error only; re-run with gDebug > 0 for more details)";
1233 }
1234
1235 if (erc > -1)
1236 if (gDebug > 0 || forceprint) {
1237 if (gRootdErrStr[erc])
1238 ::Error(Form("TAuthenticate::%s", where), "%s %s",
1239 gRootdErrStr[erc], lasterr.Data());
1240 else
1241 ::Error(Form("TAuthenticate::%s", where),
1242 "unknown error code: server must be running a newer ROOT version %s",
1243 lasterr.Data());
1244 }
1245
1246 // Update last error code
1247 fgLastError = err;
1248}
1249
1250////////////////////////////////////////////////////////////////////////////////
1251/// Set global user name to be used for authentication to rootd.
1252
1253void TAuthenticate::SetGlobalUser(const char *user)
1254{
1256
1257 if (fgUser != "")
1258 fgUser = "";
1259
1260 if (user && user[0])
1261 fgUser = user;
1262}
1263
1264////////////////////////////////////////////////////////////////////////////////
1265/// Set global passwd to be used for authentication to rootd.
1266
1268{
1270
1271 if (fgPasswd != "")
1272 fgPasswd = "";
1273
1274 if (passwd && passwd[0])
1275 fgPasswd = passwd;
1276}
1277
1278////////////////////////////////////////////////////////////////////////////////
1279/// Set global passwd hash flag to be used for authentication to rootd.
1280
1285
1286////////////////////////////////////////////////////////////////////////////////
1287/// Set global SRP passwd flag to be used for authentication to rootd.
1288
1290{
1291 ::Error("SetGlobalSRPPwd", "SRP no longer supported by ROOT");
1292}
1293
1294////////////////////////////////////////////////////////////////////////////////
1295/// Set default expiring date for new validity contexts
1296
1301
1302////////////////////////////////////////////////////////////////////////////////
1303/// Set default user name.
1304
1306{
1307 if (fgDefaultUser != "")
1308 fgDefaultUser = "";
1309
1310 if (defaultuser && defaultuser[0])
1312}
1313
1314////////////////////////////////////////////////////////////////////////////////
1315/// Set timeout (active if > 0)
1316
1318{
1319 fgAuthTO = (to <= 0) ? -1 : to;
1320}
1321
1322////////////////////////////////////////////////////////////////////////////////
1323/// Set global AuthReUse flag
1324
1329
1330////////////////////////////////////////////////////////////////////////////////
1331/// Set global PromptUser flag
1332
1337
1338////////////////////////////////////////////////////////////////////////////////
1339/// Set secure authorization function.
1340
1345
1346////////////////////////////////////////////////////////////////////////////////
1347/// Set kerberos5 authorization function. Automatically called when
1348/// libKrb5Auth is loaded.
1349
1351{
1352 ::Error("Krb5Auth", "Kerberos5 is no longer supported by ROOT");
1353}
1354
1355////////////////////////////////////////////////////////////////////////////////
1356/// Set Globus authorization function. Automatically called when
1357/// libGlobusAuth is loaded.
1358
1360{
1361 ::Error("GlobusAuth", "Globus is no longer supported by ROOT");
1362}
1363
1364////////////////////////////////////////////////////////////////////////////////
1365/// SSH client authentication code (no longer supported)
1366
1368{
1369 ::Error("SshAuth", "SSH is no longer supported by ROOT");
1370 return 1;
1371}
1372
1373////////////////////////////////////////////////////////////////////////////////
1374/// Method returning the user to be used for the ssh login (no longer supported)
1375
1376const char *TAuthenticate::GetSshUser(TString /* user */) const
1377{
1378 ::Error("GetSshUser", "SSH is no longer supported by ROOT");
1379 return nullptr;
1380}
1381
1382////////////////////////////////////////////////////////////////////////////////
1383/// Check if 'host' matches 'href':
1384/// this means either equal or "containing" it, even with wild cards *
1385/// in the first field (in the case 'href' is a name, ie not IP address)
1386/// Returns kTRUE if the two matches.
1387
1388Bool_t TAuthenticate::CheckHost(const char *host, const char *href)
1389{
1391
1393
1394 // Both strings should have been defined
1395 if (!host || !href)
1396 return kFALSE;
1397
1398 // 'href' == '*' indicates any 'host' ...
1399 if (!strcmp(href,"*"))
1400 return kTRUE;
1401
1402 // If 'href' contains at a letter or an hyphen it is assumed to be
1403 // a host name. Otherwise a name.
1404 // Check also for wild cards
1405 Bool_t name = kFALSE;
1406 TRegexp rename("[+a-zA-Z]");
1407 Int_t len;
1408 if (rename.Index(href,&len) != -1 || strstr(href,"-"))
1409 name = kTRUE;
1410
1411 // Check also for wild cards
1412 Bool_t wild = kFALSE;
1413 if (strstr(href,"*"))
1414 wild = kTRUE;
1415
1416 // Now build the regular expression for final checking
1418
1419 // host to check
1420 TString theHost(host);
1421 if (!name) {
1423 theHost = addr.GetHostAddress();
1424 if (gDebug > 2)
1425 ::Info("TAuthenticate::CheckHost", "checking host IP: %s", theHost.Data());
1426 }
1427
1428 // Check 'host' against 'rehost'
1429 Ssiz_t pos = rehost.Index(theHost,&len);
1430 if (pos == -1)
1431 retval = kFALSE;
1432
1433 // If IP and no wilds, it should match either
1434 // the beginning or the end of the string
1435 if (!wild) {
1436 if (pos > 0 && pos != (Ssiz_t)(theHost.Length()-strlen(href)))
1437 retval = kFALSE;
1438 }
1439
1440 return retval;
1441}
1442
1443////////////////////////////////////////////////////////////////////////////////
1444/// RFIO authentication (no longer supported)
1445
1447{
1448 ::Error("RfioAuth", "RfioAuth is no longer supported by ROOT");
1449 return -1;
1450}
1451
1452////////////////////////////////////////////////////////////////////////////////
1453/// UsrPwd client authentication code.
1454/// Returns 0 in case authentication failed
1455/// 1 in case of success
1456
1458{
1460
1461 if (gDebug > 2)
1462 Info("ClearAuth", "enter: user: %s (passwd hashed?: %d)",
1463 user.Data(),(Int_t)pwdhash);
1464
1468 Int_t needsalt = 1;
1469 if (pwdhash)
1470 needsalt = 0;
1471 fDetails = TString::Format("pt:%d ru:%d cp:%d us:",
1473 if (gDebug > 2)
1474 Info("ClearAuth", "ru:%d pt:%d cp:%d ns:%d rk:%d",
1476#ifdef R__WIN32
1477 needsalt = 0;
1478#endif
1479 Int_t stat, kind;
1480
1481 if (fVersion > 1) {
1482
1483 //
1484 // New protocol
1485 //
1486 Int_t anon = 0;
1487 TString salt = "";
1488 TString pashash = "";
1489
1490 // Get effective user (fro remote checks in $HOME/.rhosts)
1493 if (pw) {
1494 effUser = TString(pw->fUser);
1495 delete pw;
1496 } else
1497 effUser = user;
1498
1499 // Create options string
1500 int opt = (reuse * kAUTH_REUSE_MSK) + (cryptopt * kAUTH_CRYPT_MSK) +
1502 TString options;
1503 options.Form("%d %ld %s %ld %s", opt,
1504 (Long_t)user.Length(), user.Data(),
1505 (Long_t)effUser.Length(), effUser.Data());
1506
1507 // Check established authentications
1508 kind = kROOTD_USER;
1509 stat = reuse;
1510 Int_t rc = 0;
1511 if ((rc = AuthExists(user, (Int_t) TAuthenticate::kClear, options,
1512 &kind, &stat, &StdCheckSecCtx)) == 1) {
1513 // A valid authentication exists: we are done ...
1514 return 1;
1515 }
1516 if (rc == -2) {
1517 return rc;
1518 }
1519 if (stat == kErrNotAllowed && kind == kROOTD_ERR) {
1520 return 0;
1521 }
1522
1523 if (kind == kROOTD_AUTH && stat == -1) {
1524 if (gDebug > 3)
1525 Info("ClearAuth", "anonymous user");
1526 anon = 1;
1527 cryptopt = 0;
1528 reuse = 0;
1529 needsalt = 0;
1530 }
1531
1532 // The random tag in hex representation
1533 // Protection against reply attacks
1534 char ctag[11] = {0};
1535 if (anon == 0 && cryptopt == 1) {
1536
1537 // Check that we got the right thing ..
1538 if (kind != kROOTD_RSAKEY || stat < 1 || stat > 2 ) {
1539 // Check for errors
1540 if (kind != kROOTD_ERR) {
1541 Warning("ClearAuth",
1542 "problems recvn RSA key flag: got message %d, flag: %d",
1543 kind, stat);
1544 }
1545 return 0;
1546 }
1547 if (gDebug > 3)
1548 Info("ClearAuth", "get key request ...");
1549
1550 // Save type of key
1551 fRSAKey = stat - 1;
1552
1553 // Send the key securely
1555 return 0;
1556
1557 int slen = 0;
1558 if (needsalt) {
1559 // Receive password salt
1560 char *tmpsalt = 0;
1561 if ((slen = SecureRecv(fSocket, 1, fRSAKey, &tmpsalt)) == -1) {
1562 Warning("ClearAuth", "problems secure-receiving salt -"
1563 " may result in corrupted salt");
1564 Warning("ClearAuth", "switch off reuse for this session");
1565 delete [] tmpsalt;
1566 return 0;
1567 }
1568 if (slen) {
1569 // Extract random tag, if there
1570 if (slen > 9) {
1571 int ltmp = slen;
1572 while (ltmp && tmpsalt[ltmp-1] != '#') ltmp--;
1573 if (ltmp) {
1574 if (tmpsalt[ltmp-1] == '#' &&
1575 tmpsalt[ltmp-10] == '#') {
1576 strlcpy(ctag,&tmpsalt[ltmp-10],11);
1577 // We drop the random tag
1578 ltmp -= 10;
1579 tmpsalt[ltmp] = 0;
1580 // Update salt length
1581 slen -= 10;
1582 }
1583 }
1584 if (!tmpsalt[0]) {
1585 // No salt left
1586 needsalt = 0;
1587 slen = 0;
1588 }
1589 }
1590 if (slen)
1591 salt = TString(tmpsalt);
1592 }
1593 delete [] tmpsalt;
1594 if (gDebug > 2)
1595 Info("ClearAuth", "got salt: '%s' (len: %d)", salt.Data(), slen);
1596 } else {
1597 if (gDebug > 2)
1598 Info("ClearAuth", "Salt not required");
1599 char *tmptag = 0;
1600 if (SecureRecv(fSocket, 1, fRSAKey, &tmptag) == -1) {
1601 Warning("ClearAuth", "problems secure-receiving rndmtag -"
1602 " may result in corrupted rndmtag");
1603 }
1604 if (tmptag) {
1605 strlcpy(ctag, tmptag, 11);
1606 delete [] tmptag;
1607 }
1608 }
1609 // We may not have got a salt (if the server may not access it
1610 // or if it needs the full password, like for AFS ...)
1611 if (!slen)
1612 needsalt = 0;
1613 }
1614 // Now get the password either from prompt or from memory, if saved already
1615 if (anon == 1) {
1616
1617 if (fgPasswd.Contains("@")) {
1618 // Anonymous like login with user chosen passwd ...
1619 passwd = fgPasswd;
1620 } else {
1621 // Anonymous like login with automatic passwd generation ...
1623 pw = gSystem->GetUserInfo();
1624 if (pw) {
1625 char *u = StrDup(pw->fUser);
1626 localuser = u;
1627 delete[] u;
1628 }
1629 delete pw;
1630 static TString localFQDN;
1631 if (localFQDN == "") {
1633 if (addr.IsValid())
1634 localFQDN = addr.GetHostName();
1635 }
1636 passwd.Form("%s@%s", localuser.Data(), localFQDN.Data());
1637 if (gDebug > 2)
1638 Info("ClearAuth",
1639 "automatically generated anonymous passwd: %s",
1640 passwd.Data());
1641 }
1642
1643 } else {
1644
1645 if (prompt == 1 || pashash.Length() == 0) {
1646
1647 if (passwd == "") {
1648 TString xp;
1649 xp.Form("%s@%s password: ", user.Data(),fRemote.Data());
1650 char *pwd = PromptPasswd(xp);
1651 passwd = TString(pwd);
1652 delete [] pwd;
1653 if (passwd == "") {
1654 Error("ClearAuth", "password not set");
1655 fSocket->Send("-1", kROOTD_PASS); // Needs this for consistency
1656 return 0;
1657 }
1658 }
1659 if (needsalt && !pwdhash) {
1660#ifndef R__WIN32
1662 if (!pashash.BeginsWith(salt)) {
1663 // not the right version of the crypt function:
1664 // do not send hash
1665 pashash = passwd;
1666 }
1667#else
1668 pashash = passwd;
1669#endif
1670 } else {
1671 pashash = passwd;
1672 }
1673 }
1674
1675 }
1676
1677 // Store password for later use
1678 fgUser = fUser;
1679 fgPwHash = kFALSE;
1680 fPwHash = kFALSE;
1681 fgPasswd = passwd;
1682 fPasswd = passwd;
1683
1684 // Send it to server
1685 if (anon == 0 && cryptopt == 1) {
1686
1687 // Needs to send this for consistency
1688 if (fSocket->Send("\0", kROOTD_PASS) < 0)
1689 return 0;
1690
1691 // Add the random tag received from the server
1692 // (if any); makes packets non re-usable
1693 if (strlen(ctag))
1694 pashash += ctag;
1695
1696 if (SecureSend(fSocket, 1, fRSAKey, pashash.Data()) == -1) {
1697 Warning("ClearAuth", "problems secure-sending pass hash"
1698 " - may result in authentication failure");
1699 return 0;
1700 }
1701 } else {
1702
1703 // Standard technique: invert passwd
1704 if (passwd != "") {
1705 for (int i = 0; i < passwd.Length(); i++) {
1706 char inv = ~passwd(i);
1707 passwd.Replace(i, 1, inv);
1708 }
1709 }
1710 if (fSocket->Send(passwd.Data(), kROOTD_PASS) < 0)
1711 return 0;
1712 }
1713
1714 Int_t nrec = 0;
1715 // Receive username used for login
1716 if ((nrec = fSocket->Recv(stat, kind)) < 0 ) // returns user
1717 return 0;
1718 if (gDebug > 3)
1719 Info("ClearAuth", "after kROOTD_PASS: kind= %d, stat= %d", kind,
1720 stat);
1721
1722 // Check for errors
1723 if (kind == kROOTD_ERR) {
1724 AuthError("ClearAuth", stat);
1725 fgPasswd = "";
1726 return 0;
1727 }
1728
1729 if (kind != kROOTD_PASS || stat < 1)
1730 Warning("ClearAuth",
1731 "problems recvn (user,offset) length (%d:%d bytes:%d)",
1732 kind, stat, nrec);
1733
1734 // Get user and offset
1735 char answer[256];
1736 int reclen = (stat+1 > 256) ? 256 : stat+1;
1737 if ((nrec = fSocket->Recv(answer, reclen, kind)) < 0)
1738 return 0;
1739 if (kind != kMESS_STRING)
1740 Warning("ClearAuth",
1741 "username and offset not received (%d:%d)", kind,
1742 nrec);
1743
1744 // Parse answer
1745 char lUser[128];
1746 Int_t offset = -1;
1747 sscanf(answer, "%127s %d", lUser, &offset);
1748 if (gDebug > 3)
1749 Info("ClearAuth",
1750 "received from server: user: %s, offset: %d (%s)", lUser,
1751 offset, answer);
1752
1753 // Return username
1754 user = lUser;
1755
1756 char *token = 0;
1757 if (reuse == 1 && offset > -1) {
1758 // Receive token
1759 if (cryptopt == 1) {
1760 if (SecureRecv(fSocket, 1, fRSAKey, &token) == -1) {
1761 Warning("ClearAuth",
1762 "problems secure-receiving token -"
1763 " may result in corrupted token");
1764 return 0;
1765 }
1766 } else {
1767 Int_t tlen = 9;
1768 token = new char[tlen];
1769 if (fSocket->Recv(token, tlen, kind) < 0) {
1770 delete [] token;
1771 return 0;
1772 }
1773 if (kind != kMESS_STRING)
1774 Warning("ClearAuth", "token not received (%d:%d)", kind,
1775 nrec);
1776 // Invert token
1777 for (int i = 0; i < (int) strlen(token); i++) {
1778 token[i] = ~token[i];
1779 }
1780
1781 }
1782 if (gDebug > 3)
1783 Info("ClearAuth", "received from server: token: '%s' ",
1784 token);
1785 }
1787 // Create SecContext object
1789 kClear, offset, fDetails, (const char *)token,
1790 fgExpDate, (void *)pwdctx, fRSAKey);
1791
1792 // Release allocated memory ...
1793 if (token)
1794 delete [] token;
1795
1796 // This from remote login
1797 if (fSocket->Recv(stat, kind) < 0)
1798 return 0;
1799
1800
1801 if (kind == kROOTD_AUTH && stat >= 1) {
1802 fgPasswd = "";
1803 if (kind == kROOTD_ERR)
1804 AuthError("ClearAuth", stat);
1805 return 0;
1806 }
1807
1808 } else {
1809
1810 // Old Protocol
1811
1812 // Send username
1813 if (fSocket->Send(user.Data(), kROOTD_USER) < 0)
1814 return 0;
1815
1816 // Get replay from server
1817 if (fSocket->Recv(stat, kind) < 0)
1818 return 0;
1819
1820 // This check should guarantee backward compatibility with a private
1821 // version of rootd used by CDF
1822 if (kind == kROOTD_AUTH && stat == 1) {
1823 fSecContext =
1825 return 1;
1826 }
1827
1828 if (kind == kROOTD_ERR) {
1829 TString server = "sockd";
1830 if (fProtocol.Contains("root"))
1831 server = "rootd";
1832 if (stat == kErrConnectionRefused) {
1833 if (gDebug > 0)
1834 Error("ClearAuth",
1835 "%s@%s does not accept connections from %s@%s",
1836 server.Data(),fRemote.Data(),
1837 fUser.Data(),gSystem->HostName());
1838 return -2;
1839 } else if (stat == kErrNotAllowed) {
1840 if (gDebug > 0)
1841 Error("ClearAuth",
1842 "%s@%s does not accept %s authentication from %s@%s",
1843 server.Data(),fRemote.Data(),
1844 TAuthenticate::fgAuthMeth[0].Data(),
1845 fUser.Data(),gSystem->HostName());
1846 } else
1847 AuthError("ClearAuth", stat);
1848 return 0;
1849 }
1850 // Prepare passwd to send
1851 badpass1:
1852 if (passwd == "") {
1853 TString xp;
1854 xp.Form("%s@%s password: ", user.Data(),fRemote.Data());
1855 char *p = PromptPasswd(xp);
1856 passwd = p;
1857 delete [] p;
1858 if (passwd == "")
1859 Error("ClearAuth", "password not set");
1860 }
1861 if (fUser == "anonymous" || fUser == "rootd") {
1862 if (!passwd.Contains("@")) {
1863 Warning("ClearAuth",
1864 "please use passwd of form: user@host.do.main");
1865 passwd = "";
1866 goto badpass1;
1867 }
1868 }
1869
1870 fgPasswd = passwd;
1871 fPasswd = passwd;
1872
1873 // Invert passwd
1874 if (passwd != "") {
1875 for (int i = 0; i < passwd.Length(); i++) {
1876 char inv = ~passwd(i);
1877 passwd.Replace(i, 1, inv);
1878 }
1879 }
1880 // Send it over the net
1881 if (fSocket->Send(passwd, kROOTD_PASS) < 0)
1882 return 0;
1883
1884 // Get result of attempt
1885 if (fSocket->Recv(stat, kind) < 0) // returns user
1886 return 0;
1887 if (gDebug > 3)
1888 Info("ClearAuth", "after kROOTD_PASS: kind= %d, stat= %d", kind,
1889 stat);
1890
1891 if (kind == kROOTD_AUTH && stat == 1) {
1892 fSecContext =
1894 return 1;
1895 } else {
1896 if (kind == kROOTD_ERR)
1897 AuthError("ClearAuth", stat);
1898 return 0;
1899 }
1900 }
1901 return 0;
1902}
1903
1904////////////////////////////////////////////////////////////////////////////////
1905/// Sets fUser=user and search fgAuthInfo for the entry pertaining to
1906/// (host,user), setting fHostAuth accordingly.
1907/// If no entry is found fHostAuth is not changed
1908
1909THostAuth *TAuthenticate::GetHostAuth(const char *host, const char *user,
1910 Option_t */*opt*/, Int_t *exact)
1911{
1912 if (exact)
1913 *exact = 0;
1914
1915 if (gDebug > 2)
1916 ::Info("TAuthenticate::GetHostAuth", "enter ... %s ... %s", host, user);
1917
1918 // Strip off the servertype, if any
1919 Int_t srvtyp = -1;
1920 TString hostname = host;
1921 if (hostname.Contains(":")) {
1922 char *ps = (char *)strstr(host,":");
1923 if (ps)
1924 srvtyp = atoi(ps+1);
1925 hostname.Remove(hostname.Index(":"));
1926 }
1928 if (strncmp(host,"default",7) && !hostFQDN.Contains("*")) {
1930 if (addr.IsValid())
1931 hostFQDN = addr.GetHostName();
1932 }
1933 TString usr = user;
1934 if (!usr.Length())
1935 usr = "*";
1936 THostAuth *rHA = 0;
1937
1938 // Check list of auth info for already loaded info about this host
1939 TIter *next = new TIter(GetAuthInfo());
1940
1941 THostAuth *ai;
1944 while ((ai = (THostAuth *) (*next)())) {
1945 if (gDebug > 3)
1946 ai->Print("Authenticate::GetHostAuth");
1947
1948 // server
1949 if (!(serverOK = (ai->GetServer() == -1) ||
1950 (ai->GetServer() == srvtyp)))
1951 continue;
1952
1953 // Use default entry if existing and nothing more specific is found
1954 if (!strcmp(ai->GetHost(),"default") && serverOK && notFound)
1955 rHA = ai;
1956
1957 // Check
1958 if (CheckHost(hostFQDN,ai->GetHost()) &&
1959 CheckHost(usr,ai->GetUser()) && serverOK) {
1960 rHA = ai;
1961 notFound = kFALSE;
1962 }
1963
1964 if (hostFQDN == ai->GetHost() &&
1965 usr == ai->GetUser() && srvtyp == ai->GetServer() ) {
1966 rHA = ai;
1967 if (exact)
1968 *exact = 1;
1969 break;
1970 }
1971 }
1972 SafeDelete(next);
1973 return rHA;
1974}
1975
1976////////////////////////////////////////////////////////////////////////////////
1977/// Checks if a THostAuth with exact match for {host,user} exists
1978/// in the fgAuthInfo list
1979/// Returns pointer to it or 0
1980
1981THostAuth *TAuthenticate::HasHostAuth(const char *host, const char *user,
1982 Option_t */*opt*/)
1983{
1984 if (gDebug > 2)
1985 ::Info("TAuthenticate::HasHostAuth", "enter ... %s ... %s", host, user);
1986
1987 // Strip off the servertype, if any
1988 Int_t srvtyp = -1;
1989 TString hostFQDN = host;
1990 if (hostFQDN.Contains(":")) {
1991 char *ps = (char *)strstr(host,":");
1992 if (ps)
1993 srvtyp = atoi(ps+1);
1994 hostFQDN.Remove(hostFQDN.Index(":"));
1995 }
1996 if (strncmp(host,"default",7) && !hostFQDN.Contains("*")) {
1998 if (addr.IsValid())
1999 hostFQDN = addr.GetHostName();
2000 }
2001
2002 TIter *next = new TIter(GetAuthInfo());
2003 THostAuth *ai;
2004 while ((ai = (THostAuth *) (*next)())) {
2005
2006 if (hostFQDN == ai->GetHost() &&
2007 !strcmp(user, ai->GetUser()) && srvtyp == ai->GetServer()) {
2008 SafeDelete(next);
2009 return ai;
2010 }
2011 }
2012 SafeDelete(next);
2013 return 0;
2014}
2015
2016////////////////////////////////////////////////////////////////////////////////
2017/// Expands include directives found in fexp files
2018/// The expanded, temporary file, is pointed to by 'ftmp'
2019/// and should be already open. To be called recursively.
2020
2022{
2023 FILE *fin;
2024 char line[kMAXPATHLEN];
2025 char cinc[20], fileinc[kMAXPATHLEN];
2026
2027 if (gDebug > 2)
2028 ::Info("TAuthenticate::FileExpand", "enter ... '%s' ... 0x%zx", fexp, (size_t)ftmp);
2029
2030 fin = fopen(fexp, "r");
2031 if (fin == 0)
2032 return;
2033
2034 while (fgets(line, sizeof(line), fin) != 0) {
2035 // Skip comment lines
2036 if (line[0] == '#')
2037 continue;
2038 if (line[strlen(line) - 1] == '\n')
2039 line[strlen(line) - 1] = '\0';
2040 if (gDebug > 2)
2041 ::Info("TAuthenticate::FileExpand", "read line ... '%s'", line);
2042 int nw = sscanf(line, "%19s %8191s", cinc, fileinc);
2043 if (nw < 1)
2044 continue; // Not enough info in this line
2045 if (strcmp(cinc, "include") != 0) {
2046 // copy line in temporary file
2047 fprintf(ftmp, "%s\n", line);
2048 } else {
2049
2050 // Drop quotes or double quotes, if any
2051 TString ln(line);
2052 ln.ReplaceAll("\"",1,"",0);
2053 ln.ReplaceAll("'",1,"",0);
2054 sscanf(ln.Data(), "%19s %8191s", cinc, fileinc);
2055
2056 // support environment directories ...
2057 if (fileinc[0] == '$') {
2060 if (edir.Contains("/")) {
2061 edir.Remove(edir.Index("/"));
2062 edir.Remove(0,1);
2063 if (gSystem->Getenv(edir.Data())) {
2064 finc.Remove(0,1);
2065 finc.ReplaceAll(edir.Data(),gSystem->Getenv(edir.Data()));
2066 fileinc[0] = '\0';
2068 fileinc[kMAXPATHLEN-1] = '\0';
2069 }
2070 }
2071 }
2072
2073 // open (expand) file in temporary file ...
2074 if (fileinc[0] == '~') {
2075 // needs to expand
2076 int flen =
2078 char *ffull = new char[flen];
2079 snprintf(ffull, flen, "%s/%s", gSystem->HomeDirectory(), fileinc + 1);
2081 delete [] ffull;
2082 }
2083 // Check if file exist and can be read ... ignore if not ...
2086 } else {
2087 ::Warning("TAuthenticate::FileExpand",
2088 "file specified by 'include' cannot be open or read (%s)",
2089 fileinc);
2090 }
2091 }
2092 }
2093 fclose(fin);
2094}
2095
2096////////////////////////////////////////////////////////////////////////////////
2097/// Determine default authentication details for method 'sec' and user 'usr'.
2098/// Checks .rootrc family files. Returned string must be deleted by the user.
2099
2100char *TAuthenticate::GetDefaultDetails(int sec, int opt, const char *usr)
2101{
2102 char temp[kMAXPATHLEN] = { 0 };
2103 const char copt[2][5] = { "no", "yes" };
2104
2105 if (gDebug > 2)
2106 ::Info("TAuthenticate::GetDefaultDetails",
2107 "enter ... %d ...pt:%d ... '%s'", sec, opt, usr);
2108
2109 if (opt < 0 || opt > 1)
2110 opt = 1;
2111
2112 // UsrPwd
2113 if (sec == TAuthenticate::kClear) {
2114 if (!usr[0] || !strncmp(usr,"*",1))
2115 usr = gEnv->GetValue("UsrPwd.Login", "");
2116 snprintf(temp, kMAXPATHLEN, "pt:%s ru:%s cp:%s us:%s",
2117 gEnv->GetValue("UsrPwd.LoginPrompt", copt[opt]),
2118 gEnv->GetValue("UsrPwd.ReUse", "1"),
2119 gEnv->GetValue("UsrPwd.Crypt", "1"), usr);
2120 }
2121
2122 if (gDebug > 2)
2123 ::Info("TAuthenticate::GetDefaultDetails", "returning ... %s", temp);
2124
2125 return StrDup(temp);
2126}
2127
2128////////////////////////////////////////////////////////////////////////////////
2129/// Remove THostAuth instance from the list
2130
2132{
2133 GetAuthInfo()->Remove(ha);
2134 // ... destroy it
2135 delete ha;
2136}
2137
2138////////////////////////////////////////////////////////////////////////////////
2139/// Print info about the authentication sector.
2140/// If 'opt' contains 's' or 'S' prints information about established TSecContext,
2141/// else prints information about THostAuth
2142
2144{
2145 TString sopt(opt);
2146
2147 if (sopt.Contains("s", TString::kIgnoreCase)) {
2148
2149 // Print established security contexts
2150 TIter next(gROOT->GetListOfSecContexts());
2151 TSecContext *sc = 0;
2152 while ((sc = (TSecContext *)next()))
2153 sc->Print();
2154
2155 } else {
2156
2157 ::Info("::Print", " +--------------------------- BEGIN --------------------------------+");
2158 ::Info("::Print", " + +");
2159 ::Info("::Print", " + List fgAuthInfo has %4d members +",
2160 GetAuthInfo()->GetSize());
2161 ::Info("::Print", " + +");
2162 ::Info("::Print", " +------------------------------------------------------------------+");
2163 TIter next(GetAuthInfo());
2164 THostAuth *ai;
2165 while ((ai = (THostAuth *)next())) {
2166 ai->Print();
2167 ai->PrintEstablished();
2168 }
2169 ::Info("::Print", " +---------------------------- END ---------------------------------+");
2170 }
2171}
2172
2173////////////////////////////////////////////////////////////////////////////////
2174/// Check if we have a valid established sec context in memory
2175/// Retrieves relevant info and negotiates with server.
2176/// options = "Opt,strlen(username),username.Data()"
2177/// message = kROOTD_USER, ...
2178
2180 Int_t *message, Int_t *rflag,
2182{
2183 // Welcome message, if requested ...
2184 if (gDebug > 2)
2185 Info("AuthExists","%d: enter: msg: %d options: '%s'",
2186 method,*message, options);
2187
2188 // Look for an existing security context matching this request
2190
2191 // First in the local list
2192 TIter next(fHostAuth->Established());
2194 while ((secctx = (TRootSecContext *)next())) {
2195 if (secctx->GetMethod() == method) {
2196 if (fRemote == secctx->GetHost()) {
2197 if (checksecctx &&
2198 (*checksecctx)(username,secctx) == 1)
2199 break;
2200 }
2201 }
2202 }
2203
2204 // If nothing found, try the all list
2205 if (!secctx) {
2206 next = TIter(gROOT->GetListOfSecContexts());
2207 while ((secctx = (TRootSecContext *)next())) {
2208 if (secctx->GetMethod() == method) {
2209 if (fRemote == secctx->GetHost()) {
2210 if (checksecctx &&
2211 (*checksecctx)(username,secctx) == 1) {
2212 notHA = kTRUE;
2213 break;
2214 }
2215 }
2216 }
2217 }
2218 }
2219
2220 // If we have been given a valid sec context retrieve some info
2221 Int_t offset = -1;
2222 TString token;
2223 if (secctx) {
2224 offset = secctx->GetOffSet();
2225 token = secctx->GetToken();
2226 if (gDebug > 2)
2227 Info("AuthExists",
2228 "found valid TSecContext: offset: %d token: '%s'",
2229 offset, token.Data());
2230 }
2231
2232 // Prepare string to be sent to the server
2233 TString sstr;
2234 sstr.Form("%d %d %s", fgProcessID, offset, options);
2235
2236 // Send message
2237 if (fSocket->Send(sstr, *message) < 0)
2238 return -2;
2239
2240 Int_t reuse = *rflag;
2241 if (reuse == 1 && offset > -1) {
2242
2243 // Receive result of checking offset
2244 // But only for recent servers
2245 // NB: not backward compatible with dev version 4.00.02: switch
2246 // off 'reuse' for such servers to avoid hanging at this point.
2248 Bool_t oldsrv = ((fProtocol.BeginsWith("root") && rproto == 9));
2249 Int_t stat = 1, kind;
2250 if (!oldsrv) {
2251 if (fSocket->Recv(stat, kind) < 0)
2252 return -2;
2253 if (kind != kROOTD_AUTH)
2254 Warning("AuthExists","protocol error: expecting %d got %d"
2255 " (value: %d)",kROOTD_AUTH,kind,stat);
2256 }
2257
2258 if (stat > 0) {
2259 if (gDebug > 2)
2260 Info("AuthExists","offset OK");
2261
2262 Int_t rsaKey = secctx->GetRSAKey();
2263 if (gDebug > 2)
2264 Info("AuthExists", "key type: %d", rsaKey);
2265
2266 if (rsaKey > -1) {
2267
2268 // Recent servers send a random tag in stat
2269 // It has to be signed too
2270 if (stat > 1) {
2271 // Create hex from tag
2272 char tag[9] = {0};
2273 snprintf(tag, 9, "%08x",stat);
2274 // Add to token
2275 token += tag;
2276 }
2277
2278 // Send token encrypted
2279 if (SecureSend(fSocket, 1, rsaKey, token) == -1) {
2280 Warning("AuthExists", "problems secure-sending token %s",
2281 "- may trigger problems in proofing Id ");
2282 return -2;
2283 }
2284 } else {
2285 // Send inverted
2286 for (int i = 0; i < token.Length(); i++) {
2287 char inv = ~token(i);
2288 token.Replace(i, 1, inv);
2289 }
2290 if (fSocket->Send(token, kMESS_STRING) < 0)
2291 return -2;
2292 }
2293 } else {
2294 if (gDebug > 0)
2295 Info("AuthExists","offset not OK - rerun authentication");
2296 // If the sec context was not valid, deactivate it ...
2297 if (secctx)
2298 secctx->DeActivate("");
2299 }
2300 }
2301
2302 Int_t stat, kind;
2303 if (fSocket->Recv(stat, kind) < 0)
2304 return -2;
2305 if (gDebug > 3)
2306 Info("AuthExists","%d: after msg %d: kind= %d, stat= %d",
2307 method,*message, kind, stat);
2308
2309 // Return flags
2310 *message = kind;
2311 *rflag = stat;
2312
2313 if (kind == kROOTD_ERR) {
2314 TString server = "sockd";
2316 server = "rootd";
2317 if (stat == kErrConnectionRefused) {
2318 Error("AuthExists","%s@%s does not accept connections from %s@%s",
2319 server.Data(),fRemote.Data(),fUser.Data(),gSystem->HostName());
2320 return -2;
2321 } else if (stat == kErrNotAllowed) {
2322 if (gDebug > 0)
2323 Info("AuthExists",
2324 "%s@%s does not accept %s authentication from %s@%s",
2325 server.Data(),fRemote.Data(), fgAuthMeth[method].Data(),
2326 fUser.Data(),gSystem->HostName());
2327 } else
2328 AuthError("AuthExists", stat);
2329
2330 // If the sec context was not valid, deactivate it ...
2331 if (secctx)
2332 secctx->DeActivate("");
2333 return 0;
2334 }
2335
2336 if (kind == kROOTD_AUTH && stat >= 1) {
2337 if (!secctx)
2338 secctx =
2340 if (gDebug > 3) {
2341 if (stat == 1)
2342 Info("AuthExists", "valid authentication exists");
2343 if (stat == 2)
2344 Info("AuthExists", "valid authentication exists: offset changed");
2345 if (stat == 3)
2346 Info("AuthExists", "remote access authorized by /etc/hosts.equiv");
2347 if (stat == 4)
2348 Info("AuthExists", "no authentication required remotely");
2349 }
2350
2351 if (stat == 2) {
2352 int newOffSet;
2353 // Receive new offset ...
2354 if (fSocket->Recv(newOffSet, kind) < 0)
2355 return -2;
2356 // ... and save it
2357 secctx->SetOffSet(newOffSet);
2358 }
2359
2361 // Add it to local list for later use (if not already there)
2362 if (notHA)
2364 return 1;
2365 }
2366 return 0;
2367}
2368
2369////////////////////////////////////////////////////////////////////////////////
2370/// Initialize random machine using seed from /dev/urandom
2371/// (or current time if /dev/urandom not available).
2372
2374{
2375 static Bool_t notinit = kTRUE;
2376
2377 if (notinit) {
2378 const char *randdev = "/dev/urandom";
2379 Int_t fd;
2380 UInt_t seed;
2381 if ((fd = open(randdev, O_RDONLY)) != -1) {
2382 if (gDebug > 2)
2383 ::Info("InitRandom", "taking seed from %s", randdev);
2384 if (read(fd, &seed, sizeof(seed)) != sizeof(seed))
2385 ::Warning("InitRandom", "could not read seed from %s", randdev);
2386 close(fd);
2387 } else {
2388 if (gDebug > 2)
2389 ::Info("InitRandom", "%s not available: using time()", randdev);
2390 seed = time(0); //better use times() + win32 equivalent
2391 }
2392 srand(seed);
2393 notinit = kFALSE;
2394 }
2395}
2396
2397////////////////////////////////////////////////////////////////////////////////
2398/// Generate a valid pair of private/public RSA keys to protect for
2399/// authentication token exchange
2400
2402{
2403 if (gDebug > 2)
2404 Info("GenRSAKeys", "enter");
2405
2406 if (fgRSAInit == 1) {
2407 if (gDebug > 2)
2408 Info("GenRSAKeys", "Keys prviously generated - return");
2409 }
2410
2411 // This is for dynamic loads ...
2412 TString lib = "libRsa";
2413
2414 // This is the local RSA implementation
2415 if (!TRSA_fun::RSA_genprim()) {
2416 char *p;
2417 if ((p = gSystem->DynamicPathName(lib, kTRUE))) {
2418 delete [] p;
2419 gSystem->Load(lib);
2420 }
2421 }
2422
2423 // Init random machine
2425
2426#ifdef R__SSL
2427 if (fgRSAKey == 1) {
2428 // Generate also the SSL key
2429 if (gDebug > 2)
2430 Info("GenRSAKeys","SSL: Generate Blowfish key");
2431
2432 // Init SSL ...
2434
2435 // ... and its error strings
2437
2438 // Load Ciphers
2440
2441 // Number of bits for key
2442 Int_t nbits = gEnv->GetValue("SSL.BFBits",256);
2443
2444 // Minimum is 128
2445 nbits = (nbits >= 128) ? nbits : 128;
2446
2447 // Max to limit size of buffers to 15912 (internal limitation)
2448 nbits = (nbits <= 15912) ? nbits : 15912;
2449
2450 // Closer Number of chars
2451 Int_t klen = nbits / 8 ;
2452
2453 // Init random engine
2454 char *rbuf = GetRandString(0,klen);
2456
2457 // This is what we export
2458 fgRSAPubExport[1].len = klen;
2459 fgRSAPubExport[1].keys = rbuf;
2460 if (gDebug > 2)
2461 Info("GenRSAKeys","SSL: BF key length: %d", fgRSAPubExport[1].len);
2462
2463 // Now set the key locally in BF form
2464 BF_set_key(&fgBFKey, klen, (const unsigned char *)rbuf);
2465 }
2466#endif
2467
2468 // Sometimes some bunch is not decrypted correctly
2469 // That's why we make retries to make sure that encryption/decryption
2470 // works as expected
2471 Bool_t notOk = 1;
2473 Int_t l_n = 0, l_d = 0;
2475#if R__RSADE
2476 Int_t l_e;
2477 char buf[rsa_STRLEN];
2478#endif
2479
2480 Int_t nAttempts = 0;
2482 Int_t thePrimeExp = kPRIMEEXP; // Prime probability = 1-0.5^thePrimeExp
2483 while (notOk && nAttempts < kMAXRSATRIES) {
2484
2485 nAttempts++;
2486 if (gDebug > 2 && nAttempts > 1) {
2487 Info("GenRSAKeys", "retry no. %d",nAttempts);
2488 srand(auth_rand());
2489 }
2490
2491 // Valid pair of primes
2494
2495 // Retry if equal
2496 Int_t nPrimes = 0;
2497 while (TRSA_fun::RSA_cmp()(&p1, &p2) == 0 && nPrimes < kMAXRSATRIES) {
2498 nPrimes++;
2499 if (gDebug > 2)
2500 Info("GenRSAKeys", "equal primes: regenerate (%d times)",nPrimes);
2501 srand(auth_rand());
2504 }
2505#if R__RSADEB
2506 if (gDebug > 3) {
2508 Info("GenRSAKeys", "local: p1: '%s' ", buf);
2510 Info("GenRSAKeys", "local: p2: '%s' ", buf);
2511 }
2512#endif
2513 // Generate keys
2514 if (TRSA_fun::RSA_genrsa()(p1, p2, &rsa_n, &rsa_e, &rsa_d)) {
2515 if (gDebug > 2 && nAttempts > 1)
2516 Info("GenRSAKeys"," genrsa: unable to generate keys (%d)",
2517 nAttempts);
2518 continue;
2519 }
2520
2521 // Get equivalent strings and determine their lengths
2523 l_n = strlen(buf_n);
2525#if R__RSADEB
2526 l_e = strlen(buf_e);
2527#endif
2529 l_d = strlen(buf_d);
2530
2531#if R__RSADEB
2532 if (gDebug > 3) {
2533 Info("GenRSAKeys", "local: n: '%s' length: %d", buf_n, l_n);
2534 Info("GenRSAKeys", "local: e: '%s' length: %d", buf_e, l_e);
2535 Info("GenRSAKeys", "local: d: '%s' length: %d", buf_d, l_d);
2536 }
2537#endif
2538 if (TRSA_fun::RSA_cmp()(&rsa_n, &rsa_e) <= 0)
2539 continue;
2540 if (TRSA_fun::RSA_cmp()(&rsa_n, &rsa_d) <= 0)
2541 continue;
2542
2543 // Now we try the keys
2544 char test[2 * rsa_STRLEN] = "ThisIsTheStringTest01203456-+/";
2545 Int_t lTes = 31;
2546 char *tdum = GetRandString(0, lTes - 1);
2547 strlcpy(test, tdum, lTes+1);
2548 delete [] tdum;
2549 char buf[2 * rsa_STRLEN];
2550 if (gDebug > 3)
2551 Info("GenRSAKeys", "local: test string: '%s' ", test);
2552
2553 // Private/Public
2554 strlcpy(buf, test, lTes+1);
2555
2556 // Try encryption with private key
2557 int lout = TRSA_fun::RSA_encode()(buf, lTes, rsa_n, rsa_e);
2558 if (gDebug > 3)
2559 Info("GenRSAKeys",
2560 "local: length of crypted string: %d bytes", lout);
2561
2562 // Try decryption with public key
2564 buf[lTes] = 0;
2565 if (gDebug > 3)
2566 Info("GenRSAKeys", "local: after private/public : '%s' ", buf);
2567
2568 if (strncmp(test, buf, lTes))
2569 continue;
2570
2571 // Public/Private
2572 strlcpy(buf, test, lTes+1);
2573
2574 // Try encryption with public key
2576 if (gDebug > 3)
2577 Info("GenRSAKeys", "local: length of crypted string: %d bytes ",
2578 lout);
2579
2580 // Try decryption with private key
2582 buf[lTes] = 0;
2583 if (gDebug > 3)
2584 Info("GenRSAKeys", "local: after public/private : '%s' ", buf);
2585
2586 if (strncmp(test, buf, lTes))
2587 continue;
2588
2589 notOk = 0;
2590 }
2591
2592 // Save Private key
2595
2596 // Save Public key
2599
2600#if R__RSADEB
2601 if (gDebug > 2) {
2602 // Determine their lengths
2603 Info("GenRSAKeys", "local: generated keys are:");
2604 Info("GenRSAKeys", "local: n: '%s' length: %d", buf_n, l_n);
2605 Info("GenRSAKeys", "local: e: '%s' length: %d", buf_e, l_e);
2606 Info("GenRSAKeys", "local: d: '%s' length: %d", buf_d, l_d);
2607 }
2608#endif
2609 // Export form
2610 if (fgRSAPubExport[0].keys) {
2611 delete [] fgRSAPubExport[0].keys;
2612 fgRSAPubExport[0].len = 0;
2613 }
2614 fgRSAPubExport[0].len = l_n + l_d + 4;
2615 fgRSAPubExport[0].keys = new char[fgRSAPubExport[0].len];
2616
2617 fgRSAPubExport[0].keys[0] = '#';
2618 memcpy(fgRSAPubExport[0].keys + 1, buf_n, l_n);
2619 fgRSAPubExport[0].keys[l_n + 1] = '#';
2620 memcpy(fgRSAPubExport[0].keys + l_n + 2, buf_d, l_d);
2621 fgRSAPubExport[0].keys[l_n + l_d + 2] = '#';
2622 fgRSAPubExport[0].keys[l_n + l_d + 3] = 0;
2623#if R__RSADEB
2624 if (gDebug > 2)
2625 Info("GenRSAKeys", "local: export pub: '%s'", fgRSAPubExport[0].keys);
2626#else
2627 if (gDebug > 2)
2628 Info("GenRSAKeys", "local: export pub length: %d bytes", fgRSAPubExport[0].len);
2629#endif
2630
2631 // Set availability flag
2632 fgRSAInit = 1;
2633
2634 return 0;
2635}
2636
2637////////////////////////////////////////////////////////////////////////////////
2638/// Allocates and fills a 0 terminated buffer of length len+1 with
2639/// len random characters.
2640/// Returns pointer to the buffer (to be deleted by the caller)
2641/// opt = 0 any non dangerous char
2642/// 1 letters and numbers (upper and lower case)
2643/// 2 hex characters (upper and lower case)
2644
2646{
2647 unsigned int iimx[4][4] = {
2648 {0x0, 0xffffff08, 0xafffffff, 0x2ffffffe}, // opt = 0
2649 {0x0, 0x3ff0000, 0x7fffffe, 0x7fffffe}, // opt = 1
2650 {0x0, 0x3ff0000, 0x7e, 0x7e}, // opt = 2
2651 {0x0, 0x3ffc000, 0x7fffffe, 0x7fffffe} // opt = 3
2652 };
2653
2654 const char *cOpt[4] = { "Any", "LetNum", "Hex", "Crypt" };
2655
2656 // Default option 0
2657 if (opt < 0 || opt > 2) {
2658 opt = 0;
2659 if (gDebug > 2)
2660 Info("GetRandString", "unknown option: %d : assume 0", opt);
2661 }
2662 if (gDebug > 2)
2663 Info("GetRandString", "enter ... len: %d %s", len, cOpt[opt]);
2664
2665 // Allocate buffer
2666 char *buf = new char[len + 1];
2667
2668 // Init random machine (if needed)
2670
2671 // randomize
2672 Int_t k = 0;
2673 Int_t i, j, l, m, frnd;
2674 while (k < len) {
2675 frnd = auth_rand();
2676 for (m = 7; m < 32; m += 7) {
2677 i = 0x7F & (frnd >> m);
2678 j = i / 32;
2679 l = i - j * 32;
2680 if ((iimx[opt][j] & (1 << l))) {
2681 buf[k] = i;
2682 k++;
2683 }
2684 if (k == len)
2685 break;
2686 }
2687 }
2688
2689 // null terminated
2690 buf[len] = 0;
2691 if (gDebug > 3)
2692 Info("GetRandString", "got '%s' ", buf);
2693
2694 return buf;
2695}
2696
2697////////////////////////////////////////////////////////////////////////////////
2698/// Encode null terminated str using the session private key indicated by enc
2699/// and sends it over the network
2700/// Returns number of bytes sent, or -1 in case of error.
2701/// enc = 1 for private encoding, enc = 2 for public encoding
2702
2704 Int_t key, const char *str)
2705{
2706 char buftmp[kMAXSECBUF];
2707 char buflen[20];
2708
2709 if (gDebug > 2)
2710 ::Info("TAuthenticate::SecureSend", "local: enter ... (enc: %d)", enc);
2711
2712 Int_t slen = strlen(str) + 1;
2713 Int_t ttmp = 0;
2714 Int_t nsen = -1;
2715
2716 if (key == 0) {
2717 strlcpy(buftmp, str, slen+1);
2718
2719 if (enc == 1)
2721 fgRSAPriKey.e);
2722 else if (enc == 2)
2724 fgRSAPubKey.e);
2725 else
2726 return nsen;
2727 } else if (key == 1) {
2728
2729#ifdef R__SSL
2730 ttmp = strlen(str);
2731 if ((ttmp % 8) > 0) // It should be a multiple of 8!
2732 ttmp = ((ttmp + 8)/8) * 8;
2733 unsigned char iv[8];
2734 memset((void *)&iv[0],0,8);
2735 BF_cbc_encrypt((const unsigned char *)str, (unsigned char *)buftmp,
2736 strlen(str), &fgBFKey, iv, BF_ENCRYPT);
2737#else
2738 if (gDebug > 0)
2739 ::Info("TAuthenticate::SecureSend","not compiled with SSL support:"
2740 " you should not have got here!");
2741#endif
2742 } else {
2743 if (gDebug > 0)
2744 ::Info("TAuthenticate::SecureSend","unknown key type (%d)",key);
2745 return nsen;
2746 }
2747
2748 snprintf(buflen,20,"%d",ttmp);
2749 if (sock->Send(buflen, kROOTD_ENCRYPT) < 0)
2750 return -1;
2751 nsen = sock->SendRaw(buftmp, ttmp);
2752 if (gDebug > 3)
2753 ::Info("TAuthenticate::SecureSend",
2754 "local: sent %d bytes (expected: %d)", nsen,ttmp);
2755
2756 return nsen;
2757}
2758
2759////////////////////////////////////////////////////////////////////////////////
2760/// Receive str from sock and decode it using key indicated by key type
2761/// Return number of received bytes or -1 in case of error.
2762/// dec = 1 for private decoding, dec = 2 for public decoding
2763
2765{
2766
2767 char buftmp[kMAXSECBUF];
2768 char buflen[20];
2769
2770 Int_t nrec = -1;
2771 // We must get a pointer ...
2772 if (!str)
2773 return nrec;
2774
2775 Int_t kind;
2776 if (sock->Recv(buflen, 20, kind) < 0)
2777 return -1;
2778 Int_t len = atoi(buflen);
2779 if (gDebug > 3)
2780 ::Info("TAuthenticate::SecureRecv", "got len '%s' %d (msg kind: %d)",
2781 buflen, len, kind);
2782 if (len == 0) {
2783 return len;
2784 }
2785 if (!strncmp(buflen, "-1", 2))
2786 return nrec;
2787
2788 // Receive buffer
2789 if ((nrec = sock->RecvRaw(buftmp, len)) < 0)
2790 return nrec;
2791 if (key == 0) {
2792 if (dec == 1)
2794 else if (dec == 2)
2796 else
2797 return -1;
2798
2799 // Prepare output
2800 const size_t strSize = strlen(buftmp) + 1;
2801 *str = new char[strSize];
2802 if (*str == nullptr) {
2803 if (gDebug > 0)
2804 ::Info("TAuthenticate::SecureRecv","Memory allocation error size (%ld)", (long) strSize);
2805 return -1;
2806 }
2807 strlcpy(*str, buftmp, strSize);
2808
2809 } else if (key == 1) {
2810#ifdef R__SSL
2811 unsigned char iv[8];
2812 memset((void *)&iv[0],0,8);
2813 *str = new char[nrec + 1];
2814 BF_cbc_encrypt((const unsigned char *)buftmp, (unsigned char *)(*str),
2816 (*str)[nrec] = '\0';
2817#else
2818 if (gDebug > 0)
2819 ::Info("TAuthenticate::SecureRecv","not compiled with SSL support:"
2820 " you should not have got here!");
2821#endif
2822 } else {
2823 if (gDebug > 0)
2824 ::Info("TAuthenticate::SecureRecv","unknown key type (%d)",key);
2825 return -1;
2826 }
2827
2828 nrec= strlen(*str);
2829
2830 return nrec;
2831}
2832
2833////////////////////////////////////////////////////////////////////////////////
2834/// Store RSA public keys from export string rsaPubExport.
2835
2837 R__rsa_NUMBER &rsa_d, char **rsassl)
2838{
2839 if (!rsaPubExport)
2840 return -1;
2841
2842 if (gDebug > 2)
2843 ::Info("TAuthenticate::DecodeRSAPublic",
2844 "enter: string length: %ld bytes", (Long_t)strlen(rsaPubExport));
2845
2846 char str[kMAXPATHLEN] = { 0 };
2848 if (klen > kMAXPATHLEN - 1) {
2849 ::Info("TAuthenticate::DecodeRSAPublic",
2850 "key too long (%d): truncate to %d",klen,kMAXPATHLEN);
2851 klen = kMAXPATHLEN - 1;
2852 }
2853 memcpy(str, rsaPubExport, klen);
2854 str[klen] ='\0';
2855
2856 Int_t keytype = -1;
2857
2858 if (klen > 0) {
2859
2860 // Skip spaces at beginning, if any
2861 int k = 0;
2862 while (str[k] == 32) k++;
2863
2864 if (str[k] == '#') {
2865
2866 keytype = 0;
2867
2868 // The format is #<hex_n>#<hex_d>#
2869 char *pd1 = strstr(str, "#");
2870 char *pd2 = pd1 ? strstr(pd1 + 1, "#") : (char *)0;
2871 char *pd3 = pd2 ? strstr(pd2 + 1, "#") : (char *)0;
2872 if (pd1 && pd2 && pd3) {
2873 // Get <hex_n> ...
2874 int l1 = (int) (pd2 - pd1 - 1);
2875 char *rsa_n_exp = new char[l1 + 1];
2876 strlcpy(rsa_n_exp, pd1 + 1, l1+1);
2877 if (gDebug > 2)
2878 ::Info("TAuthenticate::DecodeRSAPublic",
2879 "got %ld bytes for rsa_n_exp", (Long_t)strlen(rsa_n_exp));
2880 // Now <hex_d>
2881 int l2 = (int) (pd3 - pd2 - 1);
2882 char *rsa_d_exp = new char[l2 + 1];
2883 strlcpy(rsa_d_exp, pd2 + 1, 13);
2884 if (gDebug > 2)
2885 ::Info("TAuthenticate::DecodeRSAPublic",
2886 "got %ld bytes for rsa_d_exp", (Long_t)strlen(rsa_d_exp));
2887
2890
2891 delete[] rsa_n_exp;
2892 delete[] rsa_d_exp;
2893
2894 } else
2895 ::Info("TAuthenticate::DecodeRSAPublic","bad format for input string");
2896#ifdef R__SSL
2897 } else {
2898 // try SSL
2899 keytype = 1;
2900
2901 RSA *rsatmp;
2902
2903 // Bio for exporting the pub key
2904 BIO *bpub = BIO_new(BIO_s_mem());
2905
2906 // Write key from kbuf to BIO
2907 BIO_write(bpub,(void *)str,strlen(str));
2908
2909 // Read pub key from BIO
2910 if (!(rsatmp = PEM_read_bio_RSAPublicKey(bpub, 0, 0, 0))) {
2911 if (gDebug > 0)
2912 ::Info("TAuthenticate::DecodeRSAPublic",
2913 "unable to read pub key from bio");
2914 } else
2915 if (rsassl)
2916 *rsassl = (char *)rsatmp;
2917 else
2918 ::Info("TAuthenticate::DecodeRSAPublic",
2919 "no space allocated for output variable");
2920 BIO_free(bpub);
2921 }
2922#else
2923 } else {
2924 if (rsassl) { } // To avoid compiler complains
2925 if (gDebug > 0)
2926 ::Info("TAuthenticate::DecodeRSAPublic","not compiled with SSL support:"
2927 " you should not have got here!");
2928 }
2929#endif
2930 }
2931
2932 return keytype;
2933}
2934
2935////////////////////////////////////////////////////////////////////////////////
2936/// Store RSA public keys from export string rsaPubExport.
2937/// Returns type of stored key, or -1 is not recognized
2938
2940{
2941 if (gDebug > 2)
2942 ::Info("TAuthenticate::SetRSAPublic",
2943 "enter: string length %ld bytes", (Long_t)strlen(rsaPubExport));
2944
2945 Int_t rsakey = -1;
2946 if (!rsaPubExport)
2947 return rsakey;
2948
2949 if (klen > 0) {
2950
2951 // Skip spaces at beginning, if any
2952 int k0 = 0;
2953 while (rsaPubExport[k0] == 32) k0++;
2954 int k2 = klen - 1;
2955
2956 // Parse rsaPubExport
2957 // Type 0 is in the form
2958 //
2959 // #< gt 10 exa chars >#< gt 10 exa chars >#
2960 //
2961 rsakey = 1;
2962 if (rsaPubExport[k0] == '#' && rsaPubExport[k2] == '#') {
2963 char *p0 = (char *)&rsaPubExport[k0];
2964 char *p2 = (char *)&rsaPubExport[k2];
2965 char *p1 = strchr(p0+1,'#');
2966 if (p1 > p0 && p1 < p2) {
2967 Int_t l01 = (Int_t)(p1-p0)-1;
2968 Int_t l12 = (Int_t)(p2-p1)-1;
2969 if (l01 >= kPRIMELENGTH*2 && l12 >= kPRIMELENGTH*2) {
2970 // Require exadecimal chars in between
2971 char *c = p0+1;
2972 while (c < p1 && ((*c < 58 && *c > 47) || (*c < 91 && *c > 64)))
2973 c++;
2974 if (c == p1) {
2975 c++;
2976 while (c < p2 && ((*c < 58 && *c > 47) || (*c < 91 && *c > 64)))
2977 c++;
2978 if (c == p2)
2979 rsakey = 0;
2980 }
2981 }
2982 }
2983 }
2984 if (gDebug > 3)
2985 ::Info("TAuthenticate::SetRSAPublic"," Key type: %d",rsakey);
2986 if (rsakey == 0) {
2987
2988 // Decode input string
2991
2992 // Save Public key
2995
2996 } else {
2997 rsakey = 1;
2998#ifdef R__SSL
2999 // Now set the key locally in BF form
3000 BF_set_key(&fgBFKey, klen, (const unsigned char *)rsaPubExport);
3001#else
3002 if (gDebug > 0)
3003 ::Info("TAuthenticate::SetRSAPublic",
3004 "not compiled with SSL support:"
3005 " you should not have got here!");
3006#endif
3007 }
3008 }
3009
3010 return rsakey;
3011}
3012
3013////////////////////////////////////////////////////////////////////////////////
3014/// Receives server RSA Public key
3015/// Sends local RSA public key encoded
3016
3018{
3019 // Receive server public key
3021 int kind, nr = 0;
3022 if ((nr = socket->Recv(serverPubKey, kMAXSECBUF, kind)) < 0)
3023 return nr;
3024 if (gDebug > 3)
3025 ::Info("TAuthenticate::SendRSAPublicKey",
3026 "received key from server %ld bytes", (Long_t)strlen(serverPubKey));
3027
3028 // Decode it
3030#ifdef R__SSL
3031 char *tmprsa = nullptr;
3033 &tmprsa) != key) {
3034 if (tmprsa)
3035 RSA_free((RSA *)tmprsa);
3036 return -1;
3037 }
3038 RSA *RSASSLServer = (RSA *)tmprsa;
3039#else
3041 return -1;
3042#endif
3043
3044 // Send local public key, encodes
3045 char buftmp[kMAXSECBUF] = {0};
3046 char buflen[20] = {0};
3047 Int_t slen = fgRSAPubExport[key].len;
3048 Int_t ttmp = 0;
3049 if (key == 0) {
3050 strlcpy(buftmp, fgRSAPubExport[key].keys, sizeof(buftmp));
3051 ttmp = TRSA_fun::RSA_encode()(buftmp, slen, rsa_n, rsa_d); // NOLINT: rsa_n, rsa_d are initialized
3052 snprintf(buflen, sizeof(buflen), "%d", ttmp);
3053 } else if (key == 1) {
3054#ifdef R__SSL
3056 Int_t kk = 0;
3057 Int_t ke = 0;
3058 Int_t ns = slen;
3059 while (ns > 0) {
3060 Int_t lc = (ns > lcmax) ? lcmax : ns ;
3061 if ((ttmp = RSA_public_encrypt(lc,
3062 (unsigned char *)&fgRSAPubExport[key].keys[kk],
3063 (unsigned char *)&buftmp[ke],
3065 char errstr[120];
3067 ::Info("TAuthenticate::SendRSAPublicKey","SSL: error: '%s' ",errstr);
3068 }
3069 kk += lc;
3070 ke += ttmp;
3071 ns -= lc;
3072 }
3073 ttmp = ke;
3074 snprintf(buflen, 20, "%d", ttmp);
3075#else
3076 if (gDebug > 0)
3077 ::Info("TAuthenticate::SendRSAPublicKey","not compiled with SSL support:"
3078 " you should not have got here!");
3079 return -1;
3080#endif
3081 } else {
3082 if (gDebug > 0)
3083 ::Info("TAuthenticate::SendRSAPublicKey","unknown key type (%d)",key);
3084#ifdef R__SSL
3085 if (RSASSLServer)
3087#endif
3088 return -1;
3089 }
3090
3091 // Send length first
3092 if ((nr = socket->Send(buflen, kROOTD_ENCRYPT)) < 0)
3093 return nr;
3094 // Send Key. second ...
3095 Int_t nsen = socket->SendRaw(buftmp, ttmp);
3096 if (gDebug > 3)
3097 ::Info("TAuthenticate::SendRSAPublicKey",
3098 "local: sent %d bytes (expected: %d)", nsen,ttmp);
3099#ifdef R__SSL
3100 if (RSASSLServer)
3102#endif
3103 return nsen;
3104}
3105
3106////////////////////////////////////////////////////////////////////////////////
3107/// Read authentication directives from $ROOTAUTHRC, $HOME/.rootauthrc or
3108/// `<Root_etc_dir>/system.rootauthrc` and create related THostAuth objects.
3109/// Files are read only if they changed since last reading
3110
3112{
3113 // rootauthrc family
3114 char *authrc = 0;
3115 if (gSystem->Getenv("ROOTAUTHRC") != 0) {
3116 authrc = StrDup(gSystem->Getenv("ROOTAUTHRC"));
3117 } else {
3118 if (fgReadHomeAuthrc)
3119 authrc = gSystem->ConcatFileName(gSystem->HomeDirectory(), ".rootauthrc");
3120 }
3121 if (authrc && gDebug > 2)
3122 ::Info("TAuthenticate::ReadRootAuthrc", "Checking file: %s", authrc);
3124 if (authrc && gDebug > 1)
3125 ::Info("TAuthenticate::ReadRootAuthrc",
3126 "file %s cannot be read (errno: %d)", authrc, errno);
3127 delete [] authrc;
3128 authrc = gSystem->ConcatFileName(TROOT::GetEtcDir(), "system.rootauthrc");
3129 if (gDebug > 2)
3130 ::Info("TAuthenticate::ReadRootAuthrc", "Checking system file: %s", authrc);
3132 if (gDebug > 1)
3133 ::Info("TAuthenticate::ReadRootAuthrc",
3134 "file %s cannot be read (errno: %d)", authrc, errno);
3135 delete [] authrc;
3136 return 0;
3137 }
3138 }
3139
3140 // Check if file has changed since last read
3142 if (tRootAuthrc == fgRootAuthrc) {
3143 struct stat si;
3144 stat(tRootAuthrc, &si);
3145 if ((UInt_t)si.st_mtime < fgLastAuthrc.Convert()) {
3146 if (gDebug > 1)
3147 ::Info("TAuthenticate::ReadRootAuthrc",
3148 "file %s already read", authrc);
3149 delete [] authrc;
3150 return 0;
3151 }
3152 }
3153
3154 // Save filename in static variable
3157
3158 // THostAuth lists
3160
3161 // Expand File into temporary file name and open it
3162 int expand = 1;
3163 TString filetmp = "rootauthrc";
3165 if (gDebug > 2)
3166 ::Info("TAuthenticate::ReadRootAuthrc", "got tmp file: %s open at 0x%zx",
3167 filetmp.Data(), (size_t)ftmp);
3168 if (ftmp == 0)
3169 expand = 0; // Problems opening temporary file: ignore 'include's ...
3170
3171 FILE *fd = 0;
3172 // If the temporary file is open, copy everything to the new file ...
3173 if (expand == 1) {
3175 fd = ftmp;
3176 rewind(fd);
3177 } else {
3178 // Open file
3179 fd = fopen(authrc, "r");
3180 if (fd == 0) {
3181 if (gDebug > 2)
3182 ::Info("TAuthenticate::ReadRootAuthrc",
3183 "file %s cannot be open (errno: %d)", authrc, errno);
3184 delete [] authrc;
3185 return 0;
3186 }
3187 }
3188
3189 // Now scan file for meaningful directives
3191 char line[kMAXPATHLEN];
3192 while (fgets(line, sizeof(line), fd) != 0) {
3193
3194 // Skip comment lines
3195 if (line[0] == '#')
3196 continue;
3197
3198 // Get rid of end of line '\n', if there ...
3199 if (line[strlen(line) - 1] == '\n')
3200 line[strlen(line) - 1] = '\0';
3201
3202 // Skip empty lines
3203 if (!line[0])
3204 continue;
3205
3206 // Now scan
3207 const size_t tmpSize = strlen(line) + 1;
3208 char *tmp = new char[tmpSize];
3209 if (!tmp) {
3210 ::Error("TAuthenticate::ReadRootAuthrc",
3211 "could not allocate temporary buffer");
3212 fclose(fd);
3213 return 0;
3214 }
3215 strlcpy(tmp, line, tmpSize);
3216 char *nxt = strtok(tmp," ");
3217
3218
3220 TString host = hostsrv;
3221 TString server = "";
3222 if (hostsrv.Contains(":")) {
3223 server = hostsrv;
3224 host.Remove(host.Index(":"));
3225 server.Remove(0,server.Index(":")+1);
3226 }
3227 Int_t srvtyp = -1;
3228 if (server.Length()) {
3229 if (server == "0" || server.BeginsWith("sock"))
3231 else if (server == "1" || server.BeginsWith("root"))
3233 }
3234
3235 // Line with host info directives
3236 TString user = "*";
3237
3238 nxt = strtok(0," ");
3239 if (!strncmp(nxt,"user",4)) {
3240 nxt = strtok(0," ");
3241 if (strncmp(nxt,"list",4) && strncmp(nxt,"method",6)) {
3242 user = TString(nxt);
3243 nxt = strtok(0," ");
3244 }
3245 }
3246
3247 // Get related THostAuth, if exists in the tmp list,
3248 TIter next(&tmpAuthInfo);
3249 THostAuth *ha;
3250 while ((ha = (THostAuth *)next())) {
3251 if (host == ha->GetHost() && user == ha->GetUser() &&
3252 srvtyp == ha->GetServer())
3253 break;
3254 }
3255 if (!ha) {
3256 // Create a new one
3257 ha = new THostAuth(host,srvtyp,user);
3258 tmpAuthInfo.Add(ha);
3259 }
3260
3261 if (!strncmp(nxt,"list",4)) {
3262 // list of methods for {host,usr}
3263 Int_t nm = 0, me[kMAXSEC] = {0};
3264 char *mth = strtok(0," ");
3265 while (mth) {
3266 Int_t met = -1;
3267 if (strlen(mth) > 1) {
3268 // Method passed as string: translate it to number
3270 if (met == -1 && gDebug > 2)
3271 ::Info("TAuthenticate::ReadRootAuthrc",
3272 "unrecognized method (%s): ", mth);
3273 } else {
3274 met = atoi(mth);
3275 }
3276 if (met > -1 && met < kMAXSEC)
3277 me[nm++] = met;
3278 mth = strtok(0," ");
3279 }
3280 if (nm)
3281 ha->ReOrder(nm,me);
3282
3283 } else if (!strncmp(nxt,"method",6)) {
3284
3285 // details for {host,usr,method}
3286 char *mth = strtok(0," ");
3287 Int_t met = -1;
3288 if (strlen(mth) > 1) {
3289 // Method passed as string: translate it to number
3291 if (met == -1 && gDebug > 2)
3292 ::Info("TAuthenticate::ReadRootAuthrc",
3293 "unrecognized method (%s): ", mth);
3294 } else {
3295 met = atoi(mth);
3296 }
3297 if (met > -1 && met < kMAXSEC) {
3298 const char *det = 0;
3299 nxt = strtok(0," ");
3300 if (nxt) {
3301 det = (const char *)strstr(line,nxt);
3302 }
3303 if (ha->HasMethod(met))
3304 ha->SetDetails(met,det);
3305 else
3306 ha->AddMethod(met,det);
3307 }
3308 }
3309 if (tmp) delete [] tmp;
3310 }
3311 // Close file and remove it if temporary
3312 fclose(fd);
3313 if (expand == 1)
3315 // Cleanup allocated memory
3316 delete [] authrc;
3317
3318 // Update authinfo with new info found
3320
3321 // Print those left, if requested ...
3322 if (gDebug > 2)
3324
3325 return authinfo->GetSize();
3326}
3327
3328////////////////////////////////////////////////////////////////////////////////
3329/// Standard version of CheckSecCtx to be passed to TAuthenticate::AuthExists
3330/// Check if User is matches the one in Ctx
3331/// Returns: 1 if ok, 0 if not
3332/// Deactivates Ctx is not valid
3333
3334Int_t StdCheckSecCtx(const char *user, TRootSecContext *ctx)
3335{
3336 Int_t rc = 0;
3337
3338 if (ctx->IsActive()) {
3339 if (!strcmp(user,ctx->GetUser()) &&
3340 strncmp("AFS", ctx->GetID(), 3))
3341 rc = 1;
3342 }
3343 return rc;
3344}
3345
3346////////////////////////////////////////////////////////////////////////////////
3347/// Tool for updating fgAuthInfo
3348/// 'nin' contains list of last input information through (re)reading
3349/// of a rootauthrc-alike file. 'nin' info has priority.
3350/// 'std' is cleaned from inactive members.
3351/// 'nin' members used to update existing members in 'std' are
3352/// removed from 'nin', do that they do not leak
3353
3355{
3356 // Remove inactive from the 'std'
3357 TIter nxstd(std);
3358 THostAuth *ha;
3359 while ((ha = (THostAuth *) nxstd())) {
3360 if (!ha->IsActive()) {
3361 std->Remove(ha);
3362 SafeDelete(ha);
3363 }
3364 }
3365
3366 // Merge 'nin' info in 'std'
3367 TIter nxnew(nin);
3369 while ((hanew = (THostAuth *)nxnew())) {
3370 if (hanew->NumMethods()) {
3372 hostsrv.Form("%s:%d",hanew->GetHost(),hanew->GetServer());
3373 THostAuth *hastd =
3375 if (hastd) {
3376 // Update with new info
3377 hastd->Update(hanew);
3378 // Flag for removal
3379 hanew->DeActivate();
3380 } else {
3381 // Add new ThostAuth to std
3382 std->Add(hanew);
3383 }
3384 } else
3385 // Flag for removal empty objects
3386 hanew->DeActivate();
3387 }
3388
3389 // Cleanup memory before quitting
3390 nxnew.Reset();
3391 while ((hanew = (THostAuth *)nxnew())) {
3392 if (!hanew->IsActive()) {
3393 nin->Remove(hanew);
3395 }
3396 }
3397
3398}
3399
3400////////////////////////////////////////////////////////////////////////////////
3401/// Tool for removing SecContext ctx from THostAuth listed in
3402/// fgAuthInfo
3403
3405{
3406 THostAuth *ha = 0;
3407
3408 // authinfo first
3410 while ((ha = (THostAuth *)nxai())) {
3411 TIter next(ha->Established());
3412 TRootSecContext *lctx = 0;
3413 while ((lctx = (TRootSecContext *) next())) {
3414 if (lctx == ctx) {
3415 ha->Established()->Remove(ctx);
3416 break;
3417 }
3418 }
3419 }
3420}
3421
3422////////////////////////////////////////////////////////////////////////////////
3423/// Static method returning supported client protocol.
3424
3429
const Int_t kAUTH_SSALT_MSK
Definition AuthConst.h:30
const Int_t kAUTH_CRYPT_MSK
Definition AuthConst.h:29
const Int_t kMAXSECBUF
Definition AuthConst.h:27
const Int_t kAUTH_REUSE_MSK
Definition AuthConst.h:28
const Int_t kPRIMEEXP
Definition AuthConst.h:34
const Int_t kPRIMELENGTH
Definition AuthConst.h:33
const Int_t kMAXRSATRIES
Definition AuthConst.h:32
const Int_t kAUTH_RSATY_MSK
Definition AuthConst.h:31
const Int_t kMAXSEC
Definition AuthConst.h:26
@ kROOTD_RSAKEY
@ kROOTD_ENCRYPT
@ kROOTD_PASS
@ kMESS_STRING
@ kROOTD_USER
@ kROOTD_BYE
@ kROOTD_NEGOTIA
@ kROOTD_AUTH
@ kROOTD_ERR
R__EXTERN const char * gRootdErrStr[]
Definition NetErrors.h:72
@ kErrNotAllowed
Definition NetErrors.h:49
@ kErrConnectionRefused
Definition NetErrors.h:50
@ kErrError
Definition NetErrors.h:69
#define SafeDelete(p)
Definition RConfig.hxx:533
#define c(i)
Definition RSha256.hxx:101
bool Bool_t
Boolean (0=false, 1=true) (bool)
Definition RtypesCore.h:77
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
Definition RtypesCore.h:68
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
constexpr Ssiz_t kNPOS
The equivalent of std::string::npos for the ROOT class TString.
Definition RtypesCore.h:131
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
@ kMAXPATHLEN
Definition Rtypes.h:61
TVirtualMutex * gAuthenticateMutex
Int_t StdCheckSecCtx(const char *, TRootSecContext *)
Standard version of CheckSecCtx to be passed to TAuthenticate::AuthExists Check if User is matches th...
R__rsa_KEY_export R__fgRSAPubExport[2]
static int auth_rand()
rand() implementation using /udev/random or /dev/random, if available
R__EXTERN TVirtualMutex * gAuthenticateMutex
Int_t(* Krb5Auth_t)(TAuthenticate *auth, TString &user, TString &det, Int_t version)
Int_t(* SecureAuth_t)(TAuthenticate *auth, const char *user, const char *passwd, const char *remote, TString &det, Int_t version)
Int_t(* GlobusAuth_t)(TAuthenticate *auth, TString &user, TString &det)
Int_t(* CheckSecCtx_t)(const char *subj, TRootSecContext *ctx)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
char name[80]
Definition TGX11.cxx:110
Int_t gDebug
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:627
#define gROOT
Definition TROOT.h:411
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2495
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2509
char * StrDup(const char *str)
Duplicate the string str.
Definition TString.cxx:2563
@ kReadPermission
Definition TSystem.h:55
Bool_t R_ISREG(Int_t mode)
Definition TSystem.h:126
Bool_t R_ISDIR(Int_t mode)
Definition TSystem.h:123
R__EXTERN TSystem * gSystem
Definition TSystem.h:572
@ kS_IWUSR
Definition TSystem.h:111
@ kS_IRUSR
Definition TSystem.h:110
#define R__LOCKGUARD2(mutex)
const char * proto
Definition civetweb.c:18822
#define snprintf
Definition civetweb.c:1579
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.
static Bool_t fgPromptUser
TRootSecContext * fSecContext
static Bool_t fgPwHash
ESecurity fSecurity
THostAuth * fHostAuth
static void FileExpand(const char *fin, FILE *ftmp)
Expands include directives found in fexp files The expanded, temporary file, is pointed to by 'ftmp' ...
static TString fgUser
TSocket * fSocket
static const char * GetGlobalUser()
Static method returning the global user.
static void SetGlobalUser(const char *user)
Set global user name to be used for authentication to rootd.
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.
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.
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.
static void SetGlobalExpDate(TDatime expdate)
Set default expiring date for new validity contexts.
static Int_t GetRSAInit()
Static method returning the RSA initialization flag.
static void SetSecureAuthHook(SecureAuth_t func)
Set secure authorization function.
static Int_t GetClientProtocol()
Static method returning supported client protocol.
static Int_t ReadRootAuthrc()
Read authentication directives from $ROOTAUTHRC, $HOME/.rootauthrc or <Root_etc_dir>/system....
static Bool_t fgReadHomeAuthrc
static Int_t fgAuthTO
static Int_t fgLastError
static Int_t SecureSend(TSocket *Socket, Int_t enc, Int_t KeyType, const char *In)
Encode null terminated str using the session private key indicated by enc and sends it over the netwo...
Int_t GenRSAKeys()
Generate a valid pair of private/public RSA keys to protect for authentication token exchange.
Bool_t CheckNetrc(TString &user, TString &passwd)
Try to get user name and passwd from the ~/.rootnetrc or ~/.netrc files.
static const char * GetRSAPubExport(Int_t key=0)
Static method returning the RSA public keys.
static void InitRandom()
Initialize random machine using seed from /dev/urandom (or current time if /dev/urandom not available...
static R__rsa_KEY fgRSAPubKey
static Bool_t fgAuthReUse
static Bool_t GetGlobalPwHash()
Static method returning the global password hash flag.
static void SetKrb5AuthHook(Krb5Auth_t func)
Set kerberos5 authorization function.
static void SetGlobusAuthHook(GlobusAuth_t func)
Set Globus authorization function.
static void SetRSAInit(Int_t init=1)
Static method setting RSA initialization flag.
static void SetGlobalPasswd(const char *passwd)
Set global passwd to be used for authentication to rootd.
static TDatime fgExpDate
TString fProtocol
void SetEnvironment()
Set default authentication environment.
static Int_t SendRSAPublicKey(TSocket *Socket, Int_t key=0)
Receives server RSA Public key Sends local RSA public key encoded.
static TDatime fgLastAuthrc
static TList * fgAuthInfo
static TString fgPasswd
static TString fgAuthMeth[kMAXSEC]
void CatchTimeOut()
Called in connection with a timer timeout.
Bool_t GetUserPasswd(TString &user, TString &passwd, Bool_t &pwhash, Bool_t srppwd)
Try to get user name and passwd from several sources.
Bool_t Authenticate()
Authenticate to remote rootd 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 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 'nin' contains list of last input information through (re)reading of a r...
static TString fgDefaultUser
static Int_t GetAuthMethodIdx(const char *meth)
Static method returning the method index (which can be used to find the method in GetAuthMethod()).
static Int_t fgRSAKey
static Int_t DecodeRSAPublic(const char *rsapubexport, R__rsa_NUMBER &n, R__rsa_NUMBER &d, char **rsassl=nullptr)
Store RSA public keys from export string rsaPubExport.
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.
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.
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 Returns pointer ...
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition TDatime.h:37
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:490
Int_t NumMethods() const
Definition THostAuth.h:68
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=nullptr, Int_t key=-1)
Create a Security context and add it to local list Return pointer to it to be stored in TAuthenticate...
const char * GetHost() const
Definition THostAuth.h:91
Int_t GetServer() const
Definition THostAuth.h:92
void SetUser(const char *user)
Definition THostAuth.h:97
void SetHost(const char *host)
Definition THostAuth.h:95
void SetFirst(Int_t level)
Set 'method' to be the first used (if in the list ...).
void SetServer(Int_t server)
Definition THostAuth.h:96
void RemoveMethod(Int_t level)
Remove method 'meth' from the list, if there ...
void CountFailure(Int_t level)
Count failures for 'method'.
void AddFirst(Int_t level, const char *details=nullptr)
Add new method in first position If already in the list, set as first method 'level' with authenticat...
Int_t GetMethod(Int_t idx) const
Definition THostAuth.h:69
Bool_t HasMethod(Int_t level, Int_t *pos=nullptr)
Return kTRUE if method 'level' is in the list.
TList * Established() const
Definition THostAuth.h:99
const char * GetDetails(Int_t level)
Return authentication details for specified level or "" if the specified level does not exist for thi...
void SetLast(Int_t level)
Set 'method' to be the last used (if in the list ...).
void CountSuccess(Int_t level)
Count successes for 'method'.
This class represents an Internet Protocol (IP) address.
A doubly linked list.
Definition TList.h:38
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
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:1057
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1071
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1045
static const TString & GetEtcDir()
Get the sysconfig directory in the installation. Static utility function.
Definition TROOT.cxx:3107
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
void Print(Option_t *option="F") const override
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 AddForCleanup(Int_t port, Int_t proto, Int_t type)
Create a new TSecContextCleanup Internally is added to the list.
const char * GetUser() const
Definition TSecContext.h:82
virtual Int_t Recv(TMessage *&mess)
Receive a TMessage object.
Definition TSocket.cxx:809
static Int_t GetClientProtocol()
Static method returning supported client protocol.
Definition TSocket.cxx:1435
Int_t GetRemoteProtocol() const
Definition TSocket.h:124
virtual void Close(Option_t *opt="")
Close the socket.
Definition TSocket.cxx:380
virtual Int_t RecvRaw(void *buffer, Int_t length, ESendRecvOptions opt=kDefault)
Receive a raw buffer of specified length bytes.
Definition TSocket.cxx:889
virtual Int_t SendRaw(const void *buffer, Int_t length, ESendRecvOptions opt=kDefault)
Send a raw buffer of specified length.
Definition TSocket.cxx:611
@ kSOCKD
Definition TSocket.h:50
@ kROOTD
Definition TSocket.h:50
Int_t GetPort() const
Definition TSocket.h:113
Int_t GetServType() const
Definition TSocket.h:115
virtual Int_t Send(const TMessage &mess)
Send a TMessage object.
Definition TSocket.cxx:513
Basic string class.
Definition TString.h:138
Ssiz_t Length() const
Definition TString.h:425
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition TString.h:702
const char * Data() const
Definition TString.h:384
@ kIgnoreCase
Definition TString.h:285
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:631
TString & Remove(Ssiz_t pos)
Definition TString.h:693
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:2384
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2362
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:640
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:659
virtual FILE * TempFileName(TString &base, const char *dir=nullptr, const char *suffix=nullptr)
Create a secure temporary file by appending a unique 6 letter string to base.
Definition TSystem.cxx:1510
virtual int GetPid()
Get process id.
Definition TSystem.cxx:716
virtual const char * Getenv(const char *env)
Get environment variable.
Definition TSystem.cxx:1676
virtual char * ConcatFileName(const char *dir, const char *name)
Concatenate a directory and a file name.
Definition TSystem.cxx:1082
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition TSystem.cxx:1868
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:1409
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:1307
virtual void DispatchOneEvent(Bool_t pendingOnly=kFALSE)
Dispatch a single event.
Definition TSystem.cxx:427
virtual const char * HostName()
Return the system's host name.
Definition TSystem.cxx:301
virtual Int_t GetEffectiveUid()
Returns the effective user id.
Definition TSystem.cxx:1583
virtual TInetAddress GetHostByName(const char *server)
Get Internet Protocol (IP) address of host.
Definition TSystem.cxx:2302
virtual const char * HomeDirectory(const char *userName=nullptr)
Return the user's home directory.
Definition TSystem.cxx:897
virtual int Unlink(const char *name)
Unlink, i.e.
Definition TSystem.cxx:1392
virtual UserGroup_t * GetUserInfo(Int_t uid)
Returns all user info in the UserGroup_t structure.
Definition TSystem.cxx:1612
char * DynamicPathName(const char *lib, Bool_t quiet=kFALSE)
Find a dynamic library called lib using the system search paths.
Definition TSystem.cxx:2031
Handles synchronous and a-synchronous timer events.
Definition TTimer.h:51
This class implements a mutex interface.
TPaveText * pt
TLine * line
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:135
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4
auto * t1
Definition textangle.C:20