35 #include <sys/param.h>
37 #include <sys/types.h>
40 #include <sys/times.h>
42 #include "XrdVersion.hh"
61 #define POPTS(t,y) {if (t) {t->Beg(epname); std::cerr <<y; t->End();}}
104 "loading crypto factory",
106 "resolving user / host",
111 "duplicating bucket",
113 "serializing buffer",
115 "exporting public key",
116 "encrypting random tag",
117 "random tag mismatch",
118 "random tag missing",
120 "getting credentials",
121 "credentials missing",
122 "wrong password for user",
124 "cache entry for link missing",
125 "session handshaking ID missing",
126 "session handshaking ID mismatch",
127 "unknown step option",
128 "marshaling integer",
129 "unmarshaling integer",
130 "saving new credentials",
133 "obtaining reference cipher",
134 "obtaining cipher public info",
135 "adding bucket to list",
136 "finalizing cipher from public info",
137 "error during initialization",
161 String XrdSecProtocolpwd::FileAdmin=
"";
162 String XrdSecProtocolpwd::FileExpCreds=
"";
163 String XrdSecProtocolpwd::FileUser =
"";
164 String XrdSecProtocolpwd::FileCrypt=
"/.xrdpass";
165 String XrdSecProtocolpwd::FileSrvPuk=
"";
166 String XrdSecProtocolpwd::SrvID =
"";
167 String XrdSecProtocolpwd::SrvEmail =
"";
168 String XrdSecProtocolpwd::DefCrypto=
"ssl";
169 String XrdSecProtocolpwd::DefError =
"insufficient credentials - contact ";
175 int XrdSecProtocolpwd::ncrypt = 0;
187 int XrdSecProtocolpwd::Debug = 0;
188 bool XrdSecProtocolpwd::Server = 1;
189 int XrdSecProtocolpwd::UserPwd = 0;
190 bool XrdSecProtocolpwd::SysPwd = 0;
191 int XrdSecProtocolpwd::VeriClnt = 2;
193 int XrdSecProtocolpwd::VeriSrv = 1;
195 int XrdSecProtocolpwd::AutoReg =
kpAR_none;
196 int XrdSecProtocolpwd::LifeCreds = 0;
197 int XrdSecProtocolpwd::MaxPrompts = 3;
198 int XrdSecProtocolpwd::MaxFailures = 10;
199 int XrdSecProtocolpwd::AutoLogin = 0;
200 int XrdSecProtocolpwd::TimeSkew = 300;
201 bool XrdSecProtocolpwd::KeepCreds = 0;
202 int XrdSecProtocolpwd::FmtExpCreds = 0;
205 XrdSysError XrdSecProtocolpwd::eDest(0,
"secpwd_");
218 static const char *ukn =
"Unknown";
220 kclt = (kclt < 0) ? 0 : kclt;
234 static const char *ukn =
"Unknown";
236 ksrv = (ksrv < 0) ? 0 : ksrv;
257 EPNAME(
"XrdSecProtocolpwd");
259 if (
QTRACE(Authen)) {
PRINT(
"constructing: "<<
this); }
277 hs->
Tty = (isatty(0) == 0 || isatty(1) == 0) ? 0 : 1;
281 PRINT(
"could not create handshake vars object");
291 NOTIFY(
"warning: host name undefined");
296 CName[0] =
'?'; CName[1] =
'\0';
300 DEBUG(
"constructing: host: "<<hname);
310 DEBUG(
"mode: server");
313 DEBUG(
"mode: client");
315 DEBUG(
"using autologin file: "<<PFAlog.
Name());
317 DEBUG(
"running in update-autologin mode");
321 DEBUG(
"server verification ON");
323 DEBUG(
"server verification OFF");
355 ErrF(erp,
kPWErrInit,
"tracing object (pwdTrace) not initialized! cannot continue");
360 int trace = 0, traceSut = 0, traceCrypto = 0;
366 }
else if (Debug >= 2) {
372 }
else if (Debug >= 1) {
388 PRINT(
"no user info available - invalid ");
389 ErrF(erp,
kPWErrInit,
"could not get user info from pwuid");
395 Server = (opt.
mode ==
's');
412 infodir += (
"/." +
Prefix);
414 if (!infodir.
endswith(
"/")) infodir +=
"/";
423 if (errno == ENOENT) {
425 DEBUG(
"infodir non existing: "<<infodir.
c_str());
429 DEBUG(
"cannot create infodir (errno: "<<errno<<
")");
435 DEBUG(
"cannot stat infodir "<<infodir<<
" (errno: "<<errno<<
")");
449 AutoReg = (opt.
areg > -1) ? opt.
areg : AutoReg;
455 UserPwd = (opt.
upwd > -1) ? opt.
upwd : UserPwd;
467 struct spwd *spw = getspnam(pw->pw_name);
470 DEBUG(
"no privileges to access shadow passwd file");
473 DEBUG(
"problems acquiring credentials"
474 " to access the system password file");
478 if (!pw->pw_passwd &&
479 (pw->pw_passwd && strlen(pw->pw_passwd) <= 1)) {
481 DEBUG(
"no privileges to access system passwd file");
504 if (
stat(FileAdmin.c_str(),&st) == -1) {
505 if (errno == ENOENT) {
506 PRINT(
"FileAdmin non existing: "<<FileAdmin.c_str());
508 PRINT(
"cannot stat FileAdmin (errno: "<<errno<<
")");
511 if (UserPwd == 0 && !SysPwd) {
512 PRINT(
"no passwd info available - invalid ");
513 ErrF(erp,
kPWErrInit,
"could not find a valid password file");
517 if (FileAdmin.length() > 0) {
520 PFAdmin.
Init(FileAdmin.c_str(),0);
524 if (cacheAdmin.
Load(FileAdmin.c_str()) != 0) {
525 PRINT(
"problems init cache for file admin ");
526 ErrF(erp,
kPWErrError,
"initializing cache for file admin");
535 ent = cacheAdmin.Get(pfeRef,
"+++SrvEmail");
539 DefError += SrvEmail;
543 DEBUG(
"contact e-mail: "<<SrvEmail);
546 }
else if (UserPwd == 0 && !SysPwd) {
547 PRINT(
"no passwd info available - invalid ");
548 ErrF(erp,
kPWErrError,
"could not find a valid password file");
553 if (UserPwd > 0 || SysPwd) {
554 if (cacheUser.
Init(100) != 0) {
555 PRINT(
"problems init cache for user pwd info"
556 " - passwd files in user accounts will not be used");
573 while ((from = clist.
tokenize(ncpt, from,
'|')) != -1) {
582 String ptag(
"+++SrvPuk_");
584 if (FileAdmin.
length() > 0) {
589 PRINT(
"ref cipher for module "<<ncpt<<
" missing: disable");
590 cryptlist.
erase(ncpt);
595 PRINT(
"ref cipher for module "<<ncpt<<
596 " cannot be instantiated : disable");
597 cryptlist.
erase(ncpt);
601 PRINT(
"max number of crypto modules ("
610 PRINT(
"cannot instantiate crypto factory "<<ncpt);
619 PRINT(
"could not find any valid crypto module");
620 ErrF(erp,
kPWErrInit,
"could not find any valid crypto module");
630 if (FileUser[0] !=
'/') FileUser.
insert(
'/',0);
640 FileCrypt = opt.
cpass;
641 if (FileCrypt[0] !=
'/') FileCrypt.
insert(
'/',0);
649 NOTIFY(
"Exporting client creds to internal buffer");
657 const char *efmts[4] = {
"PFile",
"hex",
"raw",
"raw/nokeyword"};
658 NOTIFY(
"Exporting client creds (fmt:"<<efmts[FmtExpCreds]<<
") to files "<<FileExpCreds);
673 sprintf(Parms,
"v:%d,id:%s,c:%s,po:%s",
676 sprintf(Parms,
"v:%d,id:%s,c:%s",
679 PRINT(
"no system resources for 'Parms'");
680 ErrF(erp,
kPWErrInit,
"no system resources for 'Parms'");
684 NOTIFY(
"using FileAdmin: "<<FileAdmin);
686 NOTIFY(
"contact e-mail: "<<SrvEmail);
687 NOTIFY(
"auto-registration mode: "<<AutoReg);
688 NOTIFY(
"verify client mode: "<<VeriClnt);
689 NOTIFY(
"available crypto modules: "<<cryptlist);
691 NOTIFY(
"using private pwd files: $(HOME)"<<FileUser);
693 NOTIFY(
"using private crypt-hash files: $(HOME)"<<FileCrypt);
697 NOTIFY(
"using system pwd information");
700 NOTIFY(
"client credentials will be kept");
725 if (FileSrvPuk.
length() > 0) {
729 if (
stat(FileSrvPuk.
c_str(),&st) == -1) {
730 if (errno == ENOENT) {
731 PRINT(
"server public key file "<<FileSrvPuk<<
" non existing: creating");
736 DEBUG(
"asserting dir: "<<dir);
738 PRINT(
"cannot create dir for srvpuk(errno: "<<errno<<
")");
739 ErrF(erp,
kPWErrInit,
"cannot create dir for server public key file- exit");
743 PRINT(
"cannot stat server public key file (errno: "<<errno<<
")");
745 PRINT(
"server public key file invalid - exit");
746 ErrF(erp,
kPWErrInit,
"server public key file invalid - exit");
752 PFSrvPuk.
Init(FileSrvPuk.
c_str(),openmode);
756 if (cacheSrvPuk.
Load(FileSrvPuk.
c_str()) != 0) {
757 PRINT(
"problems init cache for server public key file ");
758 ErrF(erp,
kPWErrError,
"initializing cache for server public key file ");
763 PRINT(
"server public key file invalid ");
764 ErrF(erp,
kPWErrInit,
"server public key file invalid");
768 PRINT(
"server public key file undefined");
769 ErrF(erp,
kPWErrInit,
"server public key file undefined");
775 AutoLogin = (opt.
alog > -1) ? opt.
alog : AutoLogin;
776 NOTIFY(
"AutoLogin level: "<<AutoLogin);
802 if (errno == ENOENT) {
803 PRINT(
"Autologin file "<<fnrc<<
" non existing: creating");
806 PRINT(
"cannot stat autologin file (errno: "<<errno<<
")");
807 PRINT(
"switching off auto-login");
821 PRINT(
"problems init cache for autologin file");
824 PRINT(
"problems attaching-to / creating autologin file");
831 NOTIFY(
"could not init properly autologin - switch off ");
837 if (AutoLogin <= 0) {
839 if (cacheAlog.
Init(100) != 0) {
840 PRINT(
"problems init cache for user temporary autolog");
883 int sz = clientCreds->
size;
884 char *nbuf = (
char *) malloc(sz);
886 memcpy(nbuf, clientCreds->
buffer, sz);
896 "handshake var container missing",
"getCredentials");
901 if ((!parm && !hs->
Parms) || (parm && (!(parm->
buffer) || parm->
size <= 0)))
902 return ErrC(ei,0,0,0,
kPWErrNoBuffer,
"missing parameters",
"getCredentials");
912 const char *stepstr = 0;
927 memset(&SessionSt,0,
sizeof(SessionSt));
957 if (ParseClientInput(bpar, &bmai, Emsg) == -1) {
967 bmai->
Dump(
"Main IN");
977 if (!CheckRtag(bmai, Emsg))
1005 return ErrC(ei,bpar,bmai,0,
1014 if (hs->
Tty || (AutoLogin > 0))
1030 return ErrC(ei,bpar,bmai,0,
1072 if (!(bck = QueryCreds(bmai, (AutoLogin > 0), status)))
1094 status = SessionSt.
ctype;
1095 if (!(bck = QueryCreds(bmai, 0, status)))
1131 PRINT(
"problems adding bucket kXRS_status");
1135 if (AddSerialized(
'c', nextstep, hs->
ID,
1137 return ErrC(ei,bpar,bmai,0,
1146 bmai->
Dump(
"Main OUT");
1154 DEBUG(
"returned " << nser <<
" bytes of credentials");
1157 DEBUG(
"problems with final serialization");
1188 "handshake var container missing",
1189 "protocol initialization problems");
1198 DEBUG(
"handshaking ID: " << hs->
ID);
1207 char *bpub = 0, *bpid = 0;
1209 const char *stepstr = 0;
1241 bpar->
Dump(stepstr);
1250 if (ParseServerInput(bpar, &bmai, ClntMsg) == -1) {
1263 NOTIFY(
"no bucket kXRS_status found in main buffer");
1269 ulen = (ulen >
sizeof(CName)-1) ?
sizeof(CName)-1 : ulen;
1281 bmai->
Dump(
"main IN");
1285 if (!CheckRtag(bmai, ClntMsg))
1289 if (!CheckTimeStamp(bmai, TimeSkew, ClntMsg))
1324 rc = QueryUser(entst, ClntMsg);
1327 DefError.
c_str(),stepstr);
1330 for (i = 0; i <
ncrypt; i++) {
1334 if (!(bpub = refcip[i]->Public(lpub)))
1337 bpid =
new char[lpub+5];
1340 sprintf(cid,
"%d",cryptID[i]);
1342 memcpy(bpid+5, bpub, lpub);
1350 "out-of-memory",stepstr);
1364 if (QueryUser(entst,ClntMsg) != 0)
1406 if (SaveCreds(bck) != 0) {
1407 ClntMsg =
"Warning: could not correctly update credentials database";
1430 if (!CheckCreds(bck, ctype)) {
1438 if (hs->
Cref->
cnt < MaxPrompts) {
1453 ClntMsg =
"insufficient credentials";
1466 if (cacheAdmin.
Flush() != 0) {
1467 PRINT(
"WARNING: some problem flushing to admin"
1468 " file after updating "<<hs->
Pent->
name);
1483 if (cacheAdmin.
Flush() != 0) {
1484 PRINT(
"WARNING: some problem flushing to admin"
1485 " file after updating "<<hs->
Pent->
name);
1497 ClntMsg =
"Credentials expired";
1499 ClntMsg =
"Password change requested";
1508 int sz = bck->
size+5;
1509 char *buf = (
char *) malloc(sz);
1511 memcpy(buf,
"&pwd", 4);
1515 char *out =
new char[2*sz+1];
1523 if (FileExpCreds.
length() > 0) {
1524 if (ExportCreds(bck) != 0)
1525 PRINT(
"WARNING: some problem exporting creds to file;"
1526 " template is :"<<FileExpCreds);
1541 if (VeriClnt == 2 && !(hs->
RtagOK)) {
1551 PRINT(
"client cannot reply to additional request: failure");
1561 if (ClntMsg.
length() > 0)
1563 PRINT(
"problems adding bucket with message for client");
1571 PRINT(
"problems adding bucket kXRS_status");
1575 if (AddSerialized(
's', nextstep, hs->
ID,
1578 "main / session cipher",stepstr);
1587 bmai->
Dump(
"Main OUT");
1629 if ((
mode ==
'c') &&
debug <= 0)
return;
1631 POPTS(t,
"*** ------------------------------------------------------------ ***");
1632 POPTS(t,
" Mode: "<< ((
mode ==
'c') ?
"client" :
"server"));
1635 POPTS(t,
" Check user's autologin info: " << (
alog != 0 ?
"yes" :
"no"));
1636 POPTS(t,
" Verification level of server ownership on public key: " <<
verisrv);
1641 POPTS(t,
" File with known servers public keys:" <<
srvpuk);
1642 POPTS(t,
" Update auto-login info option:" <<
areg);
1644 POPTS(t,
" Check pwd file in user's home: " << (
upwd != 0 ?
"yes" :
"no"));
1645 POPTS(t,
" Verification level of client ownership on public key: " <<
vericlnt);
1646 POPTS(t,
" Autoregistration option:" <<
areg);
1647 POPTS(t,
" Check system pwd file option: " <<
syspwd);
1651 POPTS(t,
" List of supported crypto modules: " <<
clist);
1653 POPTS(t,
" Directory with admin pwd files: " <<
dir);
1655 POPTS(t,
" User's sub-directory with pwd files: " <<
udir);
1657 POPTS(t,
" User's crypt hash pwd file: " <<
cpass);
1658 POPTS(t,
" Keep client credentials in memory: " << (
keepcreds != 0 ?
"yes" :
"no"));
1660 POPTS(t,
" File for exported client credentials: " <<
expcreds);
1661 POPTS(t,
" Format for exported client credentials: " <<
expfmt);
1663 POPTS(t,
" Client credentials not exported to file");
1666 POPTS(t,
"*** ------------------------------------------------------------ ***");
1685 EPNAME(
"ProtocolpwdInit");
1688 char *rc = (
char *)
"";
1717 cenv = getenv(
"XrdSecDEBUG");
1719 {
if (cenv[0] >= 49 && cenv[0] <= 51)
opts.
debug = atoi(cenv);
1720 else {
PRINT(
"unsupported debug value from env XrdSecDEBUG: "<<cenv<<
" - setting to 1");
1726 cenv = getenv(
"XrdSecPWDVERIFYSRV");
1728 if (cenv[0] >= 48 && cenv[0] <= 49)
opts.verisrv = atoi(cenv);
1730 cenv = getenv(
"XrdSecPWDSRVPUK");
1732 opts.srvpuk = strdup(cenv);
1734 cenv = getenv(
"XrdSecPWDAUTOLOG");
1736 if (cenv[0] >= 48 && cenv[0] <= 50)
opts.alog = atoi(cenv);
1738 cenv = getenv(
"XrdSecPWDALOGFILE");
1740 opts.alogfile = strdup(cenv);
1742 cenv = getenv(
"XrdSecPWDMAXPROMPT");
1744 opts.maxprompts = strtol(cenv, (
char **)0, 10);
1745 if (errno == ERANGE)
opts.maxprompts = -1;
1756 if (
opts.srvpuk) free(
opts.srvpuk);
1757 if (
opts.alogfile) free(
opts.alogfile);
1764 cenv = getenv(
"XRDDEBUG");
1765 if (cenv && !strcmp(cenv,
"1"))
opts.
debug = 1;
1772 char parmbuff[1024];
1773 strlcpy(parmbuff, parms,
sizeof(parmbuff));
1821 while ((op = inParms.
GetToken())) {
1822 if (!strncmp(op,
"-upwd:",6)) {
1824 }
else if (!strncmp(op,
"-dir:",5)) {
1825 dir = (
const char *)(op+5);
1826 }
else if (!strncmp(op,
"-udir:",6)) {
1827 udir = (
const char *)(op+6);
1828 }
else if (!strncmp(op,
"-c:",3)) {
1829 clist = (
const char *)(op+3);
1830 }
else if (!strncmp(op,
"-d:",3)) {
1832 }
else if (!strncmp(op,
"-a:",3)) {
1834 }
else if (!strncmp(op,
"-vc:",4)) {
1836 }
else if (!strncmp(op,
"-syspwd",7)) {
1838 }
else if (!strncmp(op,
"-lf:",4)) {
1840 }
else if (!strncmp(op,
"-maxfail:",9)) {
1841 maxfail = atoi(op+9);
1842 }
else if (!strncmp(op,
"-cryptfile:",11)) {
1843 cpass = (
const char *)(op+11);
1844 }
else if (!strncmp(op,
"-keepcreds",10)) {
1846 }
else if (!strncmp(op,
"-expcreds:",10)) {
1847 expcreds = (
const char *)(op+10);
1848 }
else if (!strncmp(op,
"-expfmt:",8)) {
1849 expfmt = atoi(op+8);
1853 areg = (areg >= 0 && areg <= 2) ? areg : 0;
1854 vc = (vc >= 0 && vc <= 2) ? vc : 2;
1864 opts.syspwd = syspwd;
1865 opts.lifecreds = lifetime;
1866 opts.maxfailures = maxfail;
1867 opts.expfmt = expfmt;
1876 opts.keepcreds = keepcreds;
1877 if (expcreds.
length() > 0)
1878 opts.expcreds = (
char *)expcreds.
c_str();
1904 const char *hostname,
1915 const char *msg =
"Secpwd: Insufficient memory for protocol.";
1919 std::cerr <<msg <<std::endl;
1925 std::cerr <<
"protocol object instantiated" << std::endl;
1948 PRINT(
"invalid input ("<<buf<<
")");
1960 if (!(
opts.length())) {
1961 DEBUG(
"missing options - bad format");
1966 int ii =
opts.find(
"c:");
1971 PRINT(
"crypto information not found in options");
1978 PRINT(
"cryptomod buffer missing");
1995 int fid = hs->
CF->
ID();
1999 if (cryptID[i] == fid)
break;
2004 PRINT(
"max number of crypto slots reached - do nothing");
2013 hs->
Rcip = refcip[i];
2025 bool XrdSecProtocolpwd::CheckCreds(
XrdSutBucket *creds,
int ctype)
2032 if (!hs->
CF || !creds || !hs->
Pent) {
2033 PRINT(
"Invalid inputs ("<<hs->
CF<<
","<<creds<<
","<<hs->
Pent<<
")");
2039 NOTIFY(
"Cached information about creds missing");
2044 int len = creds->
size+4;
2045 char *cbuf = (KeepCreds) ?
new char[len] : (
char *)0;
2054 PRINT(
"Could not allocate working buckets area for the salt");
2061 memcpy(cbuf,
"pwd:", 4);
2066 DoubleHash(hs->
CF,creds,tmps);
2074 if (match && KeepCreds)
2075 creds->
SetBuf(cbuf, len);
2081 passwd.reset(0,creds->
size,creds->
size);
2083 char *pass_crypt = crypt(passwd.c_str(), hs->
Pent->
buf1.
buf);
2087 if (match && KeepCreds) {
2088 memcpy(cbuf,
"cpt:", 4);
2090 creds->
SetBuf(cbuf, len);
2093 NOTIFY(
"Crypt-like passwords (via crypt(...)) not supported");
2107 bool XrdSecProtocolpwd::CheckCredsAFS(
XrdSutBucket *,
int)
2133 PRINT(
"Could not get entry in cache");
2139 PRINT(
"Could not generate salt: out-of-memory");
2144 PRINT(
"Could not create salt bucket");
2150 DoubleHash(hs->
CF,creds,salt);
2160 DEBUG(
"Entry for tag: "<<wTag<<
" updated in cache");
2165 if (cacheAdmin.
Flush() != 0) {
2166 PRINT(
"WARNING: some problem flushing to admin file after updating "<<wTag);
2175 int XrdSecProtocolpwd::ExportCreds(
XrdSutBucket *creds)
2190 if (FileExpCreds.
length() <= 0) {
2191 PRINT(
"File (template) undefined - do nothing");
2196 String filecreds = FileExpCreds;
2199 PRINT(
"Problems resolving templates in "<<filecreds);
2202 DEBUG(
"Exporting client creds to: "<<filecreds);
2205 int lsl = filecreds.
rfind(
'/');
2206 PRINT(
"Exporting client creds to: "<<filecreds<<
" "<<lsl);
2208 String dir(filecreds, 0, lsl-1);
2209 PRINT(
"asserting dir: "<<dir);
2211 PRINT(
"Problems creating directory "<<dir);
2216 if (FmtExpCreds == 0) {
2219 if (!pfcreds.IsValid()) {
2220 PRINT(
"Problem attaching / creating file "<<filecreds);
2232 if (!strncmp(creds->
buffer,
"pwd:", 4)) {
2242 ent.
mtime = time(0);
2243 pfcreds.WriteEntry(ent);
2244 DEBUG(
"New entry for "<<wTag<<
" successfully written to file: "
2247 char *buf = 0, *out = 0;
2250 sz = creds->
size + 5;
2251 if ((buf = (
char *) malloc(sz))) {
2252 memcpy(buf,
"&pwd", 4);
2256 if (FmtExpCreds == 1) {
2257 out =
new char[2*sz+1];
2261 PRINT(
"Problem creating buffer for exported credentials!");
2266 int fd =
open(filecreds.
c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0600);
2268 PRINT(
"problems creating file - errno: " << errno);
2269 if (buf) {free(buf); buf = 0;}
2276 if (FmtExpCreds == 1) {
2278 pw = (
const char *)out;
2280 }
else if (FmtExpCreds == 3) {
2282 int offs = (hs->
SysPwd == 2) ? 9 : 5;
2283 pw = (
const char *)(buf + offs);
2286 pw = (
const char *)buf;
2290 int nw = 0, written = 0;
2292 if ((nw =
write(fd, pw + written, lw)) < 0) {
2293 if (errno == EINTR) {
2306 if (buf) {free(buf); buf = 0;}
2316 bool netrc,
int &status)
2339 PRINT(
"Could allocate bucket for creds");
2351 char *cbuf = getenv(
"XrdSecCREDS");
2353 int len = strlen(cbuf);
2356 char *out =
new char[sz/2+2];
2358 if ((cf = strstr(out,
"&pwd"))) {
2368 DEBUG(
"using "<<len<<
" bytes of creds from the environment; pfx: "<<pfx);
2377 if (strncmp(pfx,
"pwd",3))
2384 if (!strncmp(pfx,
"afs",3)) {
2387 PRINT(
"Warning: problems updating bucket with AFS info");
2399 PRINT(
"Could create new entry in cache");
2422 if (cacheAlog.
Refresh() != 0) {
2423 PRINT(
"problems assuring cache update for file alog ");
2429 hs->
Pent = cacheAlog.Get(pfeRef, wTag.
c_str(),&wild);
2434 bool afspwd = strncmp(cf,
"afs",3) ? 0 : 1;
2435 if (!strncmp(cf,
"cpt",3) || afspwd) {
2448 PRINT(
"Warning: problems updating bucket with AFS info");
2467 if (QueryNetRc(host, passwd, status) == 0) {
2469 if ((hs->
Pent = cacheAlog.
Add(pfeRef, wTag.
c_str()))) {
2481 PRINT(
"Could create new entry in cache");
2489 PRINT(
"Could create new entry in cache");
2547 NOTIFY(
"Not connected to tty: cannot prompt user for credentials");
2555 snprintf(prompt,
XrdSutMAXPPT,
"Password for %s not active: "
2556 "starting activation handshake.",hs->
Tag.
c_str());
2566 snprintf(prompt,
XrdSutMAXPPT,
"AFS password for %s@%s: ",
2574 int natt = MaxPrompts;
2577 while (natt-- && passwd.
length() <= 0) {
2582 PRINT(
"Requesting a password change");
2584 passwd.
erase(
"$changepwd$",0,strlen(
"$changepwd$"));
2591 DoubleHash(hs->
CF,creds,creds);
2613 if (passwd.
length() <= 0) {
2622 int XrdSecProtocolpwd::UpdateAlog()
2630 PRINT(
"Tag undefined - do nothing");
2656 DEBUG(
"Entry for tag: "<<wTag<<
" updated in cache");
2659 if (cacheAlog.
Flush() != 0) {
2660 PRINT(
"WARNING: some problem flushing to alog file after updating "<<wTag);
2668 int XrdSecProtocolpwd::QueryUser(
int &status,
String &cmsg)
2705 if ((rcst =
stat(
File.
c_str(),&st)) != 0 && errno == ENOENT) {
2713 mtime = (rcst == 0) ? st.st_mtime : mtime;
2719 hs->
Pent = cacheUser.Get(pfeRef, wTag.
c_str());
2730 if (ff.ReadEntry(wTag.
c_str(),*(hs->
Pent)) > 0) {
2738 }
else if (UserPwd > 1) {
2740 if (QueryCrypt(FileCrypt, pwhash) > 0) {
2771 if (QueryCrypt(fn, pwhash) > 0) {
2793 if (cacheAdmin.
Refresh() != 0) {
2794 PRINT(
"problems assuring cache update for file admin ");
2798 hs->
Pent = cacheAdmin.Get(pfeRef, wTag.
c_str());
2809 }
else if (status >=
kPFE_ok) {
2811 if (MaxFailures > 0 && hs->
Pent->
cnt >= MaxFailures) {
2816 if (LifeCreds > 0) {
2852 snprintf(msg,
XrdSutMAXPPT,
"user '%s' unknown: auto-registration"
2853 " not allowed: contact %s to register",
2857 snprintf(msg,
XrdSutMAXPPT,
"max number of failures (%d) reached"
2858 " for user '%s': contact %s to re-activate",
2864 cmsg.
insert(msg,0,strlen(msg));
2872 int XrdSecProtocolpwd::GetUserHost(
String &user,
String &host)
2879 if (host.
length() <= 0) host = getenv(
"XrdSecHOST");
2883 if (user.
length() <= 0) user = getenv(
"XrdSecUSER");
2886 if (user.
length() <= 0) {
2890 NOTIFY(
"user not defined:"
2891 "not tty: cannot prompt for user");
2896 String prompt =
"Enter user or tag";
2898 prompt.
append(
" for host ");
2905 DEBUG(
" user: "<<user<<
", host: "<<host);
2922 if (!bls || !buf || (opt != 0 && opt !=
'c' && opt !=
's')) {
2923 PRINT(
"invalid inputs ("
2924 <<bls<<
","<<buf<<
","<<opt<<
")"
2944 if (cip->
Encrypt(*brt) == 0) {
2945 PRINT(
"error encrypting random tag");
2958 PRINT(
"error adding bucket with time stamp");
2973 PRINT(
"error creating random tag bucket");
2980 PRINT(
"cache entry not found: protocol error");
2998 PRINT(
"error creating bucket "
3011 if (cip->
Encrypt(*bck) == 0) {
3012 PRINT(
"error encrypting bucket - cipher "
3029 EPNAME(
"ParseClientInput");
3034 PRINT(
"invalid inputs ("<<br<<
","<<bm<<
")");
3035 emsg =
"invalid inputs";
3046 emsg =
"error instantiating main buffer";
3052 int ii =
opts.find(
"v:");
3055 sver.erase(sver.find(
','));
3056 hs->
RemVers = atoi(sver.c_str());
3059 emsg =
"server version information not found in options:"
3060 " assume same as local";
3065 emsg =
"error creating cache";
3074 ii =
opts.find(
"id:");
3082 ii =
opts.find(
"po:");
3097 if (GetUserHost(hs->
User,host) != 0) {
3098 emsg =
"error getting user and host";
3106 hs->
Tag += (
"@" + host);
3108 hs->
Tag += (
":" + srvid);
3112 emsg =
"file with server public keys invalid";
3115 char *ptag =
new char[host.
length()+srvid.
length()+10];
3117 sprintf(ptag,
"%s:%s_%d",host.
c_str(),srvid.
c_str(),hs->
CF->
ID());
3119 XrdSutPFEntry *ent = cacheSrvPuk.Get(pfeRef, (
const char *)ptag, &wild);
3125 PRINT(
"could not instantiate session cipher "
3126 "using cipher public info from server");
3127 emsg =
"could not instantiate session cipher ";
3134 emsg =
"server puk not found in cache - tag: ";
3139 emsg =
"could not allocate buffer for server puk tag";
3147 emsg =
"cache entry not found";
3154 emsg =
"cache entry expired";
3165 emsg =
"main buffer missing";
3174 emsg =
"session cipher not found";
3180 emsg =
"error decrypting main buffer with session cipher";
3187 emsg =
"error deserializing main buffer";
3200 memcpy(cid, bp->
buffer, 5);
3204 ptag.erase(0,ptag.find(
'@')+1);
3213 if (
id == hs->
CF->
ID()) {
3218 PRINT(
"could not instantiate session cipher "
3219 "using cipher public info from server");
3220 emsg =
"could not instantiate session cipher ";
3228 PRINT(
"could not create entry in cache - tag: "<<ptag);
3232 bp = bcklst->
Next();
3237 cacheSrvPuk.
Flush();
3251 EPNAME(
"ParseServerInput");
3255 PRINT(
"invalid inputs ("<<br<<
","<<bm<<
")");
3256 cmsg =
"invalid inputs";
3266 cmsg =
"main buffer missing";
3278 cmsg =
"reference cipher missing";
3283 cmsg =
"cannot get reference cipher";
3289 cmsg =
"cannot finalize session cipher";
3301 cmsg =
"error decrypting main buffer with session cipher";
3308 cmsg =
"error deserializing main buffer";
3316 cmsg =
"client version information not found in options:"
3317 " assume same as local";
3328 cmsg =
"cannot create cache entry";
3336 cmsg =
"cache entry expired";
3344 if ((bck = (*bm)->GetBucket(
kXRS_user))) {
3359 const char *msg1,
const char *msg2,
3366 int k, i = 0, sz = strlen(
"Secpwd");
3372 const char *cmsg = (cm > -1) ?
gPWErrStr[cm] : 0;
3376 msgv[i++] = (
char *)
"Secpwd";
3377 if (cmsg) {msgv[i++] = (
char *)
": ";
3378 msgv[i++] = (
char *)cmsg;
3379 sz += strlen(msgv[i-1]) + 2;
3381 if (msg1) {msgv[i++] = (
char *)
": ";
3382 msgv[i++] = (
char *)msg1;
3383 sz += strlen(msgv[i-1]) + 2;
3385 if (msg2) {msgv[i++] = (
char *)
": ";
3386 msgv[i++] = (
char *)msg2;
3387 sz += strlen(msgv[i-1]) + 2;
3389 if (msg3) {msgv[i++] = (
char *)
": ";
3390 msgv[i++] = (
char *)msg3;
3391 sz += strlen(msgv[i-1]) + 2;
3396 einfo->
setErrInfo(ecode, (
const char **)msgv, i);
3399 char *bout =
new char[sz+10];
3402 for (k = 0; k < i; k++)
3403 strcat(bout, msgv[k]);
3406 for (k = 0; k < i; k++)
3425 ErrF(einfo, ecode, msg1, msg2, msg3);
3438 const char *msg1,
const char *msg2,
3444 ErrF(einfo, ecode, msg1, msg2, msg3);
3467 PRINT(
"Bad inputs "<<cf<<
","<<bck<<
")");
3472 if ((!s1 || s1->
size <= 0) && (!s2 || s2->
size <= 0)) {
3473 PRINT(
"Both salts undefined - do nothing");
3478 int ltag = (tag) ? strlen(tag) + 1 : 0;
3484 PRINT(
"Could not get hooks to one-way hash functions ("
3490 char *nhash = 0, *thash = bck->
buffer;
3491 int nhlen = bck->
size;
3492 if (s1 && s1->
size > 0) {
3493 if (!(nhash =
new char[(*
KDFunLen)() + ltag])) {
3494 PRINT(
"Could not allocate memory for hash - s1");
3497 if ((nhlen = (*
KDFun)(thash,nhlen,
3499 PRINT(
"Problems hashing - s1");
3507 if (s2 && s2->
size > 0) {
3508 if (!(nhash =
new char[(*
KDFunLen)() + ltag])) {
3509 PRINT(
"Could not allocate memory for hash - s2");
3512 if (thash && thash != bck->
buffer) thash += ltag;
3513 if ((nhlen = (*
KDFun)(thash,nhlen,
3515 PRINT(
"Problems hashing - s2");
3517 if (thash && thash != bck->
buffer)
delete[] thash;
3520 if (thash && thash != bck->
buffer)
delete[] thash;
3526 memcpy(thash,tag,ltag);
3529 bck->
SetBuf(thash,nhlen+ltag);
3536 int XrdSecProtocolpwd::QueryCrypt(
String &fn,
String &pwhash)
3552 int len = 0, n = 0, fid = -1;
3554 DEBUG(
"analyzing file: "<<fn);
3561 PRINT(
"Cannot get pwnam structure for user "<<hs->
User);
3569 int uid = pw->pw_uid;
3573 bool go = priv.Valid();
3575 PRINT(
"problems acquiring temporarily identity: "<<hs->
User);
3579 String fpw(pw->pw_dir, strlen(pw->pw_dir) + fn.
length() + 5);
3582 DEBUG(
"checking file "<<fpw<<
" for user "<<hs->
User);
3587 if (go &&
stat(fpw.c_str(), &st) == -1) {
3588 if (errno != ENOENT) {
3589 PRINT(
"cannot stat password file "<<fpw<<
" (errno:"<<errno<<
")");
3592 PRINT(
"file "<<fpw<<
" does not exist");
3598 (!S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) ||
3599 (st.st_mode & (S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH)) != 0)) {
3600 PRINT(
"pass file "<<fpw<<
": wrong permissions "<<
3601 (st.st_mode & 0777) <<
" (should be 0600)");
3607 if (go && (fid =
open(fpw.c_str(), O_RDONLY)) == -1) {
3608 PRINT(
"cannot open file "<<fpw<<
" (errno:"<<errno<<
")");
3615 if (go && (n =
read(fid, pass,
sizeof(pass)-1)) <= 0) {
3617 PRINT(
"cannot read file "<<fpw<<
" (errno:"<<errno<<
")");
3627 while (len-- && (pass[len] ==
'\n' || pass[len] == 32))
3642 #ifdef HAVE_SHADOWPW
3647 struct spwd *spw = 0;
3649 if ((spw = getspnam(hs->
User.
c_str())) == 0) {
3650 NOTIFY(
"shadow passwd not accessible to this application");
3652 pwhash = spw->sp_pwdp;
3654 NOTIFY(
"problems acquiring temporarily superuser privileges");
3658 pwhash = pw->pw_passwd;
3664 if ((rc = pwhash.
length()) <= 2) {
3665 NOTIFY(
"passwd hash not available for user "<<hs->
User);
3676 int XrdSecProtocolpwd::QueryNetRc(
String host,
String &passwd,
int &status)
3694 String fnrc = getenv(
"XrdSecNETRC");
3695 if (fnrc.
length() <= 0) {
3696 PRINT(
"File name undefined");
3701 PRINT(
"Problems resolving templates in "<<fnrc);
3704 DEBUG(
"checking file "<<fnrc<<
" for user "<<hs->
User);
3709 if (errno != ENOENT) {
3710 PRINT(
"cannot stat password file "<<fnrc<<
" (errno:"<<errno<<
")");
3712 PRINT(
"file "<<fnrc<<
" does not exist");
3716 if (!S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) ||
3717 (st.st_mode & (S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH)) != 0) {
3718 PRINT(
"pass file "<<fnrc<<
": wrong permissions "<<
3719 (st.st_mode & 0777) <<
" (should be 0600)");
3725 PRINT(
"cannot open file "<<fnrc<<
" (errno:"<<errno<<
")");
3729 int nm = 0, nmmx = -1;
3730 while (fgets(line,
sizeof(line), fid) != 0) {
3734 int nword = sscanf(line,
"%s %s %s %s %s %s", word[0], word[1],
3735 word[2], word[3], word[4], word[5]);
3736 if (nword != 6)
continue;
3737 if (strcmp(word[0],
"machine") || strcmp(word[2],
"login") ||
3738 strcmp(word[4],
"password"))
3741 if ((nm = host.
matches(word[1])) > 0) {
3743 if (!strcmp(hs->
User.
c_str(),word[3])) {
3745 if (nm == host.
length()) {
3775 EPNAME(
"CheckTimeStamp");
3778 if (!bm || skew <= 0) {
3780 emsg =
"input buffer undefined ";
3782 emsg =
"negative skew: invalid ";
3788 if (hs->
RtagOK || VeriClnt != 1) {
3800 emsg =
"bucket with time stamp not found";
3805 dtim = (dtim < 0) ? -dtim : dtim;
3807 emsg =
"time difference too big: ";
emsg += (int)dtim;
3808 emsg +=
" - allowed skew: ";
emsg += skew;
3814 DEBUG(
"Time stamp successfully checked");
3828 emsg =
"Buffer not defined";
3838 emsg =
"Session cipher undefined";
3843 emsg =
"error decrypting random tag with session cipher";
3847 emsg =
"random tag missing - protocol error";
3853 emsg =
"random tag content mismatch";
3866 DEBUG(
"Random tag successfully checked");
3868 NOTIFY(
"Nothing to check");
void XrdCryptoSetTrace(kXR_int32 trace)
static XrdSysError eDest(0,"crypto_")
#define cryptoTRACE_Notify
int(* XrdCryptoKDFunLen_t)()
#define cryptoTRACE_Debug
int(* XrdCryptoKDFun_t)(const char *pass, int plen, const char *salt, int slen, char *key, int klen)
int stat(const char *path, struct stat *buf)
int open(const char *path, int oflag,...)
ssize_t write(int fildes, const void *buf, size_t nbyte)
ssize_t read(int fildes, void *buf, size_t nbyte)
XrdSecBuffer XrdSecParameters
XrdSecBuffer XrdSecCredentials
static const short kOptsChngPwd
XrdVERSIONINFO(XrdSecProtocolpwdInit, secpwd)
char * XrdSecProtocolpwdInit(const char mode, const char *parms, XrdOucErrInfo *erp)
static const short kOptsAutoReg
static const char * pwdServerSteps[]
static const short kOptsUserPwd
static const short kOptsServer
static const short kOptsExpCred
static const char * ServerStepStr(int ksrv)
static const kXR_int32 Version
static const char * pwdClientSteps[]
XrdSecProtocol * XrdSecProtocolpwdObject(const char mode, const char *hostname, XrdNetAddrInfo &endPoint, const char *parms, XrdOucErrInfo *erp)
static const short kOptsAFSPwd
static const short kOptsCrypPwd
static const short kOptsVeriClt
static const char * gPWErrStr[]
static const short kOptsClntTty
static const short kOptsVeriSrv
static const short kOptsAregAll
static const char * ClientStepStr(int kclt)
XrdCryptoKDFunLen_t KDFunLen
int emsg(int rc, char *msg)
int XrdSutGetPass(const char *prompt, XrdOucString &passwd)
int XrdSutParseTime(const char *tstr, int opt)
int XrdSutExpand(XrdOucString &path)
int XrdSutResolve(XrdOucString &path, const char *ho, const char *vo, const char *gr, const char *us)
int XrdSutToHex(const char *in, int lin, char *out)
const char * XrdSutHome()
int XrdSutMkdir(const char *dir, unsigned int mode, const char *opt)
const char * XrdSutBuckStr(int kbck)
void XrdSutSetTrace(kXR_int32 trace)
int XrdSutFromHex(const char *in, char *out, int &lout)
int XrdSutGetLine(XrdOucString &line, const char *prompt)
virtual int Decrypt(const char *in, int lin, char *out)
virtual int Encrypt(const char *in, int lin, char *out)
virtual char * Public(int &lpub)
virtual bool Finalize(bool padded, char *pub, int lpub, const char *t)
virtual void SetTrace(kXR_int32 trace)
virtual XrdCryptoKDFun_t KDFun()
virtual XrdCryptoCipher * Cipher(const char *t, int l=0)
virtual XrdCryptoKDFunLen_t KDFunLen()
static XrdCryptoFactory * GetCryptoFactory(const char *factoryname)
int setErrInfo(int code, const char *emsg)
void insert(const int i, int start=-1)
const char * c_str() const
void assign(const char *s, int j, int k=-1)
int erase(int start=0, int size=0)
int matches(const char *s, char wch=' *')
int rfind(const char c, int start=STR_NPOS)
int replace(const char *s1, const char *s2, int from=0, int to=-1)
int find(const char c, int start=0, bool forward=1)
int tokenize(XrdOucString &tok, int from, char del=':')
char * GetToken(char **rest=0, int lowcase=0)
char * vorg
Entity's virtual organization(s)
XrdNetAddrInfo * addrInfo
Entity's connection details.
const char * tident
Trace identifier always preset.
char prot[XrdSecPROTOIDSIZE]
Auth protocol used (e.g. krb5)
char * grps
Entity's group name(s)
char * name
Entity's name.
char * host
Entity's host name dnr dependent.
XrdSecProtocolpwd(int opts, const char *hname, XrdNetAddrInfo &endPoint, const char *parms=0)
static char * Init(pwdOptions o, XrdOucErrInfo *erp)
void Delete()
Delete the protocol object. DO NOT use C++ delete() on this object.
int Authenticate(XrdSecCredentials *cred, XrdSecParameters **parms, XrdOucErrInfo *einfo=0)
XrdSecCredentials * getCredentials(XrdSecParameters *parm=0, XrdOucErrInfo *einfo=0)
static XrdOucTrace * EnableTracing()
int SetBuf(const char *nb=0, int ns=0)
void ToString(XrdOucString &s)
void Update(char *nb=0, int ns=0, int ty=0)
int AddBucket(char *bp=0, int sz=0, int ty=0)
int UpdateBucket(const char *bp, int sz, int ty)
void Message(const char *prepose=0)
int Serialized(char **buffer, char opt='n')
const char * GetOptions() const
void Dump(const char *stepstr=0, bool all=false)
XrdSutBucket * GetBucket(kXR_int32 type, const char *tag=0)
kXR_int32 MarshalBucket(kXR_int32 type, kXR_int32 code)
const char * GetProtocol() const
void Deactivate(kXR_int32 type)
kXR_int32 UnmarshalBucket(kXR_int32 type, kXR_int32 &code)
void SetBuf(const char *b=0, kXR_int32 l=0)
int Flush(const char *pfname=0)
XrdSutPFEntry * Add(XrdSutPFCacheRef &urRef, const char *ID, bool force=0)
int Init(int capacity=100, bool lock=1)
void Dump(const char *msg=0)
int Load(const char *pfname)
void SetName(const char *n=0)
const char * Name() const
kXR_int32 ReadEntry(const char *name, XrdSutPFEntry &ent, int opt=0)
bool Init(const char *n, kXR_int32 openmode=kPFEcreate, kXR_int32 createmode=0600, bool hashtab=1)
static int GetRndmTag(XrdOucString &rtag)
static char * GetBuffer(int len, int opt=-1)
XrdSysLogger * logger(XrdSysLogger *lp=0)
void Print(XrdOucTrace *t)
Generic structure to pass security information back and forth.
char * buffer
Pointer to the buffer.
int size
Size of the buffer or length of data in the buffer.