00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <unistd.h>
00012 #include <ctype.h>
00013 #include <errno.h>
00014 #include <stdlib.h>
00015 #include <strings.h>
00016 #include <stdio.h>
00017 #include <sys/param.h>
00018 #include <pwd.h>
00019 #include <sys/types.h>
00020 #include <sys/stat.h>
00021 #include <fcntl.h>
00022 #include <sys/times.h>
00023
00024
00025 #ifdef R__AFS
00026 extern "C" {
00027 #include <afs/stds.h>
00028 #include <afs/kautils.h>
00029 afs_int32 ka_Authenticate(char *name, char *instance, char *cell,
00030 struct ubik_client *conn, int service,
00031 struct ktc_encryptionKey *key, Date start,
00032 Date end, struct ktc_token *token,
00033 afs_int32 * pwexpires);
00034 afs_int32 ka_ReadPassword(char *prompt, int verify, char *cell,
00035 struct ktc_encryptionKey *key);
00036 afs_int32 ka_AuthServerConn(char *cell, int service,
00037 struct ktc_token *token,
00038 struct ubik_client **conn);
00039 char *ka_LocalCell();
00040 void ka_StringToKey(char *str, char *cell,
00041 struct ktc_encryptionKey *key);
00042 }
00043 #endif
00044
00045 #include "XrdSys/XrdSysHeaders.hh"
00046 #include <XrdSys/XrdSysLogger.hh>
00047 #include <XrdSys/XrdSysError.hh>
00048 #include <XrdOuc/XrdOucStream.hh>
00049
00050 #include <XrdSys/XrdSysPriv.hh>
00051
00052 #include <XrdSut/XrdSutCache.hh>
00053
00054 #include <XrdSecpwd/XrdSecProtocolpwd.hh>
00055 #include <XrdSecpwd/XrdSecpwdPlatform.hh>
00056
00057
00058
00059
00060
00061 static String Prefix = "xrd";
00062 static String ProtoID = XrdSecPROTOIDENT;
00063 static const kXR_int32 Version = XrdSecpwdVERSION;
00064 static String AdminRef = ProtoID + "admin";
00065 static String SrvPukRef= ProtoID + "srvpuk";
00066 static String UserRef = ProtoID + "user";
00067 static String NetRcRef = ProtoID + "netrc";
00068
00069 static const char *pwdClientSteps[] = {
00070 "kXPC_none",
00071 "kXPC_normal",
00072 "kXPC_verifysrv",
00073 "kXPC_signedrtag",
00074 "kXPC_creds",
00075 "kXPC_autoreg",
00076 "kXPC_failureack",
00077 "kXPC_reserved"
00078 };
00079
00080 static const char *pwdServerSteps[] = {
00081 "kXPS_none",
00082 "kXPS_init",
00083 "kXPS_credsreq",
00084 "kXPS_rtag",
00085 "kXPS_signedrtag",
00086 "kXPS_newpuk",
00087 "kXPS_puk",
00088 "kXPS_failure",
00089 "kXPS_reserved"
00090 };
00091
00092 static const char *gPWErrStr[] = {
00093 "parsing buffer",
00094 "decoding buffer",
00095 "loading crypto factory",
00096 "protocol mismatch",
00097 "resolving user / host",
00098 "user missing",
00099 "host missing",
00100 "unknown user",
00101 "creating bucket",
00102 "duplicating bucket",
00103 "creating buffer",
00104 "serializing buffer",
00105 "generating cipher",
00106 "exporting public key",
00107 "encrypting random tag",
00108 "random tag mismatch",
00109 "random tag missing",
00110 "cipher missing",
00111 "getting credentials",
00112 "credentials missing",
00113 "wrong password for user",
00114 "checking cache",
00115 "cache entry for link missing",
00116 "session handshaking ID missing",
00117 "session handshaking ID mismatch",
00118 "unknown step option",
00119 "marshaling integer",
00120 "unmarshaling integer",
00121 "saving new credentials",
00122 "salt missing",
00123 "buffer empty",
00124 "obtaining reference cipher",
00125 "obtaining cipher public info",
00126 "adding bucket to list",
00127 "finalizing cipher from public info",
00128 "error during initialization",
00129 "wrong credentials",
00130 "error"
00131 };
00132
00133
00134 static const short kOptsServer = 0x0001;
00135 static const short kOptsUserPwd = 0x0002;
00136 static const short kOptsAutoReg = 0x0004;
00137 static const short kOptsAregAll = 0x0008;
00138 static const short kOptsVeriSrv = 0x0020;
00139 static const short kOptsVeriClt = 0x0040;
00140 static const short kOptsClntTty = 0x0080;
00141 static const short kOptsExpCred = 0x0100;
00142 static const short kOptsCrypPwd = 0x0200;
00143 static const short kOptsChngPwd = 0x0400;
00144 static const short kOptsAFSPwd = 0x0800;
00145
00146 static const int kOneDay = 86400;
00147
00148
00149
00150
00151 XrdSysMutex XrdSecProtocolpwd::pwdContext;
00152 String XrdSecProtocolpwd::FileAdmin= "";
00153 String XrdSecProtocolpwd::FileExpCreds= "";
00154 String XrdSecProtocolpwd::FileUser = "";
00155 String XrdSecProtocolpwd::FileCrypt= "/.xrdpass";
00156 String XrdSecProtocolpwd::FileSrvPuk= "";
00157 String XrdSecProtocolpwd::SrvID = "";
00158 String XrdSecProtocolpwd::SrvEmail = "";
00159 String XrdSecProtocolpwd::DefCrypto= "ssl";
00160 String XrdSecProtocolpwd::DefError = "insufficient credentials - contact ";
00161 XrdSutPFile XrdSecProtocolpwd::PFAdmin(0);
00162 XrdSutPFile XrdSecProtocolpwd::PFAlog(0);
00163 XrdSutPFile XrdSecProtocolpwd::PFSrvPuk(0);
00164
00165
00166 int XrdSecProtocolpwd::ncrypt = 0;
00167 int XrdSecProtocolpwd::cryptID[XrdCryptoMax] = {0};
00168 String XrdSecProtocolpwd::cryptName[XrdCryptoMax] = {0};
00169 XrdCryptoCipher *XrdSecProtocolpwd::refcip[XrdCryptoMax] = {0};
00170
00171
00172 XrdSutCache XrdSecProtocolpwd::cacheAdmin;
00173 XrdSutCache XrdSecProtocolpwd::cacheSrvPuk;
00174 XrdSutCache XrdSecProtocolpwd::cacheUser;
00175 XrdSutCache XrdSecProtocolpwd::cacheAlog;
00176
00177
00178 int XrdSecProtocolpwd::Debug = 0;
00179 bool XrdSecProtocolpwd::Server = 1;
00180 int XrdSecProtocolpwd::UserPwd = 0;
00181 bool XrdSecProtocolpwd::SysPwd = 0;
00182 int XrdSecProtocolpwd::VeriClnt = 2;
00183
00184 int XrdSecProtocolpwd::VeriSrv = 1;
00185
00186 int XrdSecProtocolpwd::AutoReg = kpAR_none;
00187 int XrdSecProtocolpwd::LifeCreds = 0;
00188 int XrdSecProtocolpwd::MaxPrompts = 3;
00189 int XrdSecProtocolpwd::MaxFailures = 10;
00190 int XrdSecProtocolpwd::AutoLogin = 0;
00191 int XrdSecProtocolpwd::TimeSkew = 300;
00192 bool XrdSecProtocolpwd::KeepCreds = 0;
00193
00194
00195 XrdSysError XrdSecProtocolpwd::eDest(0, "secpwd_");
00196 XrdSysLogger XrdSecProtocolpwd::Logger;
00197 XrdOucTrace *XrdSecProtocolpwd::SecTrace = 0;
00198
00199
00200
00201
00202
00203 static const char *ClientStepStr(int kclt)
00204 {
00205
00206 static const char *ukn = "Unknown";
00207
00208 kclt = (kclt < 0) ? 0 : kclt;
00209 kclt = (kclt > kXPC_reserved) ? 0 : kclt;
00210 kclt = (kclt >= kXPC_normal) ? (kclt - kXPC_normal + 1) : kclt;
00211
00212 if (kclt < 0 || kclt > (kXPC_reserved - kXPC_normal + 1))
00213 return ukn;
00214 else
00215 return pwdClientSteps[kclt];
00216 }
00217
00218
00219 static const char *ServerStepStr(int ksrv)
00220 {
00221
00222 static const char *ukn = "Unknown";
00223
00224 ksrv = (ksrv < 0) ? 0 : ksrv;
00225 ksrv = (ksrv > kXPS_reserved) ? 0 : ksrv;
00226 ksrv = (ksrv >= kXPS_init) ? (ksrv - kXPS_init + 1) : ksrv;
00227
00228 if (ksrv < 0 || ksrv > (kXPS_reserved - kXPS_init + 1))
00229 return ukn;
00230 else
00231 return pwdServerSteps[ksrv];
00232 }
00233
00234
00235
00236
00237
00238
00239
00240 XrdSecProtocolpwd::XrdSecProtocolpwd(int opts, const char *hname,
00241 const struct sockaddr *ipadd,
00242 const char *parms) : XrdSecProtocol("pwd")
00243 {
00244
00245 EPNAME("XrdSecProtocolpwd");
00246
00247 if (QTRACE(Authen)) { PRINT("constructing: "<<this); }
00248
00249
00250 if ((hs = new pwdHSVars())) {
00251
00252 hs->TimeStamp = time(0);
00253
00254 hs->CryptoMod = "";
00255 hs->User = "";
00256 hs->Tag.resize(256);
00257 hs->RemVers = -1;
00258 hs->CF = 0;
00259 hs->Hcip = 0;
00260 hs->Rcip = 0;
00261 hs->ID = "";
00262 hs->Cref = 0;
00263 hs->Pent = 0;
00264 hs->RtagOK = 0;
00265 hs->Tty = (isatty(0) == 0 || isatty(1) == 0) ? 0 : 1;
00266 hs->Step = 0;
00267 hs->LastStep = 0;
00268 } else {
00269 DEBUG("could not create handshake vars object");
00270 }
00271
00272
00273 clientCreds = 0;
00274
00275
00276 if (hname) {
00277 Entity.host = strdup(hname);
00278 } else {
00279 DEBUG("warning: host name undefined");
00280 }
00281
00282 memcpy(&hostaddr, ipadd, sizeof(hostaddr));
00283
00284 CName[0] = '?'; CName[1] = '\0';
00285
00286
00287
00288 DEBUG("constructing: host: "<<hname);
00289 DEBUG("p: "<<XrdSecPROTOIDENT<<", plen: "<<XrdSecPROTOIDLEN);
00290
00291
00292 options = opts;
00293
00294
00295
00296 if (Server) {
00297 srvMode = 1;
00298 DEBUG("mode: server");
00299 } else {
00300 srvMode = 0;
00301 DEBUG("mode: client");
00302 if (AutoLogin > 0) {
00303 DEBUG("using autologin file: "<<PFAlog.Name());
00304 if (AutoLogin > 1) {
00305 DEBUG("running in update-autologin mode");
00306 }
00307 }
00308 if (VeriSrv > 0) {
00309 DEBUG("server verification ON");
00310 } else {
00311 DEBUG("server verification OFF");
00312 }
00313
00314 if (parms) {
00315 XrdOucString p("&P=pwd,");
00316 p += parms;
00317 hs->Parms = new XrdSutBuffer(p.c_str(), p.length());
00318 }
00319 }
00320
00321
00322 String vers = Version;
00323 vers.insert('.',vers.length()-2);
00324 vers.insert('.',vers.length()-5);
00325 DEBUG("object created: v"<<vers.c_str());
00326 }
00327
00328
00329 char *XrdSecProtocolpwd::Init(pwdOptions opt, XrdOucErrInfo *erp)
00330 {
00331
00332
00333 EPNAME("Init");
00334 char *Parms = 0;
00335
00336
00337 Debug = (opt.debug > -1) ? opt.debug : Debug;
00338
00339 eDest.logger(&Logger);
00340 SecTrace = new XrdOucTrace(&eDest);
00341
00342 int trace = 0;
00343 if (Debug >= 3) {
00344 trace = cryptoTRACE_Dump;
00345 SecTrace->What |= TRACE_Authen;
00346 SecTrace->What |= TRACE_Debug;
00347 } else if (Debug >= 1) {
00348 trace = cryptoTRACE_Debug;
00349 SecTrace->What = TRACE_Debug;
00350 }
00351
00352 XrdSutSetTrace(trace);
00353 XrdCryptoSetTrace(trace);
00354
00355
00356 struct passwd *pw = getpwuid(getuid());
00357 if (!pw) {
00358 PRINT("no user info available - invalid ");
00359 ErrF(erp, kPWErrInit, "could not get user info from getpwuid");
00360 return Parms;
00361 }
00362
00363
00364
00365 Server = (opt.mode == 's');
00366
00367
00368
00369 bool argdir = 0;
00370 String infodir(512);
00371 if (opt.dir) {
00372 infodir = opt.dir;
00373
00374 if (XrdSutExpand(infodir) != 0) {
00375 PRINT("cannot expand "<<opt.dir);
00376 infodir = "";
00377 }
00378 argdir = 1;
00379 } else {
00380
00381 infodir = XrdSutHome();
00382 infodir += ("/." + Prefix);
00383 }
00384 if (!infodir.endswith("/")) infodir += "/";
00385
00386
00387 if (infodir.length()) {
00388
00389 XrdSysPrivGuard priv(pw->pw_uid, pw->pw_gid);
00390 if (priv.Valid()) {
00391 struct stat st;
00392 if (stat(infodir.c_str(),&st) == -1) {
00393 if (errno == ENOENT) {
00394 if (argdir) {
00395 DEBUG("infodir non existing: "<<infodir.c_str());
00396 } else {
00397 DEBUG("creating infodir: "<<infodir.c_str());
00398 if (XrdSutMkdir(infodir.c_str(),0777) != 0) {
00399 DEBUG("cannot create infodir (errno: "<<errno<<")");
00400 infodir = "";
00401 argdir = 0;
00402 }
00403 }
00404 } else {
00405 DEBUG("cannot stat infodir "<<infodir<<" (errno: "<<errno<<")");
00406 infodir = "";
00407 argdir = 0;
00408 }
00409 }
00410 }
00411 }
00412 DEBUG("using infodir: "<<infodir.c_str());
00413
00414
00415
00416 if (Server) {
00417
00418
00419 AutoReg = (opt.areg > -1) ? opt.areg : AutoReg;
00420
00421
00422 VeriClnt = (opt.vericlnt > -1) ? opt.vericlnt : VeriClnt;
00423
00424
00425 UserPwd = (opt.upwd > -1) ? opt.upwd : UserPwd;
00426
00427
00428 SysPwd = (opt.syspwd > -1) ? opt.syspwd : SysPwd;
00429 if (SysPwd) {
00430
00431 if (pw) {
00432 #ifndef R__AFS
00433 #ifdef R__SHADOWPW
00434
00435 XrdSysPrivGuard priv((uid_t) 0, (gid_t) 0);
00436 if (priv.Valid()) {
00437
00438 struct spwd *spw = getspnam(pw->pw_name);
00439 if (!spw) {
00440 SysPwd = 0;
00441 DEBUG("no privileges to access shadow passwd file");
00442 }
00443 } else {
00444 DEBUG("problems acquiring credentials"
00445 " to access the system password file");
00446 }
00447 #else
00448
00449 if (!pw->pw_passwd &&
00450 (pw->pw_passwd && strlen(pw->pw_passwd) <= 1)) {
00451 SysPwd = 0;
00452 DEBUG("no privileges to access system passwd file");
00453 }
00454 #endif
00455 #else
00456 PRINT("configured with AFS support");
00457 #endif
00458 } else
00459 SysPwd = 0;
00460 }
00461
00462
00463 LifeCreds = (opt.lifecreds > -1) ? opt.lifecreds : LifeCreds;
00464
00465
00466 MaxFailures = (opt.maxfailures > -1) ? opt.maxfailures : MaxFailures;
00467
00468
00469
00470 if (infodir.length()) {
00471
00472 XrdSysPrivGuard priv(pw->pw_uid, pw->pw_gid);
00473 if (priv.Valid()) {
00474 struct stat st;
00475
00476
00477 FileAdmin = infodir + AdminRef;
00478 if (stat(FileAdmin.c_str(),&st) == -1) {
00479 if (errno == ENOENT) {
00480 PRINT("FileAdmin non existing: "<<FileAdmin.c_str());
00481 } else {
00482 PRINT("cannot stat FileAdmin (errno: "<<errno<<")");
00483 }
00484 FileAdmin = "";
00485 if (UserPwd == 0 && !SysPwd) {
00486 PRINT("no passwd info available - invalid ");
00487 ErrF(erp,kPWErrInit,"could not find a valid password file");
00488 return Parms;
00489 }
00490 }
00491 if (FileAdmin.length() > 0) {
00492
00493
00494 PFAdmin.Init(FileAdmin.c_str(),0);
00495 if (PFAdmin.IsValid()) {
00496
00497
00498 if (cacheAdmin.Load(FileAdmin.c_str()) != 0) {
00499 PRINT("problems init cache for file admin ");
00500 ErrF(erp,kPWErrError,"initializing cache for file admin");
00501 return Parms;
00502 }
00503 if (QTRACE(Authen)) { cacheAdmin.Dump(); }
00504 XrdSutPFEntry *ent = cacheAdmin.Get("+++SrvID");
00505 if (ent)
00506 SrvID.insert(ent->buf1.buf, 0, ent->buf1.len);
00507 ent = cacheAdmin.Get("+++SrvEmail");
00508 if (ent)
00509 SrvEmail.insert(ent->buf1.buf, 0, ent->buf1.len);
00510
00511 DefError += SrvEmail;
00512 }
00513 DEBUG("server ID: "<<SrvID);
00514 DEBUG("contact e-mail: "<<SrvEmail);
00515 }
00516 }
00517 } else if (UserPwd == 0 && !SysPwd) {
00518 PRINT("no passwd info available - invalid ");
00519 ErrF(erp,kPWErrError,"could not find a valid password file");
00520 return Parms;
00521 }
00522
00523
00524 if (UserPwd > 0 || SysPwd) {
00525 if (cacheUser.Init(100) != 0) {
00526 PRINT("problems init cache for user pwd info"
00527 " - passwd files in user accounts will not be used");
00528 UserPwd = 0;
00529 }
00530 }
00531
00532
00533
00534 String cryptlist = opt.clist ? (const char *)(opt.clist) : DefCrypto;
00535
00536
00537
00538 XrdSutPFEntry ent;
00539 XrdCryptoFactory *cf = 0;
00540 String clist = cryptlist;
00541 if (clist.length()) {
00542 String ncpt = "";
00543 int from = 0;
00544 while ((from = clist.tokenize(ncpt, from, '|')) != -1) {
00545 if (ncpt.length() > 0) {
00546
00547 if ((cf = XrdCryptoFactory::GetCryptoFactory(ncpt.c_str()))) {
00548
00549 cryptID[ncrypt] = cf->ID();
00550 cryptName[ncrypt].insert(cf->Name(),0,strlen(cf->Name())+1);
00551 cf->SetTrace(trace);
00552
00553 String ptag("+++SrvPuk_");
00554 ptag += cf->ID();
00555 if (FileAdmin.length() > 0) {
00556
00557 XrdSysPrivGuard priv(pw->pw_uid, pw->pw_gid);
00558 if (priv.Valid()) {
00559 if (PFAdmin.ReadEntry(ptag.c_str(),ent) <= 0) {
00560 PRINT("ref cipher for module "<<ncpt<<" missing: disable");
00561 cryptlist.erase(ncpt);
00562 } else {
00563 XrdSutBucket bck;
00564 bck.SetBuf(ent.buf1.buf,ent.buf1.len);
00565 if (!(refcip[ncrypt] = cf->Cipher(&bck))) {
00566 PRINT("ref cipher for module "<<ncpt<<
00567 " cannot be instantiated : disable");
00568 cryptlist.erase(ncpt);
00569 } else {
00570 ncrypt++;
00571 if (ncrypt >= XrdCryptoMax) {
00572 PRINT("max number of crypto modules ("
00573 << XrdCryptoMax <<") reached ");
00574 break;
00575 }
00576 }
00577 }
00578 }
00579 }
00580 } else {
00581 PRINT("cannot instantiate crypto factory "<<ncpt);
00582 }
00583 }
00584 }
00585 }
00586
00587
00588
00589 if (ncrypt <= 0) {
00590 PRINT("could not find any valid crypto module");
00591 ErrF(erp,kPWErrInit,"could not find any valid crypto module");
00592 return Parms;
00593 }
00594
00595
00596
00597 if (UserPwd > 0) {
00598 FileUser = ("/" + UserRef);
00599 if (opt.udir) {
00600 FileUser.insert(opt.udir,0);
00601 if (FileUser[0] != '/') FileUser.insert('/',0);
00602 } else {
00603
00604 FileUser.insert(Prefix,0);
00605 FileUser.insert("/.",0);
00606 }
00607
00608
00609 if (opt.cpass) {
00610 UserPwd = 2;
00611 FileCrypt = opt.cpass;
00612 if (FileCrypt[0] != '/') FileCrypt.insert('/',0);
00613 }
00614 }
00615
00616
00617
00618 KeepCreds = (opt.keepcreds > -1) ? opt.keepcreds : KeepCreds;
00619 if (KeepCreds)
00620 PRINT("Exporting client creds to internal buffer");
00621
00622
00623
00624 FileExpCreds = (opt.expcreds) ? opt.expcreds : FileExpCreds;
00625 if (FileExpCreds.length() > 0)
00626 PRINT("Exporting client creds to files "<<FileExpCreds);
00627
00628
00629
00630 String popt = "";
00631 if (SysPwd) {
00632 #ifndef R__AFS
00633 popt += "sys";
00634 #else
00635 popt += "afs";
00636 popt += ka_LocalCell();
00637 #endif
00638 }
00639
00640
00641
00642 Parms = new char[cryptlist.length()+3+12+SrvID.length()+5+popt.length()+3];
00643 if (Parms) {
00644 if (popt.length() > 0)
00645 sprintf(Parms,"v:%d,id:%s,c:%s,po:%s",
00646 Version,SrvID.c_str(),cryptlist.c_str(),popt.c_str());
00647 else
00648 sprintf(Parms,"v:%d,id:%s,c:%s",
00649 Version,SrvID.c_str(),cryptlist.c_str());
00650 } else {
00651 PRINT("no system resources for 'Parms'");
00652 ErrF(erp,kPWErrInit,"no system resources for 'Parms'");
00653 }
00654
00655
00656 DEBUG("using FileAdmin: "<<FileAdmin);
00657 DEBUG("server ID: "<<SrvID);
00658 DEBUG("contact e-mail: "<<SrvEmail);
00659 DEBUG("auto-registration mode: "<<AutoReg);
00660 DEBUG("verify client mode: "<<VeriClnt);
00661 DEBUG("available crypto modules: "<<cryptlist);
00662 if (UserPwd > 0) {
00663 DEBUG("using private pwd files: $(HOME)"<<FileUser);
00664 if (UserPwd > 1) {
00665 DEBUG("using private crypt-hash files: $(HOME)"<<FileCrypt);
00666 }
00667 }
00668 if (SysPwd) {
00669 #ifndef R__AFS
00670 DEBUG("using system pwd information");
00671 #else
00672 DEBUG("using AFS information");
00673 #endif
00674 }
00675 if (KeepCreds) {
00676 DEBUG("client credentials will be kept");
00677 }
00678 }
00679
00680
00681
00682 if (!Server) {
00683
00684
00685 VeriSrv = (opt.verisrv > -1) ? opt.verisrv : VeriSrv;
00686
00687
00688 FileSrvPuk = "";
00689 if (opt.srvpuk) {
00690 FileSrvPuk = opt.srvpuk;
00691 if (XrdSutExpand(FileSrvPuk) != 0) {
00692 PRINT("cannot expand "<<opt.srvpuk);
00693 FileSrvPuk = "";
00694 }
00695 }
00696
00697
00698 if (FileSrvPuk.length() <= 0 && infodir.length() > 0)
00699 FileSrvPuk = infodir + SrvPukRef;
00700
00701 if (FileSrvPuk.length() > 0) {
00702 kXR_int32 openmode = 0;
00703 struct stat st;
00704
00705 if (stat(FileSrvPuk.c_str(),&st) == -1) {
00706 if (errno == ENOENT) {
00707 PRINT("server public key file "<<FileSrvPuk<<" non existing: creating");
00708 openmode = kPFEcreate;
00709
00710 XrdOucString dir = FileSrvPuk;
00711 dir.erase(dir.rfind('/')+1);
00712 DEBUG("asserting dir: "<<dir);
00713 if (XrdSutMkdir(dir.c_str(),0777) != 0) {
00714 DEBUG("cannot create dir for srvpuk(errno: "<<errno<<")");
00715 ErrF(erp,kPWErrInit,"cannot create dir for server public key file- exit");
00716 return Parms;
00717 }
00718 } else {
00719 PRINT("cannot stat server public key file (errno: "<<errno<<")");
00720 FileSrvPuk = "";
00721 PRINT("server public key file invalid - exit");
00722 ErrF(erp,kPWErrInit,"server public key file invalid - exit");
00723 return Parms;
00724 }
00725 }
00726
00727
00728 PFSrvPuk.Init(FileSrvPuk.c_str(),openmode);
00729 if (PFSrvPuk.IsValid()) {
00730
00731
00732 if (cacheSrvPuk.Load(FileSrvPuk.c_str()) != 0) {
00733 PRINT("problems init cache for server public key file ");
00734 ErrF(erp,kPWErrError,"initializing cache for server public key file ");
00735 return Parms;
00736 }
00737 if (QTRACE(Authen)) { cacheSrvPuk.Dump(); }
00738 } else {
00739 PRINT("server public key file invalid ");
00740 ErrF(erp,kPWErrInit,"server public key file invalid");
00741 return Parms;
00742 }
00743 } else {
00744 PRINT("server public key file undefined");
00745 ErrF(erp,kPWErrInit,"server public key file undefined");
00746 return Parms;
00747 }
00748
00749
00750
00751 AutoLogin = (opt.alog > -1) ? opt.alog : AutoLogin;
00752 DEBUG("AutoLogin level: "<<AutoLogin);
00753
00754
00755 MaxPrompts = (opt.maxprompts > -1) ? opt.maxprompts : MaxPrompts;
00756
00757
00758 if (AutoLogin > 0) {
00759 bool filefound = 0;
00760 String fnrc(256);
00761 if (opt.alogfile) {
00762 fnrc = opt.alogfile;
00763 if (XrdSutExpand(fnrc) != 0) {
00764 PRINT("cannot expand "<<opt.alogfile);
00765 fnrc = "";
00766 }
00767 }
00768
00769
00770 if (fnrc.length() <= 0)
00771
00772 fnrc = infodir + NetRcRef;
00773
00774 if (fnrc.length() > 0) {
00775 kXR_int32 openmode = 0;
00776 struct stat st;
00777 if (stat(fnrc.c_str(),&st) == -1) {
00778 if (errno == ENOENT) {
00779 PRINT("Autologin file "<<fnrc<<" non existing: creating");
00780 openmode = kPFEcreate;
00781 } else {
00782 PRINT("cannot stat autologin file (errno: "<<errno<<")");
00783 PRINT("switching off auto-login");
00784 AutoLogin = 0;
00785 }
00786 }
00787
00788 if (AutoLogin > 0) {
00789
00790 PFAlog.Init(fnrc.c_str(),openmode);
00791 if (PFAlog.IsValid()) {
00792
00793 if (cacheAlog.Load(fnrc.c_str()) == 0) {
00794 if (QTRACE(Authen)) { cacheAlog.Dump(); }
00795 filefound =1;
00796 } else {
00797 PRINT("problems init cache for autologin file");
00798 }
00799 } else {
00800 PRINT("problems attaching-to / creating autologin file");
00801 }
00802 }
00803 }
00804
00805
00806 if (!filefound) {
00807 DEBUG("could not init properly autologin - switch off ");
00808 AutoLogin = 0;
00809 }
00810 }
00811
00812
00813 if (AutoLogin <= 0) {
00814
00815 if (cacheAlog.Init(100) != 0) {
00816 PRINT("problems init cache for user temporary autolog");
00817 }
00818 }
00819
00820 Parms = (char *)"";
00821 }
00822
00823
00824 return Parms;
00825 }
00826
00827
00828
00829
00830 void XrdSecProtocolpwd::Delete()
00831 {
00832
00833 if (Entity.host) free(Entity.host);
00834
00835 SafeDelete(hs);
00836 delete this;
00837 }
00838
00839
00840
00841
00842
00843
00844
00845
00846 XrdSecCredentials *XrdSecProtocolpwd::getCredentials(XrdSecParameters *parm,
00847 XrdOucErrInfo *ei)
00848 {
00849
00850
00851 EPNAME("getCredentials");
00852
00853
00854
00855 if (srvMode) {
00856 XrdSecCredentials *creds = 0;
00857 if (clientCreds) {
00858
00859 int sz = clientCreds->size;
00860 char *nbuf = (char *) malloc(sz);
00861 if (nbuf) {
00862 memcpy(nbuf, clientCreds->buffer, sz);
00863 creds = new XrdSecCredentials(nbuf, sz);
00864 }
00865 }
00866 return creds;
00867 }
00868
00869
00870 if (!hs)
00871 return ErrC(ei,0,0,0,kPWErrError,
00872 "handshake var container missing","getCredentials");
00873 hs->ErrMsg = "";
00874
00875
00876
00877 if ((!parm && !hs->Parms) || (parm && (!(parm->buffer) || parm->size <= 0)))
00878 return ErrC(ei,0,0,0,kPWErrNoBuffer,"missing parameters","getCredentials");
00879
00880
00881 (hs->Iter)++;
00882
00883
00884 hs->TimeStamp = time(0);
00885
00886
00887 int nextstep = 0;
00888 const char *stepstr = 0;
00889 kXR_int32 status = 0;
00890 char *bpub = 0;
00891 int lpub = 0;
00892 String CryptList = "";
00893 String Host = "";
00894 String RemID = "";
00895 String Emsg;
00896 String specID = "";
00897
00898 XrdSutBucket *bck = 0;
00899 XrdSutBuffer *bpar = 0;
00900 XrdSutBuffer *bmai = 0;
00901
00902 pwdStatus_t SessionSt;
00903 memset(&SessionSt,0,sizeof(SessionSt));
00904
00905
00906
00907 XrdSysMutexHelper pwdGuard(&pwdContext);
00908
00909
00910 bpar = hs->Parms;
00911 if (!bpar && !(bpar = new XrdSutBuffer((const char *)parm->buffer,parm->size)))
00912 return ErrC(ei,0,0,0,kPWErrDecodeBuffer,"global",stepstr);
00913
00914 hs->Parms = 0;
00915
00916
00917 if (strcmp(bpar->GetProtocol(),XrdSecPROTOIDENT))
00918 return ErrC(ei,bpar,bmai,0,kPWErrBadProtocol,stepstr);
00919
00920
00921 hs->Step = (bpar->GetStep()) ? bpar->GetStep() : kXPS_init;
00922 stepstr = ServerStepStr(hs->Step);
00923
00924 if (QTRACE(Authen)) {
00925 bpar->Dump(stepstr);
00926 }
00927
00928
00929 if (ParseCrypto(bpar) != 0)
00930 return ErrC(ei,bpar,0,0,kPWErrLoadCrypto,stepstr);
00931
00932
00933 if (ParseClientInput(bpar, &bmai, Emsg) == -1) {
00934 DEBUG(Emsg);
00935 return ErrC(ei,bpar,bmai,0,kPWErrParseBuffer,Emsg.c_str(),stepstr);
00936 }
00937
00938
00939 DEBUG("version run by server: "<< hs->RemVers);
00940
00941
00942 if (QTRACE(Authen)) {
00943 bmai->Dump("Main IN");
00944 }
00945
00946
00947 if (hs->Iter > 1) {
00948 bmai->Message();
00949 bmai->Deactivate(kXRS_message);
00950 }
00951
00952
00953 if (!CheckRtag(bmai, Emsg))
00954 return ErrC(ei,bpar,bmai,0,kPWErrBadRndmTag,Emsg.c_str(),stepstr);
00955
00956
00957
00958 if ((bck = bmai->GetBucket(kXRS_status))) {
00959 int pst = 0;
00960 memcpy(&pst,bck->buffer,sizeof(pwdStatus_t));
00961 pst = ntohl(pst);
00962 memcpy(&SessionSt, &pst, sizeof(pwdStatus_t));
00963 bmai->Deactivate(kXRS_status);
00964 } else {
00965 SessionSt.ctype = kpCT_normal;
00966 }
00967
00968
00969 nextstep = kXPC_none;
00970 switch (hs->Step) {
00971
00972 case kXPS_init:
00973
00974
00975
00976 if (bpar->AddBucket(hs->CryptoMod,kXRS_cryptomod) != 0)
00977 return ErrC(ei,bpar,bmai,0,
00978 kPWErrCreateBucket,XrdSutBuckStr(kXRS_cryptomod),stepstr);
00979
00980
00981 if (bmai->MarshalBucket(kXRS_version,(kXR_int32)(Version)) != 0)
00982 return ErrC(ei,bpar,bmai,0, kPWErrCreateBucket,
00983 XrdSutBuckStr(kXRS_version),"(main list)",stepstr);
00984
00985
00986 if (hs->Tty || (AutoLogin > 0))
00987 SessionSt.options = kOptsClntTty;
00988
00989 case kXPS_puk:
00990
00991
00992
00993
00994
00995
00996 if (hs->Hcip) {
00997
00998
00999 if (!(bpub = hs->Hcip->Public(lpub)))
01000 return ErrC(ei,bpar,bmai,0,
01001 kPWErrNoPublic,"session",stepstr);
01002
01003
01004 if (bpar->UpdateBucket(bpub,lpub,kXRS_puk) != 0)
01005 return ErrC(ei,bpar,bmai,0, kPWErrAddBucket,
01006 XrdSutBuckStr(kXRS_puk),"global",stepstr);
01007 SafeDelArray(bpub);
01008
01009
01010
01011 if (VeriSrv == 1) {
01012 nextstep = kXPC_verifysrv;
01013 break;
01014 }
01015 }
01016
01017 case kXPS_signedrtag:
01018
01019
01020 if (hs->User.length()) {
01021 if (bmai->AddBucket(hs->User,kXRS_user) != 0)
01022 return ErrC(ei,bpar,bmai,0, kPWErrDuplicateBucket,
01023 XrdSutBuckStr(kXRS_user),stepstr);
01024 } else
01025 return ErrC(ei,bpar,bmai,0, kPWErrNoUser,stepstr);
01026
01027
01028
01029
01030 if (!(hs->Hcip)) {
01031 nextstep = kXPC_autoreg;
01032 break;
01033 }
01034
01035
01036
01037 status = kpCT_normal;
01038 if (hs->SysPwd == 1)
01039 status = kpCT_crypt;
01040 if (hs->SysPwd == 2)
01041 status = kpCT_afs;
01042 if (!(bck = QueryCreds(bmai, (AutoLogin > 0), status)))
01043 return ErrC(ei,bpar,bmai,0, kPWErrQueryCreds,
01044 hs->Tag.c_str(),stepstr);
01045 bmai->AddBucket(bck);
01046
01047
01048 if (hs->Pent->status == kPFE_onetime)
01049 SessionSt.options |= kOptsChngPwd;
01050
01051 nextstep = kXPC_normal;
01052 break;
01053
01054 case kXPS_credsreq:
01055
01056
01057
01058
01059 if (hs->Pent)
01060 hs->Pent->cnt = 1;
01061
01062
01063
01064 status = SessionSt.ctype;
01065 if (!(bck = QueryCreds(bmai, 0, status)))
01066 return ErrC(ei,bpar,bmai,0, kPWErrQueryCreds,
01067 hs->Tag.c_str(),stepstr);
01068 bmai->AddBucket(bck);
01069
01070 nextstep = kXPC_creds;
01071 break;
01072
01073 case kXPS_failure:
01074
01075
01076 hs->Pent->buf1.SetBuf();
01077 hs->Pent->buf2.SetBuf();
01078
01079 nextstep = kXPC_failureack;
01080 break;
01081
01082 case kXPS_newpuk:
01083
01084
01085
01086 case kXPS_rtag:
01087
01088
01089 nextstep = kXPC_signedrtag;
01090 break;
01091
01092 default:
01093 return ErrC(ei,bpar,bmai,0, kPWErrBadOpt,stepstr);
01094 }
01095
01096
01097 int *pst = (int *) new char[sizeof(pwdStatus_t)];
01098 memcpy(pst,&SessionSt,sizeof(pwdStatus_t));
01099 *pst = htonl(*pst);
01100 if (bmai->AddBucket((char *)pst,sizeof(pwdStatus_t), kXRS_status) != 0) {
01101 DEBUG("problems adding bucket kXRS_status");
01102 }
01103
01104
01105 if (AddSerialized('c', nextstep, hs->ID,
01106 bpar, bmai, kXRS_main, hs->Hcip) != 0)
01107 return ErrC(ei,bpar,bmai,0,
01108 kPWErrSerialBuffer,"main",stepstr);
01109
01110
01111 char *bser = 0;
01112 int nser = bpar->Serialized(&bser,'f');
01113
01114 if (QTRACE(Authen)) {
01115 bpar->Dump(ClientStepStr(bpar->GetStep()));
01116 bmai->Dump("Main OUT");
01117 }
01118
01119
01120 REL2(bpar,bmai);
01121
01122
01123 if (nser > 0) {
01124 DEBUG("returned " << nser <<" bytes of credentials");
01125 return new XrdSecCredentials(bser, nser);
01126 } else {
01127 DEBUG("problems with final serialization");
01128 return (XrdSecCredentials *)0;
01129 }
01130 }
01131
01132
01133
01134
01135
01136
01137
01138
01139 int XrdSecProtocolpwd::Authenticate(XrdSecCredentials *cred,
01140 XrdSecParameters **parms,
01141 XrdOucErrInfo *ei)
01142 {
01143
01144
01145
01146 EPNAME("Authenticate");
01147
01148
01149
01150 if (cred->size <= (int)XrdSecPROTOIDLEN || !cred->buffer) {
01151 strncpy(Entity.prot, "host", sizeof(Entity.prot));
01152 return 0;
01153 }
01154
01155
01156 if (!hs)
01157 return ErrS(String("none"),ei,0,0,0,kPWErrError,
01158 "handshake var container missing",
01159 "protocol initialization problems");
01160 hs->ErrMsg = "";
01161
01162
01163 hs->TimeStamp = time(0);
01164
01165
01166
01167 hs->ID = Entity.tident;
01168 DEBUG("handshaking ID: " << hs->ID);
01169
01170
01171 int i = 0;
01172 int kS_rc = kpST_more;
01173 int rc = 0;
01174 int entst = 0;
01175 int nextstep = 0;
01176 int ctype = kpCT_normal;
01177 char *bpub = 0, *bpid = 0;
01178 int lpub = 0;
01179 const char *stepstr = 0;
01180 String Message;
01181 String CryptList;
01182 String Host;
01183 String SrvPuKExp;
01184 String Salt;
01185 String RndmTag;
01186 String ClntMsg(256);
01187
01188 XrdSutBuffer *bpar = 0;
01189 XrdSutBuffer *bmai = 0;
01190 XrdSutBucket *bck = 0;
01191
01192 pwdStatus_t SessionSt = { 0, 0, 0};
01193
01194
01195
01196 XrdSysMutexHelper pwdGuard(&pwdContext);
01197
01198
01199 if (!(bpar = new XrdSutBuffer((const char *)cred->buffer,cred->size)))
01200 return ErrS(hs->ID,ei,0,0,0,kPWErrDecodeBuffer,"global",stepstr);
01201
01202
01203 if (strcmp(bpar->GetProtocol(),XrdSecPROTOIDENT))
01204 return ErrS(hs->ID,ei,bpar,bmai,0,kPWErrBadProtocol,stepstr);
01205
01206
01207 hs->Step = bpar->GetStep();
01208 stepstr = ClientStepStr(hs->Step);
01209
01210 if (QTRACE(Authen)) {
01211 bpar->Dump(stepstr);
01212 }
01213
01214
01215
01216 if (ParseCrypto(bpar) != 0)
01217 return ErrS(hs->ID,ei,bpar,0,0,kPWErrLoadCrypto,stepstr);
01218
01219
01220 if (ParseServerInput(bpar, &bmai, ClntMsg) == -1) {
01221 DEBUG(ClntMsg);
01222 return ErrS(hs->ID,ei,bpar,bmai,0,kPWErrParseBuffer,ClntMsg.c_str(),stepstr);
01223 }
01224
01225
01226 if ((bck = bmai->GetBucket(kXRS_status))) {
01227 int pst = 0;
01228 memcpy(&pst,bck->buffer,sizeof(pwdStatus_t));
01229 pst = ntohl(pst);
01230 memcpy(&SessionSt, &pst, sizeof(pwdStatus_t));
01231 bmai->Deactivate(kXRS_status);
01232 } else {
01233 DEBUG("no bucket kXRS_status found in main buffer");
01234 }
01235 hs->Tty = SessionSt.options & kOptsClntTty;
01236
01237
01238 unsigned int ulen = hs->User.length();
01239 ulen = (ulen > sizeof(CName)-1) ? sizeof(CName)-1 : ulen;
01240 if (ulen)
01241 strcpy(CName, hs->User.c_str());
01242
01243 Entity.name = strdup(CName);
01244
01245
01246
01247 DEBUG("version run by client: "<< hs->RemVers);
01248
01249
01250 if (QTRACE(Authen)) {
01251 bmai->Dump("main IN");
01252 }
01253
01254
01255 if (!CheckRtag(bmai, ClntMsg))
01256 return ErrS(hs->ID,ei,bpar,bmai,0,kPWErrBadRndmTag,stepstr,ClntMsg.c_str());
01257
01258
01259 if (!CheckTimeStamp(bmai, TimeSkew, ClntMsg))
01260 return ErrS(hs->ID,ei,bpar,bmai,0,kPWErrBadRndmTag,stepstr,ClntMsg.c_str());
01261
01262
01263 bool savecreds = (SessionSt.options & kOptsExpCred);
01264 switch (hs->Step) {
01265
01266 case kXPC_verifysrv:
01267
01268
01269
01270 nextstep = kXPS_signedrtag;
01271 break;
01272
01273 case kXPC_signedrtag:
01274
01275
01276
01277 kS_rc = kpST_ok;
01278 nextstep = kXPS_none;
01279 break;
01280
01281 case kXPC_failureack:
01282
01283
01284 kS_rc = kpST_error;
01285 nextstep = kXPS_none;
01286 break;
01287
01288 case kXPC_autoreg:
01289
01290
01291
01292
01293
01294 rc = QueryUser(entst, ClntMsg);
01295 if (rc < 0 || (entst == kPFE_disabled))
01296 return ErrS(hs->ID,ei,bpar,bmai,0, kPWErrBadCreds,
01297 DefError.c_str(),stepstr);
01298
01299
01300 for (i = 0; i < ncrypt; i++) {
01301 if (refcip[i]) {
01302
01303
01304 if (!(bpub = refcip[i]->Public(lpub)))
01305 return ErrS(hs->ID,ei,bpar,bmai,0, kPWErrNoPublic,
01306 "session",stepstr);
01307 bpid = new char[lpub+5];
01308 if (bpid) {
01309 char cid[5] = {0};
01310 sprintf(cid,"%d",cryptID[i]);
01311 memcpy(bpid,cid,5);
01312 memcpy(bpid+5, bpub, lpub);
01313
01314
01315 if (bmai->AddBucket(bpid,lpub+5,kXRS_puk) != 0)
01316 return ErrS(hs->ID,ei,bpar,bmai,0, kPWErrAddBucket,
01317 "main",stepstr);
01318 } else
01319 return ErrS(hs->ID,ei,bpar,bmai,0, kPWErrError,
01320 "out-of-memory",stepstr);
01321 SafeDelArray(bpub);
01322 }
01323 }
01324
01325 nextstep = kXPS_puk;
01326 break;
01327
01328 case kXPC_normal:
01329
01330
01331 if (QueryUser(entst,ClntMsg) != 0)
01332 return ErrS(hs->ID,ei,bpar,bmai,0, kPWErrBadCreds,
01333 ": user ",hs->User.c_str(),stepstr);
01334
01335 if (entst == kPFE_disabled)
01336 return ErrS(hs->ID,ei,bpar,bmai,0, kPWErrBadCreds,
01337 ": user ",hs->User.c_str(),stepstr);
01338
01339 if (entst == kPFE_expired || entst == kPFE_onetime) {
01340
01341 SessionSt.options |= kOptsExpCred;
01342 }
01343 if (entst == kPFE_crypt) {
01344
01345
01346
01347
01348 if (ClntMsg.beginswith("afs:")) {
01349 SessionSt.options |= kOptsAFSPwd;
01350 } else
01351 SessionSt.options |= kOptsCrypPwd;
01352
01353 ClntMsg = "";
01354 }
01355
01356 savecreds = (entst != kPFE_allowed) ? 0 : 1;
01357
01358 case kXPC_creds:
01359
01360
01361
01362 if (!(bck = bmai->GetBucket(kXRS_creds))) {
01363
01364
01365 kS_rc = kpST_more;
01366 nextstep = kXPS_credsreq;
01367 break;
01368 }
01369
01370
01371 if (savecreds) {
01372 if (SaveCreds(bck) != 0) {
01373 ClntMsg = "Warning: could not correctly update credentials database";
01374 }
01375 kS_rc = kpST_ok;
01376 nextstep = kXPS_none;
01377 bmai->Deactivate(kXRS_creds);
01378 break;
01379 }
01380
01381
01382 ctype = kpCT_normal;
01383 if (SessionSt.options & kOptsCrypPwd)
01384 ctype = kpCT_crypt;
01385 else if (SessionSt.options & kOptsAFSPwd) {
01386 ctype = kpCT_afs;
01387 String afsInfo;
01388 XrdSutBucket *bafs = bmai->GetBucket(kXRS_afsinfo);
01389 if (bafs)
01390 bafs->ToString(afsInfo);
01391 if (afsInfo == "c")
01392 ctype = kpCT_afsenc;
01393 }
01394
01395
01396 if (!CheckCreds(bck, ctype)) {
01397
01398
01399 (hs->Cref->cnt)++;
01400
01401 SessionSt.options &= ~kOptsExpCred;
01402
01403 ClntMsg = DefError;
01404 if (hs->Cref->cnt < MaxPrompts) {
01405
01406 nextstep = kXPS_credsreq;
01407 kS_rc = kpST_more;
01408
01409 if (hs->Pent->status == kPFE_crypt) {
01410 SessionSt.ctype = kpCT_crypt;
01411 if (ctype == kpCT_afs || ctype == kpCT_afsenc) {
01412 SessionSt.ctype = kpCT_afs;
01413 String afsinfo = hs->ErrMsg;
01414 bmai->UpdateBucket(afsinfo, kXRS_afsinfo);
01415 }
01416 ClntMsg = "";
01417 } else {
01418 SessionSt.ctype = kpCT_normal;
01419 ClntMsg = "insufficient credentials";
01420 }
01421 } else {
01422
01423 kS_rc = kpST_more;
01424 nextstep = kXPS_failure;
01425
01426 (hs->Pent->cnt)++;
01427
01428 hs->Pent->mtime = (kXR_int32)time(0);
01429
01430 XrdSysPrivGuard priv(getuid(), getgid());
01431 if (priv.Valid()) {
01432 if (cacheAdmin.Flush() != 0) {
01433 DEBUG("WARNING: some problem flushing to admin"
01434 " file after updating "<<hs->Pent->name);
01435 }
01436 }
01437 }
01438 } else {
01439
01440 hs->Cref->cnt = 0;
01441
01442 if (hs->Pent->cnt > 0) {
01443 hs->Pent->cnt = 0;
01444
01445 hs->Pent->mtime = (kXR_int32)time(0);
01446
01447 XrdSysPrivGuard priv(getuid(), getgid());
01448 if (priv.Valid()) {
01449 if (cacheAdmin.Flush() != 0) {
01450 DEBUG("WARNING: some problem flushing to admin"
01451 " file after updating "<<hs->Pent->name);
01452 }
01453 }
01454 }
01455 kS_rc = kpST_ok;
01456 nextstep = kXPS_none;
01457 if (SessionSt.options & kOptsExpCred ||
01458
01459 SessionSt.options & kOptsChngPwd) {
01460 kS_rc = kpST_more;
01461 nextstep = kXPS_credsreq;
01462 if (SessionSt.options & kOptsExpCred) {
01463 ClntMsg = "Credentials expired";
01464 } else if (SessionSt.options & kOptsChngPwd) {
01465 ClntMsg = "Password change requested";
01466 }
01467
01468 SessionSt.ctype = kpCT_new;
01469
01470 SessionSt.options |= kOptsExpCred;
01471 }
01472
01473 if (KeepCreds) {
01474 int sz = bck->size+5;
01475 char *buf = (char *) malloc(sz);
01476 if (buf) {
01477 memcpy(buf, "&pwd", 4);
01478 buf[4] = 0;
01479 memcpy(buf+5, bck->buffer, bck->size);
01480
01481 char *out = new char[2*sz+1];
01482 XrdSutToHex(buf, sz, out);
01483
01484 SafeDelete(clientCreds);
01485 clientCreds = new XrdSecCredentials(out, 2*sz+1);
01486 }
01487 }
01488
01489 if (FileExpCreds.length() > 0) {
01490 if (ExportCreds(bck) != 0)
01491 DEBUG("WARNING: some problem exporting creds to file;"
01492 " template is :"<<FileExpCreds);
01493 }
01494 }
01495
01496 bmai->Deactivate(kXRS_creds);
01497
01498 break;
01499
01500 default:
01501 return ErrS(hs->ID,ei,bpar,bmai,0, kPWErrBadOpt, stepstr);
01502 }
01503
01504
01505
01506 if (kS_rc == kpST_ok) {
01507 if (VeriClnt == 2 && !(hs->RtagOK)) {
01508
01509 nextstep = kXPS_rtag;
01510 kS_rc = kpST_more;
01511 }
01512 }
01513
01514
01515
01516 if (kS_rc == kpST_more && !(hs->Tty)) {
01517 DEBUG("client cannot reply to additional request: failure");
01518
01519 bpar->Deactivate(-1);
01520 bmai->Deactivate(-1);
01521 kS_rc = kpST_error;
01522 }
01523
01524 if (kS_rc == kpST_more) {
01525
01526
01527 if (ClntMsg.length() > 0)
01528 if (bmai->AddBucket(ClntMsg,kXRS_message) != 0) {
01529 DEBUG("problems adding bucket with message for client");
01530 }
01531
01532
01533 int *pst = (int *) new char[sizeof(pwdStatus_t)];
01534 memcpy(pst,&SessionSt,sizeof(pwdStatus_t));
01535 *pst = htonl(*pst);
01536 if (bmai->AddBucket((char *)pst,sizeof(pwdStatus_t), kXRS_status) != 0) {
01537 DEBUG("problems adding bucket kXRS_status");
01538 }
01539
01540
01541 if (AddSerialized('s', nextstep, hs->ID,
01542 bpar, bmai, kXRS_main, hs->Hcip) != 0)
01543 return ErrS(hs->ID,ei,bpar,bmai,0, kPWErrSerialBuffer,
01544 "main / session cipher",stepstr);
01545
01546
01547 char *bser = 0;
01548 int nser = bpar->Serialized(&bser,'f');
01549
01550
01551 if (QTRACE(Authen)) {
01552 bpar->Dump(ServerStepStr(bpar->GetStep()));
01553 bmai->Dump("Main OUT");
01554 }
01555
01556
01557 *parms = new XrdSecParameters(bser,nser);
01558 } else {
01559
01560
01561 SafeDelete(hs);
01562 }
01563
01564
01565 REL2(bpar,bmai);
01566
01567
01568 return kS_rc;
01569 }
01570
01571
01572
01573
01574
01575 extern "C"
01576 {
01577 char *XrdSecProtocolpwdInit(const char mode,
01578 const char *parms, XrdOucErrInfo *erp)
01579 {
01580
01581
01582
01583
01584
01585 pwdOptions opts;
01586 char *rc = (char *)"";
01587 char *cenv = 0;
01588
01589
01590
01591 if (mode == 'c') {
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610 opts.mode = mode;
01611
01612 cenv = getenv("XrdSecDEBUG");
01613 if (cenv)
01614 if (cenv[0] >= 49 && cenv[0] <= 51) opts.debug = atoi(cenv);
01615
01616
01617 cenv = getenv("XrdSecPWDVERIFYSRV");
01618 if (cenv)
01619 if (cenv[0] >= 48 && cenv[0] <= 49) opts.verisrv = atoi(cenv);
01620
01621 cenv = getenv("XrdSecPWDSRVPUK");
01622 if (cenv)
01623 opts.srvpuk = strdup(cenv);
01624
01625 cenv = getenv("XrdSecPWDAUTOLOG");
01626 if (cenv)
01627 if (cenv[0] >= 48 && cenv[0] <= 50) opts.alog = atoi(cenv);
01628
01629 cenv = getenv("XrdSecPWDALOGFILE");
01630 if (cenv)
01631 opts.alogfile = strdup(cenv);
01632
01633 cenv = getenv("XrdSecPWDMAXPROMPT");
01634 if (cenv) {
01635 opts.maxprompts = strtol(cenv, (char **)0, 10);
01636 if (errno == ERANGE) opts.maxprompts = -1;
01637 }
01638
01639
01640 rc = XrdSecProtocolpwd::Init(opts,erp);
01641
01642
01643 if (opts.srvpuk) free(opts.srvpuk);
01644 if (opts.alogfile) free(opts.alogfile);
01645
01646
01647 return rc;
01648 }
01649
01650
01651 cenv = getenv("XRDDEBUG");
01652 if (cenv && !strcmp(cenv,"1")) opts.debug = 1;
01653
01654
01655
01656 if (parms) {
01657
01658
01659 char parmbuff[1024];
01660 strlcpy(parmbuff, parms, sizeof(parmbuff));
01661
01662
01663 XrdOucTokenizer inParms(parmbuff);
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689 int debug = -1;
01690 int areg = -1;
01691 int vc = -1;
01692 int upw = -1;
01693 int syspwd = -1;
01694 int lifetime = -1;
01695 int maxfail = -1;
01696 String dir = "";
01697 String udir = "";
01698 String clist = "";
01699 String cpass = "";
01700 int keepcreds = -1;
01701 String expcreds = "";
01702 char *op = 0;
01703 while (inParms.GetLine()) {
01704 while ((op = inParms.GetToken())) {
01705 if (!strncmp(op, "-upwd:",6)) {
01706 upw = atoi(op+6);
01707 } else if (!strncmp(op, "-dir:",5)) {
01708 dir = (const char *)(op+5);
01709 } else if (!strncmp(op, "-udir:",6)) {
01710 udir = (const char *)(op+6);
01711 } else if (!strncmp(op, "-c:",3)) {
01712 clist = (const char *)(op+3);
01713 } else if (!strncmp(op, "-d:",3)) {
01714 debug = atoi(op+3);
01715 } else if (!strncmp(op, "-a:",3)) {
01716 areg = atoi(op+3);
01717 } else if (!strncmp(op, "-vc:",4)) {
01718 vc = atoi(op+4);
01719 } else if (!strncmp(op, "-syspwd",7)) {
01720 syspwd = 1;
01721 } else if (!strncmp(op, "-lf:",4)) {
01722 lifetime = XrdSutParseTime(op+4);
01723 } else if (!strncmp(op, "-maxfail:",9)) {
01724 maxfail = atoi(op+9);
01725 } else if (!strncmp(op, "-cryptfile:",11)) {
01726 cpass = (const char *)(op+11);
01727 } else if (!strncmp(op, "-keepcreds",10)) {
01728 keepcreds = 1;
01729 } else if (!strncmp(op, "-expcreds:",10)) {
01730 expcreds = (const char *)(op+10);
01731 }
01732 }
01733
01734 areg = (areg >= 0 && areg <= 2) ? areg : 0;
01735 vc = (vc >= 0 && vc <= 2) ? vc : 2;
01736 }
01737
01738
01739
01740 opts.debug = (debug > -1) ? debug : opts.debug;
01741 opts.mode = 's';
01742 opts.areg = areg;
01743 opts.vericlnt = vc;
01744 opts.upwd = upw;
01745 opts.syspwd = syspwd;
01746 opts.lifecreds = lifetime;
01747 opts.maxfailures = maxfail;
01748 if (dir.length() > 0)
01749 opts.dir = (char *)dir.c_str();
01750 if (udir.length() > 0)
01751 opts.udir = (char *)udir.c_str();
01752 if (clist.length() > 0)
01753 opts.clist = (char *)clist.c_str();
01754 if (cpass.length() > 0)
01755 opts.cpass = (char *)cpass.c_str();
01756 opts.keepcreds = keepcreds;
01757 if (expcreds.length() > 0)
01758 opts.expcreds = (char *)expcreds.c_str();
01759
01760
01761 return XrdSecProtocolpwd::Init(opts,erp);
01762 }
01763
01764
01765 return XrdSecProtocolpwd::Init(opts,erp);
01766 }}
01767
01768
01769
01770
01771
01772
01773 extern "C"
01774 {
01775 XrdSecProtocol *XrdSecProtocolpwdObject(const char mode,
01776 const char *hostname,
01777 const struct sockaddr &netaddr,
01778 const char *parms,
01779 XrdOucErrInfo *erp)
01780 {
01781 XrdSecProtocolpwd *prot;
01782 int options = XrdSecNOIPCHK;
01783
01784
01785
01786 if (!(prot = new XrdSecProtocolpwd(options, hostname, &netaddr, parms))) {
01787 char *msg = (char *)"Secpwd: Insufficient memory for protocol.";
01788 if (erp)
01789 erp->setErrInfo(ENOMEM, msg);
01790 else
01791 cerr <<msg <<endl;
01792 return (XrdSecProtocol *)0;
01793 }
01794
01795
01796 if (!erp)
01797 cerr << "protocol object instantiated" << endl;
01798 return prot;
01799 }}
01800
01801
01802
01803
01804
01805
01806
01807 int XrdSecProtocolpwd::ParseCrypto(XrdSutBuffer *buf)
01808 {
01809
01810
01811
01812
01813
01814
01815
01816 EPNAME("ParseCrypto");
01817
01818
01819 if (!buf) {
01820 DEBUG("invalid input ("<<buf<<")");
01821 return -1;
01822 }
01823
01824 String clist = "";
01825 XrdSutBucket *bck = 0;
01826
01827 if (!buf->GetNBuckets()) {
01828
01829
01830
01831 String opts = buf->GetOptions();
01832 if (!(opts.length())) {
01833 DEBUG("missing options - bad format");
01834 return -1;
01835 }
01836
01837
01838 int ii = opts.find("c:");
01839 if (ii >= 0) {
01840 clist.assign(opts, ii+2);
01841 clist.erase(clist.find(','));
01842 } else {
01843 DEBUG("crypto information not found in options");
01844 return -1;
01845 }
01846 } else {
01847
01848
01849 if (!(bck = buf->GetBucket(kXRS_cryptomod))) {
01850 DEBUG("cryptomod buffer missing");
01851 return -1;
01852 }
01853 bck->ToString(clist);
01854 }
01855 DEBUG("parsing list: "<<clist.c_str());
01856
01857
01858 hs->CryptoMod = "";
01859
01860 if (clist.length()) {
01861 int from = 0;
01862 while ((from = clist.tokenize(hs->CryptoMod, from, '|')) != -1) {
01863
01864 if (hs->CryptoMod.length()) {
01865
01866 if ((hs->CF = XrdCryptoFactory::GetCryptoFactory(hs->CryptoMod.c_str()))) {
01867 int fid = hs->CF->ID();
01868 int i = 0;
01869
01870 while (i < ncrypt) {
01871 if (cryptID[i] == fid) break;
01872 i++;
01873 }
01874 if (i >= ncrypt) {
01875 if (ncrypt == XrdCryptoMax) {
01876 DEBUG("max number of crypto slots reached - do nothing");
01877 return 0;
01878 } else {
01879
01880 cryptID[i] = fid;
01881 ncrypt++;
01882 }
01883 }
01884
01885 hs->Rcip = refcip[i];
01886
01887 return 0;
01888 }
01889 }
01890 }
01891 }
01892
01893 return 1;
01894 }
01895
01896
01897 bool XrdSecProtocolpwd::CheckCreds(XrdSutBucket *creds, int ctype)
01898 {
01899
01900 EPNAME("CheckCreds");
01901 bool match = 0;
01902
01903
01904 if (!hs->CF || !creds || !hs->Pent) {
01905 DEBUG("Invalid inputs ("<<hs->CF<<","<<creds<<","<<hs->Pent<<")");
01906 return match;
01907 }
01908
01909 if (ctype != kpCT_afs && ctype != kpCT_afsenc &&
01910 (!(hs->Pent->buf1.buf) || hs->Pent->buf1.len <= 0)) {
01911 DEBUG("Cached information about creds missing");
01912 return match;
01913 }
01914
01915
01916 int len = creds->size+4;
01917 char *cbuf = (KeepCreds) ? new char[len] : (char *)0;
01918
01919
01920
01921 if (ctype != kpCT_crypt && ctype != kpCT_afs && ctype != kpCT_afsenc) {
01922
01923
01924 XrdSutBucket *tmps = new XrdSutBucket();
01925 if (!tmps) {
01926 DEBUG("Could not allocate working buckets area for the salt");
01927 return match;
01928 }
01929 tmps->SetBuf(hs->Pent->buf1.buf, hs->Pent->buf1.len);
01930
01931
01932 if (KeepCreds) {
01933 memcpy(cbuf, "pwd:", 4);
01934 memcpy(cbuf+4, creds->buffer, creds->size);
01935 }
01936
01937
01938 DoubleHash(hs->CF,creds,tmps);
01939
01940 if (hs->Pent->buf2.len == creds->size)
01941 if (!memcmp(creds->buffer, hs->Pent->buf2.buf, creds->size))
01942 match = 1;
01943 SafeDelete(tmps);
01944
01945
01946 if (match && KeepCreds)
01947 creds->SetBuf(cbuf, len);
01948
01949 } else {
01950 #ifndef DONT_HAVE_CRYPT
01951 #ifndef R__AFS
01952
01953 String passwd(creds->buffer,creds->size+1);
01954 passwd.reset(0,creds->size,creds->size);
01955
01956 char *pass_crypt = crypt(passwd.c_str(), hs->Pent->buf1.buf);
01957
01958 if (!strncmp(pass_crypt, hs->Pent->buf1.buf, hs->Pent->buf1.len + 1) != 0)
01959 match = 1;
01960 if (match && KeepCreds) {
01961 memcpy(cbuf, "cpt:", 4);
01962 memcpy(cbuf+4, creds->buffer, creds->size);
01963 creds->SetBuf(cbuf, len);
01964 }
01965 #else
01966
01967 match = CheckCredsAFS(creds, ctype);
01968 #endif
01969 #else
01970 DEBUG("Crypt-like passwords (via crypt(...)) not supported");
01971 match = 0;
01972 #endif
01973 }
01974
01975
01976 if (cbuf)
01977 delete[] cbuf;
01978
01979
01980 return match;
01981 }
01982
01983 #ifdef R__AFS
01984
01985 bool XrdSecProtocolpwd::CheckCredsAFS(XrdSutBucket *creds, int ctype)
01986 {
01987
01988
01989 EPNAME("CheckCredsAFS");
01990 bool match = 0;
01991 int rc = 0;
01992
01993
01994 int life = 60;
01995
01996
01997 char *usr = (char *) hs->User.c_str();
01998
01999 bool notify = ((hs->Step == kXPC_creds) || QTRACE(ALL)) ? 1 : 0;
02000 struct ktc_encryptionKey key;
02001 if (ctype == kpCT_afs) {
02002 char *errmsg;
02003 char *pwd = new char[creds->size + 1];
02004 memcpy(pwd, creds->buffer, creds->size);
02005 pwd[creds->size] = 0;
02006 rc = ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION + KA_USERAUTH_DOSETPAG,
02007 usr, (char *)"", (char *)"", pwd,
02008 life, 0, 0, &errmsg);
02009 if (rc) {
02010 if (notify)
02011 PRINT("CheckAFS: failure: "<< errmsg);
02012 hs->ErrMsg += ka_LocalCell();
02013 } else {
02014 match = 1;
02015 if (KeepCreds)
02016
02017 ka_StringToKey(pwd, 0, &key);
02018 if (QTRACE(ALL))
02019 PRINT("CheckAFS: success!");
02020 }
02021 if (pwd) delete [] pwd;
02022
02023 } else if (ctype == kpCT_afsenc) {
02024
02025
02026 char *cell = 0;
02027 char cellname[MAXKTCREALMLEN];
02028 if (ka_ExpandCell(cell, cellname, 0) != 0) {
02029 PRINT("CheckAFS: failure expanding cell");
02030 return match;
02031 }
02032 cell = cellname;
02033
02034
02035 struct ubik_client *conn = 0;
02036 if (ka_AuthServerConn(cell, KA_AUTHENTICATION_SERVICE, 0, &conn) != 0) {
02037 PRINT("CheckAFS: failure getting an unauthenticated connection to the cell");
02038 return match;
02039 }
02040
02041
02042 memcpy(key.data, creds->buffer, creds->size);
02043 struct ktc_token token;
02044 int pwexpires;
02045 int now = hs->TimeStamp;
02046 rc = ka_Authenticate(usr, (char *)"", cell, conn,
02047 KA_TICKET_GRANTING_SERVICE,
02048 &key, now, now + life,
02049 &token, &pwexpires);
02050 if (rc) {
02051 if (notify)
02052 PRINT("CheckAFS: failure from ka_Authenticate");
02053 hs->ErrMsg += ka_LocalCell();
02054 } else {
02055 match = 1;
02056 if (QTRACE(ALL))
02057 PRINT("CheckAFS: success!");
02058 }
02059 } else {
02060 PRINT("CheckAFS: unknown credential type: "<< ctype);
02061 }
02062
02063
02064 if (match && KeepCreds) {
02065
02066 int len = strlen("afs:") + 8;
02067 char *buf = new char[len];
02068 memcpy(buf,"afs:",4);
02069 memcpy(buf+4,key.data,8);
02070
02071 creds->SetBuf(buf,len);
02072 }
02073
02074 return match;
02075 }
02076 #else
02077
02078 bool XrdSecProtocolpwd::CheckCredsAFS(XrdSutBucket *, int)
02079 {
02080
02081 return 0;
02082 }
02083 #endif
02084
02085
02086 int XrdSecProtocolpwd::SaveCreds(XrdSutBucket *creds)
02087 {
02088
02089
02090 EPNAME("SaveCreds");
02091
02092
02093 if ((hs->User.length() <= 0) || !hs->CF || !creds) {
02094 DEBUG("Bad inputs ("<<hs->User.length()<<","<<hs->CF<<","
02095 <<creds<<")");
02096 return -1;
02097 }
02098
02099 String wTag = hs->Tag + '_'; wTag += hs->CF->ID();
02100
02101
02102 XrdSutPFEntry *cent = cacheAdmin.Add(wTag.c_str());
02103 if (!cent) {
02104 DEBUG("Could not get entry in cache");
02105 return -1;
02106 }
02107
02108 char *tmps = XrdSutRndm::GetBuffer(8,3);
02109 if (!tmps) {
02110 DEBUG("Could not generate salt: out-of-memory");
02111 return -1;
02112 }
02113 XrdSutBucket *salt = new XrdSutBucket(tmps,8);
02114 if (!salt) {
02115 DEBUG("Could not create salt bucket");
02116 return -1;
02117 }
02118 cent->buf1.SetBuf(salt->buffer,salt->size);
02119
02120
02121 DoubleHash(hs->CF,creds,salt);
02122
02123 cent->buf2.SetBuf(creds->buffer,creds->size);
02124
02125
02126 cent->status = kPFE_ok;
02127
02128
02129 cent->mtime = hs->TimeStamp;
02130
02131 DEBUG("Entry for tag: "<<wTag<<" updated in cache");
02132
02133
02134 XrdSysPrivGuard priv(getuid(), getgid());
02135 if (priv.Valid()) {
02136 if (cacheAdmin.Flush() != 0) {
02137 DEBUG("WARNING: some problem flushing to admin file after updating "<<wTag);
02138 }
02139 }
02140
02141
02142 return 0;
02143 }
02144
02145
02146 int XrdSecProtocolpwd::ExportCreds(XrdSutBucket *creds)
02147 {
02148
02149
02150
02151 EPNAME("ExportCreds");
02152
02153
02154 if ((hs->User.length() <= 0) || !hs->CF || !creds) {
02155 DEBUG("Bad inputs ("<<hs->User.length()<<","<<hs->CF<<","
02156 <<creds<<")");
02157 return -1;
02158 }
02159
02160
02161 if (FileExpCreds.length() <= 0) {
02162 DEBUG("File (template) undefined - do nothing");
02163 return -1;
02164 }
02165
02166
02167 String filecreds = FileExpCreds;
02168
02169 if (XrdSutResolve(filecreds, Entity.host, Entity.vorg, Entity.grps, Entity.name) != 0) {
02170 DEBUG("Problems resolving templates in "<<filecreds);
02171 return -1;
02172 }
02173 DEBUG("Exporting client creds to: "<<filecreds);
02174
02175
02176 XrdSutPFile pfcreds(filecreds.c_str());
02177 if (!pfcreds.IsValid()) {
02178 DEBUG("Problem attaching / creating file "<<filecreds);
02179 return -1;
02180 }
02181
02182
02183 String wTag = hs->Tag + '_'; wTag += hs->CF->ID();
02184
02185
02186 XrdSutPFEntry ent;
02187 ent.SetName(wTag.c_str());
02188 ent.status = kPFE_ok;
02189 ent.cnt = 0;
02190 if (!strncmp(creds->buffer, "pwd:", 4)) {
02191
02192 ent.buf1.SetBuf(creds->buffer+4, creds->size-4);
02193 } else {
02194
02195
02196 ent.buf1.SetBuf(creds->buffer,creds->size);
02197 }
02198
02199
02200 ent.mtime = time(0);
02201 pfcreds.WriteEntry(ent);
02202 DEBUG("New entry for "<<wTag<<" successfully written to file: "
02203 <<filecreds);
02204
02205 return 0;
02206 }
02207
02208
02209 XrdSutBucket *XrdSecProtocolpwd::QueryCreds(XrdSutBuffer *bm,
02210 bool netrc, int &status)
02211 {
02212
02213 EPNAME("QueryCreds");
02214
02215
02216 if (!bm || !hs->CF || hs->Tag.length() <= 0) {
02217 DEBUG("bad inputs ("<<bm<<","<<hs->CF<<","<<hs->Tag.length()<<")");
02218 return (XrdSutBucket *)0;
02219 }
02220
02221
02222
02223 int ctype = (status > kpCT_undef) ? status : kpCT_normal;
02224 netrc = ((ctype == kpCT_normal || ctype == kpCT_onetime ||
02225 ctype == kpCT_old || ctype == kpCT_crypt)) ? netrc : 0;
02226
02227
02228 status = kpCI_undef;
02229
02230 XrdSutBucket *creds = new XrdSutBucket();
02231 if (!creds) {
02232 DEBUG("Could allocate bucket for creds");
02233 return (XrdSutBucket *)0;
02234 }
02235 creds->type = kXRS_creds;
02236
02237
02238
02239 String wTag = hs->Tag + '_'; wTag += hs->CF->ID();
02240
02241
02242
02243 char *cf = 0;
02244 char *cbuf = getenv("XrdSecCREDS");
02245 if (cbuf) {
02246 int len = strlen(cbuf);
02247
02248 int sz = len;
02249 char *out = new char[sz/2+2];
02250 XrdSutFromHex((const char *)cbuf, out, len);
02251 if ((cf = strstr(out, "&pwd"))) {
02252 cf += 5;
02253 len -= 5;
02254 if (len > 0) {
02255
02256 char pfx[5] = {0};
02257 memcpy(pfx, cf, 4);
02258 cf += 4;
02259 len -= 4;
02260 if (len > 0) {
02261 DEBUG("using "<<len<<" bytes of creds from the environment; pfx: "<<pfx);
02262
02263 hs->Pent = cacheAlog.Add(wTag.c_str());
02264 if (hs->Pent) {
02265
02266 if (hs->Pent->cnt == 0) {
02267
02268 creds->SetBuf(cf,len);
02269
02270 if (strncmp(pfx,"pwd",3))
02271 hs->Pent->status = kPFE_crypt;
02272 hs->Pent->mtime = hs->TimeStamp;
02273 hs->Pent->buf1.SetBuf(cf, len);
02274
02275 hs->Pent->buf2.SetBuf(cf, len);
02276
02277 if (!strncmp(pfx,"afs",3)) {
02278 String afsInfo = "c";
02279 if (bm->UpdateBucket(afsInfo, kXRS_afsinfo) != 0)
02280 PRINT("Warning: problems updating bucket with AFS info");
02281 }
02282
02283 status = kpCI_exact;
02284
02285 return creds;
02286 } else {
02287
02288 hs->Pent->buf1.SetBuf();
02289 hs->Pent->buf2.SetBuf();
02290 }
02291 } else {
02292 PRINT("Could create new entry in cache");
02293 return (XrdSutBucket *)0;
02294 }
02295 }
02296 }
02297 }
02298 }
02299
02300
02301
02302 String afsInfo;
02303 if (ctype == kpCT_afs || ctype == kpCT_afsenc) {
02304 XrdSutBucket *bafs = bm->GetBucket(kXRS_afsinfo);
02305 if (bafs)
02306 bafs->ToString(afsInfo);
02307 }
02308
02309
02310 if (netrc) {
02311
02312
02313 if (PFAlog.IsValid()) {
02314 if (cacheAlog.Refresh() != 0) {
02315 DEBUG("problems assuring cache update for file alog ");
02316 }
02317 }
02318
02319
02320 bool wild = 0;
02321 hs->Pent = cacheAlog.Get(wTag.c_str(),&wild);
02322
02323 if (hs->Pent && hs->Pent->buf1.buf) {
02324 if (hs->Pent->cnt == 0) {
02325 cf = hs->Pent->buf1.buf;
02326 bool afspwd = strncmp(cf,"afs",3) ? 0 : 1;
02327 if (!strncmp(cf,"cpt",3) || afspwd) {
02328 int len = hs->Pent->buf1.len;
02329 cf += 4;
02330 len -= 4;
02331 hs->Pent->status = kPFE_crypt;
02332 hs->Pent->mtime = hs->TimeStamp;
02333 hs->Pent->buf1.SetBuf(cf, len);
02334
02335 hs->Pent->buf2.SetBuf(cf, len);
02336
02337 if (afspwd) {
02338 afsInfo = "c";
02339 if (bm->UpdateBucket(afsInfo, kXRS_afsinfo) != 0)
02340 PRINT("Warning: problems updating bucket with AFS info");
02341 }
02342 }
02343
02344 creds->SetBuf(hs->Pent->buf1.buf,hs->Pent->buf1.len);
02345
02346 status = wild ? kpCI_wildcard : kpCI_exact;
02347
02348 return creds;
02349 } else {
02350
02351 hs->Pent->buf1.SetBuf();
02352 }
02353 }
02354
02355
02356 String passwd;
02357 String host(hs->Tag,hs->Tag.find("@",0)+1,hs->Tag.find(":",0)-1);
02358 if (QueryNetRc(host, passwd, status) == 0) {
02359
02360 if ((hs->Pent = cacheAlog.Add(wTag.c_str()))) {
02361
02362 hs->Pent->status = kPFE_crypt;
02363 hs->Pent->mtime = hs->TimeStamp;
02364 hs->Pent->buf1.SetBuf(passwd.c_str(),passwd.length());
02365
02366 creds->SetBuf(passwd.c_str(),passwd.length());
02367
02368 status = kpCI_exact;
02369
02370 return creds;
02371 } else {
02372 DEBUG("Could create new entry in cache");
02373 return (XrdSutBucket *)0;
02374 }
02375 }
02376 }
02377
02378
02379 if (!(hs->Pent) && !(hs->Pent = cacheAlog.Add(wTag.c_str()))) {
02380 DEBUG("Could create new entry in cache");
02381 return (XrdSutBucket *)0;
02382 }
02383
02384
02385
02386 if (hs->Pent && hs->Pent->buf1.buf && hs->Pent->cnt == 0) {
02387
02388 creds->SetBuf(hs->Pent->buf1.buf,hs->Pent->buf1.len);
02389
02390 status = kpCI_exact;
02391
02392 return creds;
02393 }
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412 if (ctype == kpCT_crypt || ctype == kpCT_afs) {
02413 if (hs->Pent && hs->Pent->buf2.buf) {
02414 if (ctype == kpCT_afs) {
02415 #ifdef R__AFS
02416 String passwd(hs->Pent->buf2.buf,hs->Pent->buf2.len);
02417
02418 struct ktc_encryptionKey key;
02419 ka_StringToKey((char *) passwd.c_str(),
02420 (char *) afsInfo.c_str(), &key);
02421
02422 creds->SetBuf(key.data,8);
02423
02424 afsInfo = "c";
02425 if (bm->UpdateBucket(afsInfo, kXRS_afsinfo) != 0)
02426 PRINT("Warning: problems updating bucket with AFS info");
02427 #else
02428
02429 creds->SetBuf(hs->Pent->buf2.buf,hs->Pent->buf2.len);
02430
02431 bm->Deactivate(kXRS_afsinfo);
02432 #endif
02433 } else {
02434
02435 creds->SetBuf(hs->Pent->buf2.buf,hs->Pent->buf2.len);
02436 }
02437
02438 hs->Pent->buf1.SetBuf(hs->Pent->buf2.buf,hs->Pent->buf2.len);
02439 hs->Pent->buf2.SetBuf();
02440
02441 status = kpCI_exact;
02442
02443 return creds;
02444 }
02445 }
02446
02447
02448
02449
02450 if (!(hs->Tty)) {
02451 DEBUG("Not connected to tty: cannot prompt user for credentials");
02452 return (XrdSutBucket *)0;
02453 }
02454
02455
02456
02457 char prompt[XrdSutMAXPPT] = {0};
02458 if (ctype == kpCT_onetime)
02459 snprintf(prompt,XrdSutMAXPPT, "Password for %s not active: "
02460 "starting activation handshake.",hs->Tag.c_str());
02461
02462
02463 if (ctype == kpCT_new) {
02464 snprintf(prompt,XrdSutMAXPPT, "Enter new password: ");
02465 } else if (ctype == kpCT_crypt) {
02466 String host(hs->Tag,hs->Tag.find("@",0)+1,hs->Tag.find(":",0)-1);
02467 snprintf(prompt,XrdSutMAXPPT, "Password for %s@%s: ",
02468 hs->User.c_str(), host.c_str());
02469 } else if (ctype == kpCT_afs || ctype == kpCT_afsenc) {
02470 snprintf(prompt,XrdSutMAXPPT, "AFS password for %s@%s: ",
02471 hs->User.c_str(), hs->AFScell.c_str());
02472 } else {
02473
02474 snprintf(prompt,XrdSutMAXPPT,"Password for %s:",hs->Tag.c_str());
02475 }
02476
02477
02478 int natt = MaxPrompts;
02479 String passwd = "";
02480 bool changepwd =0;
02481 while (natt-- && passwd.length() <= 0) {
02482 XrdSutGetPass(prompt, passwd);
02483
02484
02485 if (passwd.beginswith("$changepwd$")) {
02486 PRINT("Requesting a password change");
02487 changepwd = 1;
02488 passwd.erase("$changepwd$",0,strlen("$changepwd$"));
02489 }
02490 if (passwd.length()) {
02491
02492 creds->SetBuf(passwd.c_str(),passwd.length());
02493 if (ctype != kpCT_crypt && ctype != kpCT_afs) {
02494
02495 DoubleHash(hs->CF,creds,creds);
02496
02497 status = kpCI_prompt;
02498 } else if (ctype == kpCT_afs) {
02499 #ifdef R__AFS
02500
02501 struct ktc_encryptionKey key;
02502 ka_StringToKey((char *) passwd.c_str(),
02503 (char *) afsInfo.c_str(), &key);
02504 creds->SetBuf(key.data,8);
02505
02506 afsInfo = "c";
02507 if (bm->UpdateBucket(afsInfo, kXRS_afsinfo) != 0)
02508 PRINT("Warning: problems updating bucket with AFS info");
02509 #endif
02510 }
02511
02512
02513 if (changepwd)
02514 hs->Pent->status = kPFE_onetime;
02515 else
02516 hs->Pent->status = kPFE_ok;
02517 hs->Pent->buf1.SetBuf(creds->buffer,creds->size);
02518
02519
02520 hs->Pent->buf2.SetBuf(passwd.c_str(),passwd.length());
02521
02522 if (AutoLogin > 0)
02523 UpdateAlog();
02524 }
02525 }
02526
02527 if (passwd.length() <= 0) {
02528 delete creds;
02529 creds = 0;
02530 }
02531
02532 return creds;
02533 }
02534
02535
02536 int XrdSecProtocolpwd::UpdateAlog()
02537 {
02538
02539
02540 EPNAME("UpdateAlog");
02541
02542
02543 if (hs->Tag.length() <= 0) {
02544 DEBUG("Tag undefined - do nothing");
02545 return -1;
02546 }
02547
02548 if (!(hs->Pent) || !(hs->Pent->buf1.buf)) {
02549 DEBUG("Nothing to do");
02550 return 0;
02551 }
02552
02553
02554 String wTag = hs->Tag + '_'; wTag += hs->CF->ID();
02555
02556
02557 hs->Pent->buf2.SetBuf();
02558 hs->Pent->buf3.SetBuf();
02559 hs->Pent->buf4.SetBuf();
02560
02561
02562 hs->Pent->status = kPFE_ok;
02563
02564
02565 hs->Pent->cnt = 0;
02566
02567
02568 hs->Pent->mtime = hs->TimeStamp;
02569
02570 DEBUG("Entry for tag: "<<wTag<<" updated in cache");
02571
02572
02573 if (cacheAlog.Flush() != 0) {
02574 DEBUG("WARNING: some problem flushing to alog file after updating "<<wTag);
02575 }
02576
02577
02578 return 0;
02579 }
02580
02581
02582 int XrdSecProtocolpwd::QueryUser(int &status, String &cmsg)
02583 {
02584
02585 EPNAME("QueryUser");
02586
02587 DEBUG("Enter: " << hs->User);
02588
02589
02590 if (hs->User.length() <= 0 || !hs->CF || !hs->Cref) {
02591 DEBUG("Invalid inputs ("<<hs->User.length()<<","<<hs->CF<<","<<hs->Cref<<")");
02592 return -1;
02593 }
02594
02595
02596 String wTag = hs->Tag + '_'; wTag += hs->CF->ID();
02597
02598
02599 status = kPFE_disabled;
02600 int bad = -1;
02601 cmsg = "";
02602
02603
02604 if (UserPwd) {
02605
02606 struct passwd *pw = getpwnam(hs->User.c_str());
02607 int rcst = 0;
02608 kXR_int32 mtime = -1;
02609 bool fcrypt = 0;
02610 String File;
02611 if (pw) {
02612 File.resize(strlen(pw->pw_dir)+FileUser.length()+10);
02613 File.assign(pw->pw_dir, 0);
02614 File += FileUser;
02615
02616 struct stat st;
02617 if ((rcst = stat(File.c_str(),&st)) != 0 && errno == ENOENT) {
02618 if (UserPwd > 1) {
02619
02620 File.replace(FileUser,FileCrypt);
02621 fcrypt = 1;
02622 rcst = 0;
02623 }
02624 }
02625 mtime = (rcst == 0) ? st.st_mtime : mtime;
02626 }
02627
02628 if (rcst == 0) {
02629
02630
02631 hs->Pent = cacheUser.Get(wTag.c_str());
02632 if (!hs->Pent || (hs->Pent->mtime < mtime)) {
02633 hs->Pent = (hs->Pent) ? hs->Pent : cacheUser.Add(wTag.c_str());
02634 if (hs->Pent) {
02635
02636
02637 if (!fcrypt) {
02638
02639 XrdSutPFile ff(File.c_str(), kPFEopen,0,0);
02640 if (ff.IsValid()) {
02641
02642 if (ff.ReadEntry(wTag.c_str(),*(hs->Pent)) > 0) {
02643 bad = 0;
02644 status = hs->Pent->status;
02645 ff.Close();
02646 return 0;
02647 }
02648 ff.Close();
02649 }
02650 } else if (UserPwd > 1) {
02651 String pwhash;
02652 if (QueryCrypt(FileCrypt, pwhash) > 0) {
02653 bad = 0;
02654 status = kPFE_crypt;
02655
02656 hs->Pent->mtime = hs->TimeStamp;
02657 hs->Pent->status = status;
02658 hs->Pent->cnt = 0;
02659 if (!FileCrypt.beginswith("afs:"))
02660 hs->Pent->buf1.SetBuf(pwhash.c_str(),pwhash.length()+1);
02661
02662 cmsg = FileCrypt;
02663 return 0;
02664 }
02665 }
02666 }
02667 } else {
02668
02669 bad = 0;
02670 status = hs->Pent->status;
02671 hs->Pent->mtime = hs->TimeStamp;
02672 if (status == kPFE_crypt)
02673 cmsg = FileCrypt;
02674 return 0;
02675 }
02676 }
02677 }
02678
02679
02680
02681 if (SysPwd) {
02682 String pwhash, fn;
02683 if (QueryCrypt(fn, pwhash) > 0) {
02684 bad = 0;
02685 status = kPFE_crypt;
02686
02687 hs->Pent = cacheUser.Add(wTag.c_str());
02688 hs->Pent->mtime = hs->TimeStamp;
02689 hs->Pent->status = status;
02690 hs->Pent->cnt = 0;
02691 if (!fn.beginswith("afs:"))
02692 hs->Pent->buf1.SetBuf(pwhash.c_str(),pwhash.length()+1);
02693
02694 cmsg = fn;
02695 return 0;
02696 }
02697 }
02698
02699
02700 if (PFAdmin.IsValid()) {
02701
02702
02703 XrdSysPrivGuard priv(getuid(), getgid());
02704 if (priv.Valid()) {
02705 if (cacheAdmin.Refresh() != 0) {
02706 DEBUG("problems assuring cache update for file admin ");
02707 return -1;
02708 }
02709 }
02710 hs->Pent = cacheAdmin.Get(wTag.c_str());
02711
02712 if (hs->Pent) {
02713 bad = 0;
02714 status = hs->Pent->status;
02715 if (status == kPFE_allowed) {
02716 if (AutoReg == kpAR_none) {
02717
02718 status = kPFE_disabled;
02719 bad = 1;
02720 }
02721 } else if (status >= kPFE_ok) {
02722
02723 if (MaxFailures > 0 && hs->Pent->cnt >= MaxFailures) {
02724 status = kPFE_disabled;
02725 bad = 2;
02726 }
02727
02728 if (LifeCreds > 0) {
02729 int expt = hs->Pent->mtime + LifeCreds;
02730 int now = hs->TimeStamp;
02731 if (expt < now)
02732 status = kPFE_expired;
02733 }
02734 if (status != kPFE_disabled)
02735 return 0;
02736 }
02737 }
02738 }
02739
02740
02741
02742
02743 if (bad == -1) {
02744 if (AutoReg != kpAR_none) {
02745 status = kPFE_allowed;
02746 if (AutoReg == kpAR_users) {
02747 struct passwd *pw = getpwnam(hs->User.c_str());
02748 if (!pw) {
02749 status = kPFE_disabled;
02750 bad = 1;
02751 }
02752 }
02753 } else
02754 bad = 1;
02755 }
02756
02757
02758 if (status == kPFE_disabled) {
02759 char msg[XrdSutMAXPPT];
02760 switch (bad) {
02761 case 1:
02762 snprintf(msg,XrdSutMAXPPT,"user '%s' unknown: auto-registration"
02763 " not allowed: contact %s to register",
02764 hs->User.c_str(),SrvEmail.c_str());
02765 break;
02766 case 2:
02767 snprintf(msg,XrdSutMAXPPT,"max number of failures (%d) reached"
02768 " for user '%s': contact %s to re-activate",
02769 MaxFailures,hs->User.c_str(),SrvEmail.c_str());
02770 break;
02771 default:
02772 msg[0] = '\0';
02773 }
02774 cmsg.insert(msg,0,strlen(msg));
02775 }
02776
02777
02778 return 0;
02779 }
02780
02781
02782 int XrdSecProtocolpwd::GetUserHost(String &user, String &host)
02783 {
02784
02785 EPNAME("GetUserHost");
02786
02787
02788 host = Entity.host;
02789 if (host.length() <= 0) host = getenv("XrdSecHOST");
02790
02791
02792 user = Entity.name;
02793 if (user.length() <= 0) user = getenv("XrdSecUSER");
02794
02795
02796 if (user.length() <= 0) {
02797
02798
02799 if (!(hs->Tty)) {
02800 DEBUG("user not defined:"
02801 "not tty: cannot prompt for user");
02802 return -1;
02803 }
02804
02805
02806 String prompt = "Enter user or tag";
02807 if (host.length()) {
02808 prompt.append(" for host ");
02809 prompt.append(host);
02810 }
02811 prompt.append(":");
02812 XrdSutGetLine(user,prompt.c_str());
02813 }
02814
02815 DEBUG(" user: "<<user<<", host: "<<host);
02816
02817
02818 return 0;
02819 }
02820
02821
02822 int XrdSecProtocolpwd::AddSerialized(char opt, kXR_int32 step, String ID,
02823 XrdSutBuffer *bls, XrdSutBuffer *buf,
02824 kXR_int32 type,
02825 XrdCryptoCipher *cip)
02826 {
02827
02828
02829
02830 EPNAME("AddSerialized");
02831
02832 if (!bls || !buf || (opt != 0 && opt != 'c' && opt != 's')) {
02833 DEBUG("invalid inputs ("
02834 <<bls<<","<<buf<<","<<opt<<")"
02835 <<" - type: "<<XrdSutBuckStr(type));
02836 return -1;
02837 }
02838
02839
02840
02841 if (step > 0) {
02842 bls->SetStep(step);
02843 buf->SetStep(step);
02844 hs->LastStep = step;
02845 }
02846
02847
02848
02849
02850 XrdSutBucket *brt = buf->GetBucket(kXRS_rtag);
02851 if (brt && cip) {
02852
02853
02854 if (cip->Encrypt(*brt) == 0) {
02855 DEBUG("error encrypting random tag");
02856 return -1;
02857 }
02858
02859
02860 brt->type = kXRS_signed_rtag;
02861 }
02862
02863
02864 if (opt == 'c') {
02865
02866
02867 if (buf->MarshalBucket(kXRS_timestamp,(kXR_int32)(hs->TimeStamp)) != 0) {
02868 DEBUG("error adding bucket with time stamp");
02869 return -1;
02870 }
02871 }
02872
02873
02874
02875 if (opt == 's' || step != kXPC_autoreg) {
02876
02877
02878 String RndmTag;
02879 XrdSutRndm::GetRndmTag(RndmTag);
02880
02881
02882 if (!(brt = new XrdSutBucket(RndmTag,kXRS_rtag))) {
02883 DEBUG("error creating random tag bucket");
02884 return -1;
02885 }
02886 buf->AddBucket(brt);
02887
02888
02889 if (!hs->Cref) {
02890 DEBUG("cache entry not found: protocol error");
02891 return -1;
02892 }
02893
02894
02895 hs->Cref->buf1.SetBuf(brt->buffer,brt->size);
02896 hs->Cref->mtime = (kXR_int32)hs->TimeStamp;
02897 }
02898
02899
02900 char *bser = 0;
02901 int nser = buf->Serialized(&bser);
02902
02903
02904 XrdSutBucket *bck = 0;;
02905 if (!(bck = bls->GetBucket(type))) {
02906
02907 if (!(bck = new XrdSutBucket(bser,nser,type))) {
02908 DEBUG("error creating bucket "
02909 <<" - type: "<<XrdSutBuckStr(type));
02910 return -1;
02911 }
02912
02913
02914 bls->AddBucket(bck);
02915 } else {
02916 bck->Update(bser,nser);
02917 }
02918
02919
02920 if (cip) {
02921 if (cip->Encrypt(*bck) == 0) {
02922 DEBUG("error encrypting bucket - cipher "
02923 <<" - type: "<<XrdSutBuckStr(type));
02924 return -1;
02925 }
02926 }
02927
02928 return 0;
02929 }
02930
02931
02932 int XrdSecProtocolpwd::ParseClientInput(XrdSutBuffer *br, XrdSutBuffer **bm,
02933 String &emsg)
02934 {
02935
02936
02937
02938
02939 EPNAME("ParseClientInput");
02940
02941
02942 if (!br || !bm) {
02943 DEBUG("invalid inputs ("<<br<<","<<bm<<")");
02944 emsg = "invalid inputs";
02945 return -1;
02946 }
02947
02948
02949 XrdSutBucket *bckm = 0;
02950
02951
02952 if (!br->GetNBuckets()) {
02953
02954 if (!((*bm) = new XrdSutBuffer(br->GetProtocol(),br->GetOptions()))) {
02955 emsg = "error instantiating main buffer";
02956 return -1;
02957 }
02958
02959
02960 String opts = br->GetOptions();
02961 int ii = opts.find("v:");
02962 if (ii >= 0) {
02963 String sver(opts,ii+2);
02964 sver.erase(sver.find(','));
02965 hs->RemVers = atoi(sver.c_str());
02966 } else {
02967 hs->RemVers = Version;
02968 emsg = "server version information not found in options:"
02969 " assume same as local";
02970 }
02971
02972
02973 if (!(hs->Cref = new XrdSutPFEntry("c"))) {
02974 emsg = "error creating cache";
02975 return -1;
02976 }
02977
02978
02979 hs->Cref->status = hs->RemVers;
02980
02981
02982 String srvid;
02983 ii = opts.find("id:");
02984 if (ii >= 0) {
02985 srvid.assign(opts, ii+3);
02986 srvid.erase(srvid.find(','));
02987 }
02988
02989
02990 String popt;
02991 ii = opts.find("po:");
02992 if (ii >= 0) {
02993 popt.assign(opts, ii+3);
02994 popt.erase(popt.find(','));
02995
02996 if (popt.beginswith("sys")) {
02997 hs->SysPwd = 1;
02998 } else if (popt.beginswith("afs")) {
02999 hs->SysPwd = 2;
03000 hs->AFScell.assign(popt,3);
03001 }
03002 }
03003
03004
03005 String host;
03006 if (GetUserHost(hs->User,host) != 0) {
03007 emsg = "error getting user and host";
03008 return -1;
03009 }
03010
03011
03012 hs->Tag.resize(hs->User.length()+host.length()+srvid.length()+5);
03013 hs->Tag = hs->User;
03014 if (host.length() > 0)
03015 hs->Tag += ("@" + host);
03016 if (srvid.length() > 0)
03017 hs->Tag += (":" + srvid);
03018
03019
03020 if (!PFSrvPuk.IsValid()) {
03021 emsg = "file with server public keys invalid";
03022 return -1;
03023 }
03024 char *ptag = new char[host.length()+srvid.length()+10];
03025 if (ptag) {
03026 sprintf(ptag,"%s:%s_%d",host.c_str(),srvid.c_str(),hs->CF->ID());
03027 bool wild = 0;
03028 XrdSutPFEntry *ent = cacheSrvPuk.Get((const char *)ptag, &wild);
03029 if (ent) {
03030
03031 SafeDelete(hs->Hcip);
03032 if (!(hs->Hcip =
03033 hs->CF->Cipher(0,ent->buf1.buf,ent->buf1.len))) {
03034 DEBUG("could not instantiate session cipher "
03035 "using cipher public info from server");
03036 emsg = "could not instantiate session cipher ";
03037 } else {
03038 DEBUG("hsHcip: 0x"<<hs->Hcip->AsHexString());
03039 }
03040 } else {
03041
03042 emsg = "server puk not found in cache - tag: ";
03043 emsg += ptag;
03044 }
03045 SafeDelArray(ptag);
03046 } else
03047 emsg = "could not allocate buffer for server puk tag";
03048
03049
03050 return 0;
03051 }
03052
03053
03054 if (!hs->Cref) {
03055 emsg = "cache entry not found";
03056 return -1;
03057 }
03058
03059
03060 int reftime = hs->TimeStamp - TimeSkew;
03061 if (hs->Cref->mtime < reftime) {
03062 emsg = "cache entry expired";
03063
03064 SafeDelete(hs->Cref);
03065 return -1;
03066 }
03067
03068
03069 hs->RemVers = hs->Cref->status;
03070
03071
03072 if (!(bckm = br->GetBucket(kXRS_main))) {
03073 emsg = "main buffer missing";
03074 return -1;
03075 }
03076
03077
03078 if (hs->LastStep != kXPC_autoreg) {
03079
03080
03081 if (!hs->Hcip) {
03082 emsg = "session cipher not found";
03083 return -1;
03084 }
03085
03086
03087 if (!(hs->Hcip->Decrypt(*bckm))) {
03088 emsg = "error decrypting main buffer with session cipher";
03089 return -1;
03090 }
03091 }
03092
03093
03094 if (!((*bm) = new XrdSutBuffer(bckm->buffer,bckm->size))) {
03095 emsg = "error deserializing main buffer";
03096 return -1;
03097 }
03098
03099
03100 bool newpuk = 0;
03101 XrdSutBuckList *bcklst = (*bm)->GetBuckList();
03102 XrdSutBucket *bp = bcklst->Begin();
03103 while (bp) {
03104 if (bp->type == kXRS_puk) {
03105 newpuk = 1;
03106
03107 char cid[5] = {0};
03108 memcpy(cid, bp->buffer, 5);
03109 int id = atoi(cid);
03110
03111 String ptag(hs->Tag);
03112 ptag.erase(0,ptag.find('@')+1);
03113 ptag += '_';
03114 ptag += cid;
03115
03116 XrdSutPFEntry *ent = cacheSrvPuk.Add(ptag.c_str());
03117 if (ent) {
03118
03119 ent->buf1.SetBuf((bp->buffer)+5,(bp->size)-5);
03120 ent->mtime = hs->TimeStamp;
03121 if (id == hs->CF->ID()) {
03122
03123 SafeDelete(hs->Hcip);
03124 if (!(hs->Hcip =
03125 hs->CF->Cipher(0,ent->buf1.buf,ent->buf1.len))) {
03126 DEBUG("could not instantiate session cipher "
03127 "using cipher public info from server");
03128 emsg = "could not instantiate session cipher ";
03129 } else {
03130 DEBUG("hsHcip: 0x"<<hs->Hcip->AsHexString());
03131 }
03132 }
03133 } else {
03134
03135 DEBUG("could not create entry in cache - tag: "<<ptag);
03136 }
03137 }
03138
03139 bp = bcklst->Next();
03140 }
03141 (*bm)->Deactivate(kXRS_puk);
03142
03143 if (newpuk)
03144 cacheSrvPuk.Flush();
03145
03146
03147 return 0;
03148 }
03149
03150
03151 int XrdSecProtocolpwd::ParseServerInput(XrdSutBuffer *br, XrdSutBuffer **bm,
03152 String &cmsg)
03153 {
03154
03155
03156
03157
03158 EPNAME("ParseServerInput");
03159
03160
03161 if (!br || !bm) {
03162 DEBUG("invalid inputs ("<<br<<","<<bm<<")");
03163 cmsg = "invalid inputs";
03164 return -1;
03165 }
03166
03167
03168 XrdSutBucket *bck = 0;
03169 XrdSutBucket *bckm = 0;
03170
03171
03172 if (!(bckm = br->GetBucket(kXRS_main))) {
03173 cmsg = "main buffer missing";
03174 return -1;
03175 }
03176
03177
03178 if ((bck = br->GetBucket(kXRS_puk))) {
03179
03180
03181 SafeDelete(hs->Hcip);
03182
03183
03184 if (!hs->Rcip) {
03185 cmsg = "reference cipher missing";
03186 return -1;
03187 }
03188
03189 if (!(hs->Hcip = hs->CF->Cipher(*hs->Rcip))) {
03190 cmsg = "cannot get reference cipher";
03191 return -1;
03192 }
03193
03194
03195 if (!(hs->Hcip->Finalize(bck->buffer,bck->size,0))) {
03196 cmsg = "cannot finalize session cipher";
03197 return -1;
03198 }
03199
03200
03201 br->Deactivate(kXRS_puk);
03202 }
03203
03204
03205
03206 if (hs->Hcip) {
03207 if (!(hs->Hcip->Decrypt(*bckm))) {
03208 cmsg = "error decrypting main buffer with session cipher";
03209 return -1;
03210 }
03211 }
03212
03213
03214 if (!((*bm) = new XrdSutBuffer(bckm->buffer,bckm->size))) {
03215 cmsg = "error deserializing main buffer";
03216 return -1;
03217 }
03218
03219
03220 if (hs->RemVers == -1) {
03221 if ((*bm)->UnmarshalBucket(kXRS_version,hs->RemVers) != 0) {
03222 hs->RemVers = Version;
03223 cmsg = "client version information not found in options:"
03224 " assume same as local";
03225 } else {
03226 (*bm)->Deactivate(kXRS_version);
03227 }
03228 }
03229
03230
03231
03232 if (!hs->Cref) {
03233
03234 if (!(hs->Cref = new XrdSutPFEntry(hs->ID.c_str()))) {
03235 cmsg = "cannot create cache entry";
03236 return -1;
03237 }
03238 } else {
03239
03240
03241 int reftime = hs->TimeStamp - TimeSkew;
03242 if (hs->Cref->mtime < reftime) {
03243 cmsg = "cache entry expired";
03244 SafeDelete(hs->Cref);
03245 return -1;
03246 }
03247 }
03248
03249
03250
03251 if ((bck = (*bm)->GetBucket(kXRS_user))) {
03252 if (hs->User.length() <= 0) {
03253 bck->ToString(hs->User);
03254
03255 hs->Tag = hs->User;
03256 }
03257 (*bm)->Deactivate(kXRS_user);
03258 }
03259
03260
03261 return 0;
03262 }
03263
03264
03265 void XrdSecProtocolpwd::ErrF(XrdOucErrInfo *einfo, kXR_int32 ecode,
03266 const char *msg1, const char *msg2,
03267 const char *msg3)
03268 {
03269
03270 EPNAME("ErrF");
03271
03272 char *msgv[12];
03273 int k, i = 0, sz = strlen("Secpwd");
03274
03275
03276
03277 int cm = (ecode >= kPWErrParseBuffer &&
03278 ecode <= kPWErrError) ? (ecode-kPWErrParseBuffer) : -1;
03279 const char *cmsg = (cm > -1) ? gPWErrStr[cm] : 0;
03280
03281
03282
03283 msgv[i++] = (char *)"Secpwd";
03284 if (cmsg) {msgv[i++] = (char *)": ";
03285 msgv[i++] = (char *)cmsg;
03286 sz += strlen(msgv[i-1]) + 2;
03287 }
03288 if (msg1) {msgv[i++] = (char *)": ";
03289 msgv[i++] = (char *)msg1;
03290 sz += strlen(msgv[i-1]) + 2;
03291 }
03292 if (msg2) {msgv[i++] = (char *)": ";
03293 msgv[i++] = (char *)msg2;
03294 sz += strlen(msgv[i-1]) + 2;
03295 }
03296 if (msg3) {msgv[i++] = (char *)": ";
03297 msgv[i++] = (char *)msg3;
03298 sz += strlen(msgv[i-1]) + 2;
03299 }
03300
03301
03302 if (einfo) {
03303 einfo->setErrInfo(ecode, (const char **)msgv, i);
03304 }
03305 if (QTRACE(Debug)) {
03306 char *bout = new char[sz+10];
03307 if (bout) {
03308 bout[0] = 0;
03309 for (k = 0; k < i; k++)
03310 sprintf(bout,"%s%s",bout,msgv[k]);
03311 DEBUG(bout);
03312 } else {
03313 for (k = 0; k < i; k++)
03314 DEBUG(msgv[k]);
03315 }
03316 }
03317 }
03318
03319
03320 XrdSecCredentials *XrdSecProtocolpwd::ErrC(XrdOucErrInfo *einfo,
03321 XrdSutBuffer *b1,
03322 XrdSutBuffer *b2,
03323 XrdSutBuffer *b3,
03324 kXR_int32 ecode,
03325 const char *msg1,
03326 const char *msg2,
03327 const char *msg3)
03328 {
03329
03330
03331
03332 ErrF(einfo, ecode, msg1, msg2, msg3);
03333
03334
03335 REL3(b1,b2,b3);
03336
03337
03338 return (XrdSecCredentials *)0;
03339 }
03340
03341
03342 int XrdSecProtocolpwd::ErrS(String ID, XrdOucErrInfo *einfo,
03343 XrdSutBuffer *b1, XrdSutBuffer *b2,
03344 XrdSutBuffer *b3, kXR_int32 ecode,
03345 const char *msg1, const char *msg2,
03346 const char *msg3)
03347 {
03348
03349
03350
03351 ErrF(einfo, ecode, msg1, msg2, msg3);
03352
03353
03354 REL3(b1,b2,b3);
03355
03356
03357 return kpST_error;
03358 }
03359
03360
03361 int XrdSecProtocolpwd::DoubleHash(XrdCryptoFactory *cf, XrdSutBucket *bck,
03362 XrdSutBucket *s1, XrdSutBucket *s2,
03363 const char *tag)
03364 {
03365
03366
03367
03368
03369 EPNAME("DoubleHash");
03370
03371
03372
03373 if (!cf || !bck) {
03374 DEBUG("Bad inputs "<<cf<<","<<bck<<")");
03375 return -1;
03376 }
03377
03378
03379 if ((!s1 || s1->size <= 0) && (!s2 || s2->size <= 0)) {
03380 DEBUG("Both salts undefined - do nothing");
03381 return 0;
03382 }
03383
03384
03385 int ltag = (tag) ? strlen(tag) + 1 : 0;
03386
03387
03388 XrdCryptoKDFun_t KDFun = cf->KDFun();
03389 XrdCryptoKDFunLen_t KDFunLen = cf->KDFunLen();
03390 if (!KDFun || !KDFunLen) {
03391 DEBUG("Could not get hooks to one-way hash functions ("
03392 <<KDFun<<","<<KDFunLen<<")");
03393 return -1;
03394 }
03395
03396
03397 char *nhash = 0, *thash = bck->buffer;
03398 int nhlen = bck->size;
03399 if (s1 && s1->size > 0) {
03400 if (!(nhash = new char[(*KDFunLen)() + ltag])) {
03401 DEBUG("Could not allocate memory for hash - s1");
03402 return -1;
03403 }
03404 if ((nhlen = (*KDFun)(thash,nhlen,
03405 s1->buffer,s1->size,nhash+ltag,0)) <= 0) {
03406 DEBUG("Problems hashing - s1");
03407 delete[] nhash;
03408 return -1;
03409 }
03410 thash = nhash;
03411 }
03412
03413
03414 if (s2 && s2->size > 0) {
03415 if (!(nhash = new char[(*KDFunLen)() + ltag])) {
03416 DEBUG("Could not allocate memory for hash - s2");
03417 return -1;
03418 }
03419 if (thash && thash != bck->buffer) thash += ltag;
03420 if ((nhlen = (*KDFun)(thash,nhlen,
03421 s2->buffer,s2->size,nhash+ltag,0)) <= 0) {
03422 DEBUG("Problems hashing - s2");
03423 delete[] nhash;
03424 if (thash && thash != bck->buffer) delete[] thash;
03425 return -1;
03426 }
03427 if (thash && thash != bck->buffer) delete[] thash;
03428 thash = nhash;
03429 }
03430
03431
03432 if (tag)
03433 memcpy(thash,tag,ltag);
03434
03435
03436 bck->SetBuf(thash,nhlen+ltag);
03437
03438
03439 return 0;
03440 }
03441
03442
03443 int XrdSecProtocolpwd::QueryCrypt(String &fn, String &pwhash)
03444 {
03445
03446
03447
03448
03449
03450
03451
03452
03453
03454
03455
03456 EPNAME("QueryCrypt");
03457
03458 int rc = -1;
03459 int len = 0, n = 0, fid = -1;
03460 pwhash = "";
03461 DEBUG("analyzing file: "<<fn);
03462
03463
03464
03465 struct passwd *pw = getpwnam(hs->User.c_str());
03466 if (!pw) {
03467 DEBUG("Cannot get pwnam structure for user "<<hs->User);
03468 return -1;
03469 }
03470
03471
03472 if (fn.length() > 0) {
03473
03474
03475 int uid = pw->pw_uid;
03476
03477
03478 XrdSysPrivGuard priv(uid, pw->pw_gid);
03479 bool go = priv.Valid();
03480 if (!go) {
03481 DEBUG("problems acquiring temporarly identity: "<<hs->User);
03482 }
03483
03484
03485 String fpw(pw->pw_dir, strlen(pw->pw_dir) + fn.length() + 5);
03486 if (go) {
03487 fpw += ("/" + fn);
03488 DEBUG("checking file "<<fpw<<" for user "<<hs->User);
03489 }
03490
03491
03492 struct stat st;
03493 if (go && stat(fpw.c_str(), &st) == -1) {
03494 if (errno != ENOENT) {
03495 DEBUG("cannot stat password file "<<fpw<<" (errno:"<<errno<<")");
03496 rc = -1;
03497 } else {
03498 DEBUG("file "<<fpw<<" does not exist");
03499 rc = 0;
03500 }
03501 go = 0;
03502 }
03503 if (go &&
03504 (!S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) ||
03505 (st.st_mode & (S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH)) != 0)) {
03506 DEBUG("pass file "<<fpw<<": wrong permissions "<<
03507 (st.st_mode & 0777) << " (should be 0600)");
03508 rc = -2;
03509 go = 0;
03510 }
03511
03512
03513 if (go && (fid = open(fpw.c_str(), O_RDONLY)) == -1) {
03514 DEBUG("cannot open file "<<fpw<<" (errno:"<<errno<<")");
03515 rc = -1;
03516 go = 0;
03517 }
03518
03519
03520 char pass[128];
03521 if (go && (n = read(fid, pass, sizeof(pass)-1)) <= 0) {
03522 close(fid);
03523 DEBUG("cannot read file "<<fpw<<" (errno:"<<errno<<")");
03524 rc = -1;
03525 go = 0;
03526 }
03527 if (fid > -1)
03528 close(fid);
03529
03530
03531 if (go) {
03532 len = n;
03533 while (len-- && (pass[len] == '\n' || pass[len] == 32))
03534 pass[len] = 0;
03535
03536 pass[++len] = 0;
03537 rc = len;
03538
03539 pwhash = pass;
03540 }
03541 }
03542
03543
03544 if (pwhash.length() > 0)
03545 return rc;
03546
03547
03548 #ifdef R__AFS
03549
03550 fn = "afs:";
03551 fn += ka_LocalCell();
03552 pwhash = "afs";
03553 #else
03554 #ifdef R__SHADOWPW
03555 {
03556
03557 XrdSysPrivGuard priv((uid_t)0, (gid_t)0);
03558 if (priv.Valid()) {
03559 struct spwd *spw = 0;
03560
03561 if ((spw = getspnam(hs->User.c_str())) == 0) {
03562 DEBUG("shadow passwd not accessible to this application");
03563 } else
03564 pwhash = spw->sp_pwdp;
03565 } else {
03566 DEBUG("problems acquiring temporarly superuser privileges");
03567 }
03568 }
03569 #else
03570 pwhash = pw->pw_passwd;
03571 #endif
03572
03573
03574 fn = "system";
03575 #endif
03576
03577 if ((rc = pwhash.length()) <= 2) {
03578 DEBUG("passwd hash not available for user "<<hs->User);
03579 pwhash = "";
03580 fn = "";
03581 rc = -1;
03582 }
03583
03584
03585 return rc;
03586 }
03587
03588
03589 int XrdSecProtocolpwd::QueryNetRc(String host, String &passwd, int &status)
03590 {
03591
03592
03593
03594
03595
03596
03597
03598
03599
03600
03601
03602
03603 EPNAME("QueryNetRc");
03604 passwd = "";
03605
03606
03607 String fnrc = getenv("XrdSecNETRC");
03608 if (fnrc.length() <= 0) {
03609 DEBUG("File name undefined");
03610 return -1;
03611 }
03612
03613 if (XrdSutResolve(fnrc, Entity.host, Entity.vorg, Entity.grps, Entity.name) != 0) {
03614 DEBUG("Problems resolving templates in "<<fnrc);
03615 return -1;
03616 }
03617 DEBUG("checking file "<<fnrc<<" for user "<<hs->User);
03618
03619
03620 struct stat st;
03621 if (stat(fnrc.c_str(), &st) == -1) {
03622 if (errno != ENOENT) {
03623 DEBUG("cannot stat password file "<<fnrc<<" (errno:"<<errno<<")");
03624 } else {
03625 DEBUG("file "<<fnrc<<" does not exist");
03626 }
03627 return -1;
03628 }
03629 if (!S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) ||
03630 (st.st_mode & (S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH)) != 0) {
03631 DEBUG("pass file "<<fnrc<<": wrong permissions "<<
03632 (st.st_mode & 0777) << " (should be 0600)");
03633 return -2;
03634 }
03635
03636 FILE *fid = fopen(fnrc.c_str(), "r");
03637 if (!fid) {
03638 DEBUG("cannot open file "<<fnrc<<" (errno:"<<errno<<")");
03639 return -1;
03640 }
03641 char line[512];
03642 int nm = 0, nmmx = -1;
03643 while (fgets(line, sizeof(line), fid) != 0) {
03644 if (line[0] == '#')
03645 continue;
03646 char word[6][128];
03647 int nword = sscanf(line, "%s %s %s %s %s %s", word[0], word[1],
03648 word[2], word[3], word[4], word[5]);
03649 if (nword != 6) continue;
03650 if (strcmp(word[0], "machine") || strcmp(word[2], "login") ||
03651 strcmp(word[4], "password"))
03652 continue;
03653
03654 if ((nm = host.matches(word[1])) > 0) {
03655
03656 if (!strcmp(hs->User.c_str(),word[3])) {
03657
03658 if (nm == host.length()) {
03659 passwd = word[5];
03660 status = kpCI_exact;
03661 break;
03662 }
03663
03664 if (nm > nmmx) {
03665 nmmx = nm;
03666 passwd = word[5];
03667 status = kpCI_wildcard;
03668 }
03669 }
03670 }
03671 }
03672
03673
03674 fclose(fid);
03675
03676
03677 if (passwd.length() > 0)
03678 return 0;
03679 return -1;
03680 }
03681
03682
03683 bool XrdSecProtocolpwd::CheckTimeStamp(XrdSutBuffer *bm, int skew, String &emsg)
03684 {
03685
03686
03687
03688 EPNAME("CheckTimeStamp");
03689
03690
03691 if (!bm || skew <= 0) {
03692 if (!bm)
03693 emsg = "input buffer undefined ";
03694 else
03695 emsg = "negative skew: invalid ";
03696 return 0;
03697 }
03698
03699
03700
03701 if (hs->RtagOK || VeriClnt != 1) {
03702 DEBUG("Nothing to do");
03703
03704 if (bm->GetBucket(kXRS_timestamp))
03705 bm->Deactivate(kXRS_timestamp);
03706 return 1;
03707 }
03708
03709
03710
03711 kXR_int32 tstamp = 0;
03712 if (bm->UnmarshalBucket(kXRS_timestamp,tstamp) != 0) {
03713 emsg = "bucket with time stamp not found";
03714 return 0;
03715 }
03716
03717 kXR_int32 dtim = hs->TimeStamp - tstamp;
03718 dtim = (dtim < 0) ? -dtim : dtim;
03719 if (dtim > skew) {
03720 emsg = "time difference too big: "; emsg += (int)dtim;
03721 emsg += " - allowed skew: "; emsg += skew;
03722 bm->Deactivate(kXRS_timestamp);
03723 return 0;
03724 }
03725 bm->Deactivate(kXRS_timestamp);
03726
03727 DEBUG("Time stamp successfully checked");
03728
03729
03730 return 1;
03731 }
03732
03733
03734 bool XrdSecProtocolpwd::CheckRtag(XrdSutBuffer *bm, String &emsg)
03735 {
03736
03737 EPNAME("CheckRtag");
03738
03739
03740 if (!bm) {
03741 emsg = "Buffer not defined";
03742 return 0;
03743 }
03744
03745
03746 if (hs->Cref && hs->Cref->buf1.len > 0) {
03747 XrdSutBucket *brt = 0;
03748 if ((brt = bm->GetBucket(kXRS_signed_rtag))) {
03749
03750 if (!(hs->Hcip)) {
03751 emsg = "Session cipher undefined";
03752 return 0;
03753 }
03754
03755 if (!(hs->Hcip->Decrypt(*brt))) {
03756 emsg = "error decrypting random tag with session cipher";
03757 return 0;
03758 }
03759 } else {
03760 emsg = "random tag missing - protocol error";
03761 return 0;
03762 }
03763
03764
03765 if (memcmp(brt->buffer,hs->Cref->buf1.buf,hs->Cref->buf1.len)) {
03766 emsg = "random tag content mismatch";
03767 SafeDelete(hs->Cref);
03768
03769 return 0;
03770 }
03771
03772
03773 memset(hs->Cref->buf1.buf,0,hs->Cref->buf1.len);
03774 hs->Cref->buf1.SetBuf();
03775
03776
03777 hs->RtagOK = 1;
03778 bm->Deactivate(kXRS_signed_rtag);
03779 DEBUG("Random tag successfully checked");
03780 } else {
03781 DEBUG("Nothing to check");
03782 }
03783
03784
03785 return 1;
03786 }