00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <unistd.h>
00010 #include <ctype.h>
00011 #include <errno.h>
00012 #include <stdlib.h>
00013 #include <strings.h>
00014 #include <stdio.h>
00015 #include <sys/param.h>
00016 #include <pwd.h>
00017 #include <sys/types.h>
00018 #include <sys/stat.h>
00019 #include <fcntl.h>
00020 #include <dirent.h>
00021
00022 #include "XrdNet/XrdNetDNS.hh"
00023 #include "XrdSys/XrdSysHeaders.hh"
00024 #include <XrdSys/XrdSysLogger.hh>
00025 #include <XrdSys/XrdSysError.hh>
00026 #include "XrdSys/XrdSysPlugin.hh"
00027 #include "XrdSys/XrdSysPriv.hh"
00028 #include <XrdOuc/XrdOucStream.hh>
00029
00030 #include <XrdSut/XrdSutCache.hh>
00031
00032 #include <XrdCrypto/XrdCryptoMsgDigest.hh>
00033 #include <XrdCrypto/XrdCryptosslAux.hh>
00034 #include <XrdCrypto/XrdCryptosslgsiAux.hh>
00035
00036 #include <XrdSecgsi/XrdSecProtocolgsi.hh>
00037 #include <XrdSecgsi/XrdSecgsiTrace.hh>
00038
00039
00040
00041
00042
00043 static String Prefix = "xrd";
00044 static String ProtoID = XrdSecPROTOIDENT;
00045 static const kXR_int32 Version = XrdSecgsiVERSION;
00046
00047 static const char *gsiClientSteps[] = {
00048 "kXGC_none",
00049 "kXGC_certreq",
00050 "kXGC_cert",
00051 "kXGC_reserved"
00052 };
00053
00054 static const char *gsiServerSteps[] = {
00055 "kXGS_none",
00056 "kXGS_init",
00057 "kXGS_cert",
00058 "kXGS_reserved"
00059 };
00060
00061 static const char *gGSErrStr[] = {
00062 "ErrParseBuffer",
00063 "ErrDecodeBuffer",
00064 "ErrLoadCrypto",
00065 "ErrBadProtocol",
00066 "ErrCreateBucket",
00067 "ErrDuplicateBucket",
00068 "ErrCreateBuffer",
00069 "ErrSerialBuffer",
00070 "ErrGenCipher",
00071 "ErrExportPuK",
00072 "ErrEncRndmTag",
00073 "ErrBadRndmTag",
00074 "ErrNoRndmTag",
00075 "ErrNoCipher",
00076 "ErrNoCreds",
00077 "ErrBadOpt",
00078 "ErrMarshal",
00079 "ErrUnmarshal",
00080 "ErrSaveCreds",
00081 "ErrNoBuffer",
00082 "ErrRefCipher",
00083 "ErrNoPublic",
00084 "ErrAddBucket",
00085 "ErrFinCipher",
00086 "ErrInit",
00087 "ErrBadCreds",
00088 "ErrError"
00089 };
00090
00091
00092 static const int kOneDay = 86400;
00093 static const char *gUsrPxyDef = "/tmp/x509up_u";
00094
00095
00096
00097
00098
00099 XrdSysMutex XrdSecProtocolgsi::gsiContext;
00100 String XrdSecProtocolgsi::CAdir = "/etc/grid-security/certificates/";
00101 String XrdSecProtocolgsi::CRLdir = "/etc/grid-security/certificates/";
00102 String XrdSecProtocolgsi::DefCRLext= ".r0";
00103 String XrdSecProtocolgsi::GMAPFile = "/etc/grid-security/grid-mapfile";
00104 String XrdSecProtocolgsi::SrvCert = "/etc/grid-security/xrd/xrdcert.pem";
00105 String XrdSecProtocolgsi::SrvKey = "/etc/grid-security/xrd/xrdkey.pem";
00106 String XrdSecProtocolgsi::UsrProxy;
00107 String XrdSecProtocolgsi::UsrCert = "/.globus/usercert.pem";
00108 String XrdSecProtocolgsi::UsrKey = "/.globus/userkey.pem";;
00109 String XrdSecProtocolgsi::PxyValid = "12:00";
00110 int XrdSecProtocolgsi::DepLength= 0;
00111 int XrdSecProtocolgsi::DefBits = 512;
00112 int XrdSecProtocolgsi::CACheck = 1;
00113 int XrdSecProtocolgsi::CRLCheck = 1;
00114 int XrdSecProtocolgsi::GMAPOpt = 1;
00115 String XrdSecProtocolgsi::DefCrypto= "ssl";
00116 String XrdSecProtocolgsi::DefCipher= "aes-128-cbc:bf-cbc:des-ede3-cbc";
00117 String XrdSecProtocolgsi::DefMD = "sha1:md5";
00118 String XrdSecProtocolgsi::DefError = "invalid credentials ";
00119 int XrdSecProtocolgsi::PxyReqOpts = 0;
00120 int XrdSecProtocolgsi::AuthzPxy = 0;
00121 XrdSysPlugin *XrdSecProtocolgsi::GMAPPlugin = 0;
00122 XrdSecgsiGMAP_t XrdSecProtocolgsi::GMAPFun = 0;
00123 XrdSysPlugin *XrdSecProtocolgsi::AuthzPlugin = 0;
00124 XrdSecgsiAuthz_t XrdSecProtocolgsi::AuthzFun = 0;
00125 int XrdSecProtocolgsi::GMAPCacheTimeOut = -1;
00126 String XrdSecProtocolgsi::SrvAllowedNames;
00127
00128
00129 int XrdSecProtocolgsi::ncrypt = 0;
00130 XrdCryptoFactory *XrdSecProtocolgsi::cryptF[XrdCryptoMax] = {0};
00131 int XrdSecProtocolgsi::cryptID[XrdCryptoMax] = {0};
00132 String XrdSecProtocolgsi::cryptName[XrdCryptoMax] = {0};
00133 XrdCryptoCipher *XrdSecProtocolgsi::refcip[XrdCryptoMax] = {0};
00134
00135
00136 XrdSutCache XrdSecProtocolgsi::cacheCA;
00137 XrdSutCache XrdSecProtocolgsi::cacheCert;
00138 XrdSutCache XrdSecProtocolgsi::cachePxy;
00139 XrdSutCache XrdSecProtocolgsi::cacheGMAP;
00140 XrdSutCache XrdSecProtocolgsi::cacheGMAPFun;
00141
00142
00143 int XrdSecProtocolgsi::Debug = 0;
00144 bool XrdSecProtocolgsi::Server = 1;
00145 int XrdSecProtocolgsi::TimeSkew = 300;
00146
00147
00148 XrdSysError XrdSecProtocolgsi::eDest(0, "secgsi_");
00149 XrdSysLogger XrdSecProtocolgsi::Logger;
00150 XrdOucTrace *XrdSecProtocolgsi::GSITrace = 0;
00151
00152 XrdOucTrace *gsiTrace = 0;
00153
00154
00155
00156
00157
00158 static const char *ClientStepStr(int kclt)
00159 {
00160
00161 static const char *ukn = "Unknown";
00162
00163 kclt = (kclt < 0) ? 0 : kclt;
00164 kclt = (kclt > kXGC_reserved) ? 0 : kclt;
00165 kclt = (kclt >= kXGC_certreq) ? (kclt - kXGC_certreq + 1) : kclt;
00166
00167 if (kclt < 0 || kclt > (kXGC_reserved - kXGC_certreq + 1))
00168 return ukn;
00169 else
00170 return gsiClientSteps[kclt];
00171 }
00172
00173
00174 static const char *ServerStepStr(int ksrv)
00175 {
00176
00177 static const char *ukn = "Unknown";
00178
00179 ksrv = (ksrv < 0) ? 0 : ksrv;
00180 ksrv = (ksrv > kXGS_reserved) ? 0 : ksrv;
00181 ksrv = (ksrv >= kXGS_init) ? (ksrv - kXGS_init + 1) : ksrv;
00182
00183 if (ksrv < 0 || ksrv > (kXGS_reserved - kXGS_init + 1))
00184 return ukn;
00185 else
00186 return gsiServerSteps[ksrv];
00187 }
00188
00189
00190
00191
00192
00193
00194
00195 void gsiHSVars::Dump(XrdSecProtocolgsi *p)
00196 {
00197
00198 EPNAME("HSVars::Dump");
00199
00200 PRINT("----------------------------------------------------------------");
00201 PRINT("protocol instance: "<<p);
00202 PRINT("this: "<<this);
00203 PRINT(" ");
00204 PRINT("Time stamp: "<<TimeStamp);
00205 PRINT("Crypto mod: "<<CryptoMod);
00206 PRINT("Remote version: "<<RemVers);
00207 PRINT("Ref cipher: "<<Rcip);
00208 PRINT("Bucket for exp cert: "<<Cbck);
00209 PRINT("Handshake ID: "<<ID);
00210 PRINT("Cache reference: "<<Cref);
00211 PRINT("Relevant file entry: "<<Pent);
00212 PRINT("Chain pointer: "<<Chain);
00213 PRINT("CRL pointer: "<<Crl);
00214 PRINT("Proxy chain: "<<PxyChain);
00215 PRINT("Rndm tag checked: "<<RtagOK);
00216 PRINT("Last step: "<<LastStep);
00217 PRINT("Options: "<<Options);
00218 PRINT("----------------------------------------------------------------");
00219 }
00220
00221
00222
00223
00224
00225
00226
00227 XrdSecProtocolgsi::XrdSecProtocolgsi(int opts, const char *hname,
00228 const struct sockaddr *ipadd,
00229 const char *parms) : XrdSecProtocol("gsi")
00230 {
00231
00232 EPNAME("XrdSecProtocolgsi");
00233
00234 if (QTRACE(Authen)) { PRINT("constructing: "<<this); }
00235
00236
00237 if ((hs = new gsiHSVars())) {
00238
00239 hs->TimeStamp = time(0);
00240
00241 hs->Tty = (isatty(0) == 0 || isatty(1) == 0) ? 0 : 1;
00242 } else {
00243 DEBUG("could not create handshake vars object");
00244 }
00245
00246
00247 if (ipadd) {
00248 Entity.host = XrdNetDNS::getHostName((sockaddr&)*ipadd);
00249
00250 memcpy(&hostaddr, ipadd, sizeof(hostaddr));
00251 } else {
00252 PRINT("WARNING: IP addr undefined: cannot determine host name: failure may follow");
00253 }
00254
00255
00256 sessionCF = 0;
00257 sessionKey = 0;
00258 bucketKey = 0;
00259 sessionMD = 0;
00260 sessionKsig = 0;
00261 sessionKver = 0;
00262 sessionKver = 0;
00263 proxyChain = 0;
00264
00265
00266
00267 DEBUG("constructing: host: "<<hname);
00268 DEBUG("p: "<<XrdSecPROTOIDENT<<", plen: "<<XrdSecPROTOIDLEN);
00269
00270
00271 options = opts;
00272 srvMode = 0;
00273
00274
00275
00276 if (Server) {
00277 srvMode = 1;
00278 DEBUG("mode: server");
00279 } else {
00280 DEBUG("mode: client");
00281
00282
00283 if (parms) {
00284 XrdOucString p("&P=gsi,");
00285 p += parms;
00286 hs->Parms = new XrdSutBuffer(p.c_str(), p.length());
00287 }
00288 }
00289
00290
00291 String vers = Version;
00292 vers.insert('.',vers.length()-2);
00293 vers.insert('.',vers.length()-5);
00294 DEBUG("object created: v"<<vers.c_str());
00295 }
00296
00297
00298 char *XrdSecProtocolgsi::Init(gsiOptions opt, XrdOucErrInfo *erp)
00299 {
00300
00301
00302 EPNAME("Init");
00303 char *Parms = 0;
00304
00305
00306
00307 int timestamp = (int)time(0);
00308
00309
00310 Debug = (opt.debug > -1) ? opt.debug : Debug;
00311
00312 eDest.logger(&Logger);
00313 GSITrace = new XrdOucTrace(&eDest);
00314
00315 int trace = 0;
00316 if (Debug >= 3) {
00317 trace = cryptoTRACE_Dump;
00318 GSITrace->What |= TRACE_Authen;
00319 GSITrace->What |= TRACE_Debug;
00320 } else if (Debug >= 1) {
00321 trace = cryptoTRACE_Debug;
00322 GSITrace->What = TRACE_Debug;
00323 }
00324 gsiTrace = GSITrace;
00325
00326 XrdSutSetTrace(trace);
00327 XrdCryptoSetTrace(trace);
00328
00329
00330
00331 Server = (opt.mode == 's');
00332
00333
00334
00335
00336
00337
00338
00339
00340 if (opt.ca >= 0 && opt.ca <= 2)
00341 CACheck = opt.ca;
00342 DEBUG("option CACheck: "<<CACheck);
00343
00344
00345
00346 struct stat st;
00347 if (opt.certdir) {
00348 DEBUG("testing CA dir(s): "<<opt.certdir);
00349 String CAtmp;
00350 String tmp = opt.certdir;
00351 String dp;
00352 int from = 0;
00353 while ((from = tmp.tokenize(dp, from, ',')) != -1) {
00354 if (dp.length() > 0) {
00355 if (XrdSutExpand(dp) == 0) {
00356 if (stat(dp.c_str(),&st) == -1) {
00357 if (errno == ENOENT) {
00358 ErrF(erp,kGSErrError,"CA directory non existing:",dp.c_str());
00359 PRINT(erp->getErrText());
00360 } else {
00361 ErrF(erp,kGSErrError,"cannot stat CA directory:",dp.c_str());
00362 PRINT(erp->getErrText());
00363 }
00364 } else {
00365 if (!(dp.endswith('/'))) dp += '/';
00366 if (!(CAtmp.endswith(','))) CAtmp += ',';
00367 CAtmp += dp;
00368 }
00369 } else {
00370 PRINT("Warning: could not expand: "<<dp);
00371 }
00372 }
00373 }
00374 if (CAtmp.length() > 0)
00375 CAdir = CAtmp;
00376 }
00377 DEBUG("using CA dir(s): "<<CAdir);
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 if (opt.crl >= 0 && opt.crl <= 3)
00388 CRLCheck = opt.crl;
00389 DEBUG("option CRLCheck: "<<CRLCheck);
00390
00391
00392
00393 if (opt.crldir) {
00394
00395 DEBUG("testing CRL dir(s): "<<opt.crldir);
00396 String CRLtmp;
00397 String tmp = opt.crldir;
00398 String dp;
00399 int from = 0;
00400 while ((from = tmp.tokenize(dp, from, ',')) != -1) {
00401 if (dp.length() > 0) {
00402 if (XrdSutExpand(dp) == 0) {
00403 if (stat(dp.c_str(),&st) == -1) {
00404 if (errno == ENOENT) {
00405 ErrF(erp,kGSErrError,"CRL directory non existing:",dp.c_str());
00406 PRINT(erp->getErrText());
00407 } else {
00408 ErrF(erp,kGSErrError,"cannot stat CRL directory:",dp.c_str());
00409 PRINT(erp->getErrText());
00410 }
00411 } else {
00412 if (!(dp.endswith('/'))) dp += '/';
00413 if (!(CRLtmp.endswith(','))) CRLtmp += ',';
00414 CRLtmp += dp;
00415 }
00416 } else {
00417 PRINT("Warning: could not expand: "<<dp);
00418 }
00419 }
00420 }
00421 if (CRLtmp.length() > 0)
00422 CRLdir = CRLtmp;
00423
00424 } else {
00425
00426 CRLdir = CAdir;
00427 }
00428 if (CRLCheck > 0)
00429 DEBUG("using CRL dir(s): "<<CRLdir);
00430
00431
00432
00433 if (opt.crlext)
00434 DefCRLext = opt.crlext;
00435
00436
00437
00438 if (Server) {
00439
00440
00441 if (opt.clist)
00442 DefCrypto = opt.clist;
00443
00444
00445 String cryptlist(DefCrypto,0,-1,64);
00446
00447
00448 XrdSutPFEntry ent;
00449 XrdCryptoFactory *cf = 0;
00450 if (cryptlist.length()) {
00451 String ncpt = "";
00452 int from = 0;
00453 while ((from = cryptlist.tokenize(ncpt, from, '|')) != -1) {
00454 if (ncpt.length() > 0 && ncpt[0] != '-') {
00455
00456 if ((cf = XrdCryptoFactory::GetCryptoFactory(ncpt.c_str()))) {
00457
00458 cryptF[ncrypt] = cf;
00459 cryptID[ncrypt] = cf->ID();
00460 cryptName[ncrypt].insert(cf->Name(),0,strlen(cf->Name())+1);
00461 cf->SetTrace(trace);
00462
00463 if (!(refcip[ncrypt] = cf->Cipher(0,0,0))) {
00464 PRINT("ref cipher for module "<<ncpt<<
00465 " cannot be instantiated : disable");
00466 from -= ncpt.length();
00467 cryptlist.erase(ncpt);
00468 } else {
00469 ncrypt++;
00470 if (ncrypt >= XrdCryptoMax) {
00471 PRINT("max number of crypto modules ("
00472 << XrdCryptoMax <<") reached ");
00473 break;
00474 }
00475 }
00476 } else {
00477 PRINT("cannot instantiate crypto factory "<<ncpt<<
00478 ": disable");
00479 from -= ncpt.length();
00480 cryptlist.erase(ncpt);
00481 }
00482 }
00483 }
00484 }
00485
00486
00487 if (ncrypt <= 0) {
00488 ErrF(erp,kGSErrInit,"could not find any valid crypto module");
00489 PRINT(erp->getErrText());
00490 return Parms;
00491 }
00492
00493
00494 if (LoadCADir(timestamp) != 0) {
00495 ErrF(erp,kGSErrError,"problems loading CA info into cache");
00496 PRINT(erp->getErrText());
00497 return Parms;
00498 }
00499 if (QTRACE(Authen)) { cacheCA.Dump(); }
00500
00501
00502
00503 if (opt.cipher)
00504 DefCipher = opt.cipher;
00505
00506 String cip = "";
00507 int from = 0;
00508 while ((from = DefCipher.tokenize(cip, from, ':')) != -1) {
00509 if (cip.length() > 0) {
00510 int i = 0;
00511 for (; i < ncrypt; i++) {
00512 if (!(cryptF[i]->SupportedCipher(cip.c_str()))) {
00513
00514 DEBUG("cipher type not supported ("<<cip<<") - disabling");
00515 from -= cip.length();
00516 DefCipher.erase(cip);
00517 }
00518 }
00519 }
00520 }
00521
00522
00523
00524 if (opt.md)
00525 DefMD = opt.md;
00526
00527 String md = "";
00528 from = 0;
00529 while ((from = DefMD.tokenize(md, from, ':')) != -1) {
00530 if (md.length() > 0) {
00531 int i = 0;
00532 for (; i < ncrypt; i++) {
00533 if (!(cryptF[i]->SupportedMsgDigest(md.c_str()))) {
00534
00535 PRINT("MD type not supported ("<<md<<") - disabling");
00536 from -= md.length();
00537 DefMD.erase(md);
00538 }
00539 }
00540 }
00541 }
00542
00543
00544
00545 if (opt.cert) {
00546 String TmpCert = opt.cert;
00547 if (XrdSutExpand(TmpCert) == 0) {
00548 SrvCert = TmpCert;
00549 } else {
00550 PRINT("Could not expand: "<<opt.cert<<": use default");
00551 }
00552 }
00553 if (opt.key) {
00554 String TmpKey = opt.key;
00555 if (XrdSutExpand(TmpKey) == 0) {
00556 SrvKey = TmpKey;
00557 } else {
00558 PRINT("Could not expand: "<<opt.key<<": use default");
00559 }
00560 }
00561
00562
00563 if (access(SrvKey.c_str(), R_OK)) {
00564 PRINT("WARNING: process has no permission to read the certificate key file: "<<SrvKey);
00565 }
00566
00567
00568
00569 bool getpriv = 0;
00570 uid_t gsi_uid = geteuid();
00571 gid_t gsi_gid = getegid();
00572 if (!stat(SrvKey.c_str(), &st)) {
00573 if (st.st_uid != gsi_uid || st.st_gid != gsi_gid) {
00574 getpriv = 1;
00575 gsi_uid = st.st_uid;
00576 gsi_gid = st.st_gid;
00577 }
00578 }
00579
00580
00581
00582
00583 if (cacheCert.Init(10) != 0) {
00584 ErrF(erp,kGSErrError,"problems init cache for certificates");
00585 PRINT(erp->getErrText());
00586 return Parms;
00587 }
00588 int i = 0;
00589 String certcalist = "";
00590 for (; i<ncrypt; i++) {
00591
00592 XrdCryptoX509 *xsrv = 0;
00593 { XrdSysPrivGuard pGuard(gsi_uid, gsi_gid);
00594 if (pGuard.Valid())
00595 xsrv = cryptF[i]->X509(SrvCert.c_str(), SrvKey.c_str());
00596 }
00597 if (xsrv) {
00598
00599 if (xsrv->type != XrdCryptoX509::kEEC) {
00600 PRINT("problems loading srv cert: not EEC but: "<<xsrv->Type());
00601 continue;
00602 }
00603
00604 if (!(xsrv->IsValid())) {
00605 PRINT("problems loading srv cert: invalid");
00606 continue;
00607 }
00608
00609 if (!xsrv->PKI() || xsrv->PKI()->status != XrdCryptoRSA::kComplete) {
00610 PRINT("problems loading srv cert: invalid PKI");
00611 continue;
00612 }
00613
00614 XrdSutBucket *xbck = xsrv->Export();
00615 if (!xbck) {
00616 PRINT("problems loading srv cert: cannot export into bucket");
00617 continue;
00618 }
00619
00620 String tag = cryptF[i]->Name();
00621 XrdSutPFEntry *cent = cacheCert.Add(tag.c_str());
00622 if (cent) {
00623 cent->status = kPFE_ok;
00624 cent->cnt = 0;
00625 cent->mtime = xsrv->NotAfter();
00626
00627 cent->buf1.buf = (char *)xsrv;
00628 cent->buf1.len = 0;
00629
00630 cent->buf2.buf = (char *)(xsrv->PKI());
00631 cent->buf2.len = 0;
00632
00633 cent->buf3.buf = (char *)(xbck);
00634 cent->buf3.len = 0;
00635
00636 if (certcalist.find(xsrv->IssuerHash()) == STR_NPOS) {
00637 if (certcalist.length() > 0)
00638 certcalist += "|";
00639 certcalist += xsrv->IssuerHash();
00640 }
00641 }
00642 }
00643 }
00644
00645 cacheCert.Rehash(1);
00646
00647
00648 if (cacheCert.Empty()) {
00649 ErrF(erp,kGSErrError,"no valid server certificate found");
00650 PRINT(erp->getErrText());
00651 return Parms;
00652 }
00653 if (QTRACE(Authen)) { cacheCert.Dump(); }
00654
00655 DEBUG("CA list: "<<certcalist);
00656
00657
00658
00659
00660
00661
00662
00663 const char *cogmap[] = { "do-not-use", "use-if-available", "require" };
00664 if (opt.ogmap >= 0 && opt.ogmap <= 2)
00665 GMAPOpt = opt.ogmap;
00666 DEBUG("grid map file option: "<<cogmap[GMAPOpt]);
00667
00668
00669
00670 if (opt.gridmap) {
00671 String GMAPTmp = opt.gridmap;
00672 if (XrdSutExpand(GMAPTmp) == 0) {
00673 GMAPFile = GMAPTmp;
00674 } else {
00675 PRINT("Could not expand: "<<opt.gridmap<<": use default");
00676 }
00677 }
00678 bool hasgmap = 0;
00679 if (GMAPOpt > 0) {
00680 if (access(GMAPFile.c_str(),R_OK) != 0) {
00681 if (GMAPOpt > 1) {
00682 if (errno == ENOENT) {
00683 ErrF(erp,kGSErrError,"Grid map file non existing:",GMAPFile.c_str());
00684 PRINT(erp->getErrText());
00685 } else {
00686 ErrF(erp,kGSErrError,"'access' error on grid map file:",GMAPFile.c_str());
00687 PRINT(erp->getErrText());
00688 }
00689 return Parms;
00690 } else {
00691 DEBUG("Grid map file: "<<GMAPFile<<" cannot be 'access'ed: do not use");
00692 }
00693 } else {
00694 DEBUG("using grid map file: "<<GMAPFile);
00695
00696
00697 if (LoadGMAP(timestamp) != 0) {
00698 ErrF(erp,kGSErrError,"problems initializing cache for gridmap entries");
00699 PRINT(erp->getErrText());
00700 return Parms;
00701 }
00702 if (QTRACE(Authen)) { cacheGMAP.Dump(); }
00703 hasgmap = 1;
00704 }
00705 }
00706
00707
00708 bool hasauthzfun = 0;
00709 if (opt.authzfun && GMAPOpt > 0) {
00710 if (!(AuthzFun = LoadAuthzFun((const char *) opt.authzfun,
00711 (const char *) opt.authzfunparms))) {
00712 PRINT("Could not load plug-in: "<<opt.authzfun<<": ignore");
00713 } else {
00714 hasauthzfun = 1;
00715 }
00716 }
00717 bool hasgmapfun = 0;
00718 if (opt.gmapfun && GMAPOpt > 0) {
00719 if (!hasauthzfun) {
00720 if (!(GMAPFun = LoadGMAPFun((const char *) opt.gmapfun,
00721 (const char *) opt.gmapfunparms))) {
00722 PRINT("Could not load plug-in: "<<opt.gmapfun<<": ignore");
00723 } else {
00724
00725 if (cacheGMAPFun.Empty()) {
00726 if (cacheGMAPFun.Init(100) != 0) {
00727 PRINT("Error initializing GMAPFun cache");
00728 return Parms;
00729 }
00730 } else {
00731 if (cacheGMAPFun.Reset() != 0) {
00732 PRINT("Error resetting GMAPFun cache");
00733 return Parms;
00734 }
00735 }
00736 hasgmapfun = 1;
00737 }
00738 } else {
00739 PRINT("WARNING: ignoring 'gmapfun' directive since an authz plugin (specified"
00740 " via 'authzfun') has already been successfully loaded");
00741 }
00742 }
00743
00744
00745 if (!hasgmap && !hasgmapfun && !hasauthzfun) {
00746 if (GMAPOpt > 1) {
00747 ErrF(erp,kGSErrError,"Grid mapping required, but neither a grid mapfile"
00748 " nor a mapping function are available");
00749 PRINT(erp->getErrText());
00750 return Parms;
00751 }
00752 GMAPOpt = 0;
00753 }
00754
00755
00756 if (GMAPOpt > 0 && !hasauthzfun && opt.gmapto > 0) {
00757 GMAPCacheTimeOut = opt.gmapto;
00758 DEBUG("grid-map cache entries expire after "<<GMAPCacheTimeOut<<" secs");
00759 }
00760
00761
00762
00763 if (opt.dlgpxy == 1 || opt.dlgpxy == 3)
00764 PxyReqOpts |= kOptsSrvReq;
00765 if (opt.dlgpxy == 2 || opt.dlgpxy == 3)
00766 PxyReqOpts |= kOptsPxFile;
00767
00768 DEBUG("Delegated proxies options: "<<PxyReqOpts);
00769
00770
00771
00772 if (opt.authzpxy == 1)
00773 AuthzPxy = 1;
00774
00775 DEBUG("Export proxy for authorization (in XrdSecEntity.endorsement): "<<AuthzPxy);
00776
00777
00778
00779 if ((PxyReqOpts & kOptsPxFile)) {
00780 String TmpProxy = gUsrPxyDef;
00781 if (opt.exppxy) TmpProxy = opt.exppxy;
00782 if (XrdSutExpand(TmpProxy) == 0) {
00783 UsrProxy = TmpProxy;
00784 } else {
00785 UsrProxy = gUsrPxyDef;
00786 UsrProxy += "u<uid>";
00787 }
00788 DEBUG("Template for exported proxy files: "<<UsrProxy);
00789 }
00790
00791
00792
00793
00794 Parms = new char[cryptlist.length()+3+12+certcalist.length()+5];
00795 if (Parms) {
00796 sprintf(Parms,"v:%d,c:%s,ca:%s",
00797 Version,cryptlist.c_str(),certcalist.c_str());
00798 } else {
00799 ErrF(erp,kGSErrInit,"no system resources for 'Parms'");
00800 PRINT(erp->getErrText());
00801 }
00802
00803
00804 DEBUG("available crypto modules: "<<cryptlist);
00805 DEBUG("issuer CAs of server certs (hashes): "<<certcalist);
00806 }
00807
00808
00809
00810 if (!Server) {
00811
00812
00813
00814 if (cacheCA.Init(100) != 0) {
00815 ErrF(erp,kGSErrError,"problems init cache for CA info");
00816 PRINT(erp->getErrText());
00817 return Parms;
00818 }
00819
00820
00821
00822 if (cachePxy.Init(2) != 0) {
00823 ErrF(erp,kGSErrError,"problems init cache for proxies");
00824 PRINT(erp->getErrText());
00825 return Parms;
00826 }
00827
00828 struct passwd *pw = getpwuid(getuid());
00829 if (!pw) {
00830 DEBUG("WARNING: cannot get user information (uid:"<<getuid()<<")");
00831 }
00832
00833
00834 UsrProxy = gUsrPxyDef;
00835 if (opt.proxy) {
00836 String TmpProxy = opt.proxy;
00837 if (XrdSutExpand(TmpProxy) == 0) {
00838 UsrProxy = TmpProxy;
00839 } else {
00840 PRINT("Could not expand: "<<opt.proxy<<": use default");
00841 }
00842 } else {
00843 if (pw)
00844 UsrProxy += (int)(pw->pw_uid);
00845 }
00846
00847 if (opt.cert) {
00848 String TmpCert = opt.cert;
00849 if (XrdSutExpand(TmpCert) == 0) {
00850 UsrCert = TmpCert;
00851 } else {
00852 PRINT("Could not expand: "<<opt.cert<<": use default");
00853 }
00854 } else {
00855 if (pw)
00856 UsrCert.insert(XrdSutHome(),0);
00857 }
00858
00859 if (opt.key) {
00860 String TmpKey = opt.key;
00861 if (XrdSutExpand(TmpKey) == 0) {
00862 UsrKey = TmpKey;
00863 } else {
00864 PRINT("Could not expand: "<<opt.key<<": use default");
00865 }
00866 } else {
00867 if (pw)
00868 UsrKey.insert(XrdSutHome(),0);
00869 }
00870
00871 if (opt.valid)
00872 PxyValid = opt.valid;
00873
00874 if (opt.deplen != DepLength)
00875 DepLength = opt.deplen;
00876
00877 if (opt.bits > DefBits)
00878 DefBits = opt.bits;
00879
00880
00881 if (opt.dlgpxy == 1)
00882 PxyReqOpts |= kOptsDlgPxy;
00883 if (opt.dlgpxy == 2)
00884 PxyReqOpts |= kOptsFwdPxy;
00885 if (opt.sigpxy > 0 || opt.dlgpxy == 1)
00886 PxyReqOpts |= kOptsSigReq;
00887
00888
00889
00890 if (opt.srvnames)
00891 SrvAllowedNames = opt.srvnames;
00892
00893
00894 DEBUG("using certificate file: "<<UsrCert);
00895 DEBUG("using private key file: "<<UsrKey);
00896 DEBUG("proxy: file: "<<UsrProxy);
00897 DEBUG("proxy: validity: "<<PxyValid);
00898 DEBUG("proxy: depth of signature path: "<<DepLength);
00899 DEBUG("proxy: bits in key: "<<DefBits);
00900 DEBUG("server cert: allowed names: "<<SrvAllowedNames);
00901
00902
00903 Parms = (char *)"";
00904 }
00905
00906
00907 return Parms;
00908 }
00909
00910
00911
00912
00913 void XrdSecProtocolgsi::Delete()
00914 {
00915
00916 SafeFree(Entity.name);
00917 SafeFree(Entity.host);
00918 SafeFree(Entity.vorg);
00919 SafeFree(Entity.role);
00920 SafeFree(Entity.grps);
00921 SafeFree(Entity.endorsements);
00922
00923 SafeDelete(hs);
00924
00925 SafeDelete(sessionKey);
00926 SafeDelete(bucketKey);
00927 SafeDelete(sessionMD);
00928 SafeDelete(sessionKsig);
00929 SafeDelete(sessionKver);
00930 SafeDelete(proxyChain);
00931
00932 delete this;
00933 }
00934
00935
00936
00937
00938
00939
00940
00941 int XrdSecProtocolgsi::Encrypt(const char *inbuf,
00942 int inlen,
00943 XrdSecBuffer **outbuf)
00944 {
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954 EPNAME("Encrypt");
00955
00956
00957 if (!sessionKey)
00958 return -ENOENT;
00959
00960
00961 if (!inbuf || inlen <= 0 || !outbuf)
00962 return -EINVAL;
00963
00964
00965 char *buf = (char *)malloc(sessionKey->EncOutLength(inlen));
00966 if (!buf)
00967 return -ENOMEM;
00968
00969
00970 int len = sessionKey->Encrypt(inbuf, inlen, buf);
00971 if (len <= 0) {
00972 SafeFree(buf);
00973 return -EINVAL;
00974 }
00975
00976
00977 *outbuf = new XrdSecBuffer(buf, len);
00978
00979
00980 DEBUG("encrypted buffer has "<<len<<" bytes");
00981 return 0;
00982 }
00983
00984
00985 int XrdSecProtocolgsi::Decrypt(const char *inbuf,
00986 int inlen,
00987 XrdSecBuffer **outbuf)
00988 {
00989
00990
00991
00992
00993 EPNAME("Decrypt");
00994
00995
00996 if (!sessionKey)
00997 return -ENOENT;
00998
00999
01000 if (!inbuf || inlen <= 0 || !outbuf)
01001 return -EINVAL;
01002
01003
01004 char *buf = (char *)malloc(sessionKey->DecOutLength(inlen));
01005 if (!buf)
01006 return -ENOMEM;
01007
01008
01009 int len = sessionKey->Decrypt(inbuf, inlen, buf);
01010 if (len <= 0) {
01011 SafeFree(buf);
01012 return -EINVAL;
01013 }
01014
01015
01016 *outbuf = new XrdSecBuffer(buf, len);
01017
01018
01019 DEBUG("decrypted buffer has "<<len<<" bytes");
01020 return 0;
01021 }
01022
01023
01024 int XrdSecProtocolgsi::Sign(const char *inbuf,
01025 int inlen,
01026 XrdSecBuffer **outbuf)
01027 {
01028
01029
01030
01031
01032
01033
01034 EPNAME("Sign");
01035
01036
01037 if (!sessionKsig || !sessionMD)
01038 return -ENOENT;
01039
01040
01041 if (!inbuf || inlen <= 0 || !outbuf)
01042 return -EINVAL;
01043
01044
01045 sessionMD->Reset(0);
01046
01047
01048 sessionMD->Update(inbuf, inlen);
01049 sessionMD->Final();
01050
01051
01052 int lmax = sessionKsig->GetOutlen(sessionMD->Length());
01053 char *buf = (char *)malloc(lmax);
01054 if (!buf)
01055 return -ENOMEM;
01056
01057
01058 int len = sessionKsig->EncryptPrivate(sessionMD->Buffer(),
01059 sessionMD->Length(),
01060 buf, lmax);
01061 if (len <= 0) {
01062 SafeFree(buf);
01063 return -EINVAL;
01064 }
01065
01066
01067 *outbuf = new XrdSecBuffer(buf, len);
01068
01069
01070 DEBUG("signature has "<<len<<" bytes");
01071 return 0;
01072 }
01073
01074
01075 int XrdSecProtocolgsi::Verify(const char *inbuf,
01076 int inlen,
01077 const char *sigbuf,
01078 int siglen)
01079 {
01080
01081
01082
01083
01084
01085
01086 EPNAME("Verify");
01087
01088
01089 if (!sessionKver || !sessionMD)
01090 return -ENOENT;
01091
01092
01093 if (!inbuf || inlen <= 0 || !sigbuf || siglen <= 0)
01094 return -EINVAL;
01095
01096
01097 sessionMD->Reset(0);
01098
01099
01100 sessionMD->Update(inbuf, inlen);
01101 sessionMD->Final();
01102
01103
01104 int lmax = sessionKver->GetOutlen(siglen);
01105 char *buf = new char[lmax];
01106 if (!buf)
01107 return -ENOMEM;
01108
01109
01110 int len = sessionKver->DecryptPublic(sigbuf, siglen, buf, lmax);
01111 if (len <= 0) {
01112 delete[] buf;
01113 return -EINVAL;
01114 }
01115
01116
01117 bool bad = 1;
01118 if (len == sessionMD->Length()) {
01119 if (!strncmp(buf, sessionMD->Buffer(), len)) {
01120
01121 bad = 0;
01122 DEBUG("signature successfully verified");
01123 }
01124 }
01125
01126
01127 if (buf) delete[] buf;
01128
01129
01130 return ((bad) ? 1 : 0);
01131 }
01132
01133
01134 int XrdSecProtocolgsi::getKey(char *kbuf, int klen)
01135 {
01136
01137
01138
01139
01140
01141
01142
01143 EPNAME("getKey");
01144
01145
01146 if (!bucketKey) {
01147
01148
01149 if (!sessionKey)
01150
01151 return -ENOENT;
01152
01153 bucketKey = sessionKey->AsBucket();
01154 }
01155
01156
01157 if (bucketKey) {
01158
01159 if (kbuf == 0)
01160 return bucketKey->size;
01161
01162
01163 if (klen < bucketKey->size)
01164
01165 return -EOVERFLOW;
01166
01167
01168 memcpy(kbuf, bucketKey->buffer, bucketKey->size);
01169
01170
01171 DEBUG("session key exported");
01172 return bucketKey->size;
01173 }
01174
01175
01176 return -ENOMEM;
01177 }
01178
01179
01180 int XrdSecProtocolgsi::setKey(char *kbuf, int klen)
01181 {
01182
01183
01184
01185
01186
01187 EPNAME("setKey");
01188
01189
01190 if (!kbuf || klen <= 0)
01191
01192 return -EINVAL;
01193
01194 if (!sessionCF)
01195
01196 return -ENOENT;
01197
01198
01199 XrdSutBucket *bck = new XrdSutBucket();
01200 if (!bck)
01201
01202 return -ENOMEM;
01203
01204 bck->SetBuf(kbuf, klen);
01205
01206
01207 XrdCryptoCipher *newKey = sessionCF->Cipher(bck);
01208 if (!newKey) {
01209 SafeDelete(bck);
01210 return -ENOMEM;
01211 }
01212
01213
01214 SafeDelete(sessionKey);
01215
01216
01217 sessionKey = newKey;
01218
01219
01220 SafeDelete(bck);
01221
01222
01223 DEBUG("session key update");
01224 return 0;
01225 }
01226
01227
01228
01229
01230
01231
01232
01233
01234 XrdSecCredentials *XrdSecProtocolgsi::getCredentials(XrdSecParameters *parm,
01235 XrdOucErrInfo *ei)
01236 {
01237
01238
01239 EPNAME("getCredentials");
01240
01241
01242
01243 if (srvMode) {
01244 XrdSecCredentials *creds = 0;
01245 if (proxyChain) {
01246
01247 XrdCryptoX509ExportChain_t ExportChain = sessionCF->X509ExportChain();
01248 if (ExportChain) {
01249 XrdSutBucket *bck = (*ExportChain)(proxyChain, 1);
01250 if (bck) {
01251
01252
01253 char *nbuf = (char *) malloc(bck->size);
01254 if (nbuf) {
01255 memcpy(nbuf, bck->buffer, bck->size);
01256
01257 creds = new XrdSecCredentials(nbuf, bck->size);
01258 }
01259 delete bck;
01260 }
01261 }
01262 }
01263 return creds;
01264 }
01265
01266
01267 if (!hs)
01268 return ErrC(ei,0,0,0,kGSErrError,
01269 "handshake var container missing","getCredentials");
01270
01271
01272 if ((!parm && !hs->Parms) || (parm && (!(parm->buffer) || parm->size <= 0))) {
01273 if (hs->Iter == 0)
01274 return ErrC(ei,0,0,0,kGSErrNoBuffer,"missing parameters","getCredentials");
01275 else
01276 return (XrdSecCredentials *)0;
01277 }
01278
01279
01280 (hs->Iter)++;
01281
01282
01283 hs->TimeStamp = time(0);
01284
01285
01286 int step = 0;
01287 int nextstep = 0;
01288 const char *stepstr = 0;
01289 char *bpub = 0;
01290 int lpub = 0;
01291 String CryptList = "";
01292 String Host = "";
01293 String RemID = "";
01294 String Emsg;
01295 String specID = "";
01296 String issuerHash = "";
01297
01298 XrdSutBuffer *bpar = 0;
01299 XrdSutBuffer *bmai = 0;
01300
01301
01302
01303 bpar = hs->Parms;
01304 if (!bpar && !(bpar = new XrdSutBuffer((const char *)parm->buffer,parm->size)))
01305 return ErrC(ei,0,0,0,kGSErrDecodeBuffer,"global",stepstr);
01306
01307 hs->Parms = 0;
01308
01309
01310 if (strcmp(bpar->GetProtocol(),XrdSecPROTOIDENT))
01311 return ErrC(ei,bpar,bmai,0,kGSErrBadProtocol,stepstr);
01312
01313
01314 if (!(step = bpar->GetStep())) {
01315
01316 step = kXGS_init;
01317 bpar->SetStep(step);
01318 }
01319 stepstr = ServerStepStr(step);
01320
01321 if (QTRACE(Authen)) {
01322 XrdOucString msg("IN: ");
01323 msg += stepstr;
01324 bpar->Dump(msg.c_str());
01325 }
01326
01327
01328 if (ParseClientInput(bpar, &bmai, Emsg) == -1) {
01329 DEBUG(Emsg<<" CF: "<<sessionCF);
01330 return ErrC(ei,bpar,bmai,0,kGSErrParseBuffer,Emsg.c_str(),stepstr);
01331 }
01332
01333 if (QTRACE(Authen)) {
01334 if (bmai)
01335 bmai->Dump("IN: main");
01336 }
01337
01338
01339 DEBUG("version run by server: "<< hs->RemVers);
01340
01341
01342 if (!CheckRtag(bmai, Emsg))
01343 return ErrC(ei,bpar,bmai,0,kGSErrBadRndmTag,Emsg.c_str(),stepstr);
01344
01345
01346 String user(Entity.name);
01347 if (user.length() <= 0) user = getenv("XrdSecUSER");
01348
01349
01350 nextstep = kXGC_none;
01351
01352 XrdCryptoX509 *c = 0;
01353
01354 switch (step) {
01355
01356 case kXGS_init:
01357
01358
01359
01360 if (bpar->AddBucket(hs->CryptoMod,kXRS_cryptomod) != 0)
01361 return ErrC(ei,bpar,bmai,0,
01362 kGSErrCreateBucket,XrdSutBuckStr(kXRS_cryptomod),stepstr);
01363
01364
01365 if (bpar->MarshalBucket(kXRS_version,(kXR_int32)(Version)) != 0)
01366 return ErrC(ei,bpar,bmai,0, kGSErrCreateBucket,
01367 XrdSutBuckStr(kXRS_version),"global",stepstr);
01368
01369
01370 c = hs->PxyChain->Begin();
01371 if (c->type == XrdCryptoX509::kCA)
01372 issuerHash = c->SubjectHash();
01373 else
01374 issuerHash = c->IssuerHash();
01375 while ((c = hs->PxyChain->Next()) != 0) {
01376 if (c->type != XrdCryptoX509::kCA)
01377 break;
01378 issuerHash = c->SubjectHash();
01379 }
01380 DEBUG("Client issuer hash: " << issuerHash);
01381 if (bpar->AddBucket(issuerHash,kXRS_issuer_hash) != 0)
01382 return ErrC(ei,bpar,bmai,0, kGSErrCreateBucket,
01383 XrdSutBuckStr(kXRS_issuer_hash),stepstr);
01384
01385
01386 if (hs->RemVers >= 10100) {
01387 if (bpar->MarshalBucket(kXRS_clnt_opts,(kXR_int32)(hs->Options)) != 0)
01388 return ErrC(ei,bpar,bmai,0, kGSErrCreateBucket,
01389 XrdSutBuckStr(kXRS_clnt_opts),"global",stepstr);
01390 }
01391
01392
01393 nextstep = kXGC_certreq;
01394 break;
01395
01396 case kXGS_cert:
01397
01398
01399 if (!(sessionKey))
01400 return ErrC(ei,bpar,bmai,0,
01401 kGSErrNoCipher,"session cipher",stepstr);
01402
01403
01404
01405 if (!(bpub = sessionKey->Public(lpub)))
01406 return ErrC(ei,bpar,bmai,0,
01407 kGSErrNoPublic,"session",stepstr);
01408
01409
01410 if (bpar->UpdateBucket(bpub,lpub,kXRS_puk) != 0)
01411 return ErrC(ei,bpar,bmai,0, kGSErrAddBucket,
01412 XrdSutBuckStr(kXRS_puk),"global",stepstr);
01413
01414
01415 bmai->AddBucket(hs->Cbck);
01416
01417
01418 if (user.length() > 0) {
01419 if (bmai->AddBucket(user, kXRS_user) != 0)
01420 return ErrC(ei,bpar,bmai,0, kGSErrCreateBucket,
01421 XrdSutBuckStr(kXRS_user),stepstr);
01422 }
01423
01424 nextstep = kXGC_cert;
01425 break;
01426
01427 case kXGS_pxyreq:
01428
01429
01430 if (Emsg.length() > 0) {
01431 if (bmai->AddBucket(Emsg,kXRS_message) != 0)
01432 return ErrC(ei,bpar,bmai,0, kGSErrCreateBucket,
01433 XrdSutBuckStr(kXRS_message),stepstr);
01434 }
01435
01436
01437 if (user.length() > 0) {
01438 if (bmai->AddBucket(user, kXRS_user) != 0)
01439 return ErrC(ei,bpar,bmai,0, kGSErrCreateBucket,
01440 XrdSutBuckStr(kXRS_user),stepstr);
01441 }
01442
01443
01444 nextstep = kXGC_sigpxy;
01445 break;
01446
01447 default:
01448 return ErrC(ei,bpar,bmai,0, kGSErrBadOpt,stepstr);
01449 }
01450
01451
01452
01453 if (AddSerialized('c', nextstep, hs->ID,
01454 bpar, bmai, kXRS_main, sessionKey) != 0) {
01455
01456 bmai->Remove(hs->Cbck);
01457 return ErrC(ei,bpar,bmai,0,
01458 kGSErrSerialBuffer,"main",stepstr);
01459 }
01460
01461
01462 char *bser = 0;
01463 int nser = bpar->Serialized(&bser,'f');
01464
01465 if (QTRACE(Authen)) {
01466 XrdOucString msg("OUT: ");
01467 msg += ClientStepStr(bpar->GetStep());
01468 bpar->Dump(msg.c_str());
01469 msg.replace(ClientStepStr(bpar->GetStep()), "main");
01470 bmai->Dump(msg.c_str());
01471 }
01472
01473
01474 bmai->Remove(hs->Cbck);
01475
01476
01477 REL2(bpar,bmai);
01478
01479
01480 if (nser > 0) {
01481 DEBUG("returned " << nser <<" bytes of credentials");
01482 return new XrdSecCredentials(bser, nser);
01483 } else {
01484 DEBUG("problems with final serialization");
01485 return (XrdSecCredentials *)0;
01486 }
01487 }
01488
01489
01490
01491
01492
01493
01494
01495
01496 int XrdSecProtocolgsi::Authenticate(XrdSecCredentials *cred,
01497 XrdSecParameters **parms,
01498 XrdOucErrInfo *ei)
01499 {
01500
01501
01502
01503 EPNAME("Authenticate");
01504
01505
01506
01507 if (cred->size <= (int)XrdSecPROTOIDLEN || !cred->buffer) {
01508 strncpy(Entity.prot, "host", sizeof(Entity.prot));
01509 return 0;
01510 }
01511
01512
01513 if (!hs)
01514 return ErrS(Entity.tident,ei,0,0,0,kGSErrError,
01515 "handshake var container missing",
01516 "protocol initialization problems");
01517
01518
01519 hs->TimeStamp = time(0);
01520
01521
01522
01523 if (hs->ID.length() <= 0)
01524 hs->ID = Entity.tident;
01525 DEBUG("handshaking ID: " << hs->ID);
01526
01527
01528 int kS_rc = kgST_more;
01529 int step = 0;
01530 int nextstep = 0;
01531 char *bpub = 0;
01532 int lpub = 0;
01533 const char *stepstr = 0;
01534 String Message;
01535 String CryptList;
01536 String Host;
01537 String SrvPuKExp;
01538 String Salt;
01539 String RndmTag;
01540 String ClntMsg(256);
01541
01542 XrdSutBuffer *bpar = 0;
01543 XrdSutBuffer *bmai = 0;
01544
01545
01546
01547 if (!(bpar = new XrdSutBuffer((const char *)cred->buffer,cred->size)))
01548 return ErrS(hs->ID,ei,0,0,0,kGSErrDecodeBuffer,"global",stepstr);
01549
01550
01551 if (strcmp(bpar->GetProtocol(),XrdSecPROTOIDENT))
01552 return ErrS(hs->ID,ei,bpar,bmai,0,kGSErrBadProtocol,stepstr);
01553
01554
01555 step = bpar->GetStep();
01556 stepstr = ClientStepStr(step);
01557
01558 if (QTRACE(Authen)) {
01559 XrdOucString msg("IN: ");
01560 msg += stepstr;
01561 bpar->Dump(msg.c_str());
01562 }
01563
01564
01565 if (ParseServerInput(bpar, &bmai, ClntMsg) == -1) {
01566 DEBUG(ClntMsg);
01567 return ErrS(hs->ID,ei,bpar,bmai,0,kGSErrParseBuffer,ClntMsg.c_str(),stepstr);
01568 }
01569
01570
01571 DEBUG("version run by client: "<< hs->RemVers);
01572 DEBUG("options req by client: "<< hs->Options);
01573
01574
01575 if (QTRACE(Authen)) {
01576 if (bmai)
01577 bmai->Dump("IN: main");
01578 }
01579
01580
01581 if (!CheckRtag(bmai, ClntMsg))
01582 return ErrS(hs->ID,ei,bpar,bmai,0,kGSErrBadRndmTag,stepstr,ClntMsg.c_str());
01583
01584
01585 switch (step) {
01586
01587 case kXGC_certreq:
01588
01589
01590
01591
01592 if (!(bpub = hs->Rcip->Public(lpub)))
01593 return ErrS(hs->ID,ei,bpar,bmai,0, kGSErrNoPublic,
01594 "session",stepstr);
01595
01596
01597 if (bpar->AddBucket(bpub,lpub,kXRS_puk) != 0)
01598 return ErrS(hs->ID,ei,bpar,bmai,0, kGSErrAddBucket,
01599 "main",stepstr);
01600
01601
01602 if (bpar->AddBucket(DefCipher,kXRS_cipher_alg) != 0)
01603 return ErrS(hs->ID,ei,bpar,bmai,0,
01604 kGSErrAddBucket,XrdSutBuckStr(kXRS_cipher_alg),stepstr);
01605
01606
01607 if (bpar->AddBucket(DefMD,kXRS_md_alg) != 0)
01608 return ErrS(hs->ID,ei,bpar,bmai,0,
01609 kGSErrAddBucket,XrdSutBuckStr(kXRS_md_alg),stepstr);
01610
01611
01612 bpar->AddBucket(hs->Cbck);
01613
01614
01615 nextstep = kXGS_cert;
01616 break;
01617
01618 case kXGC_cert:
01619
01620
01621
01622 kS_rc = kgST_ok;
01623 nextstep = kXGS_none;
01624
01625 if (GMAPOpt > 0) {
01626
01627 String name;
01628 QueryGMAP(hs->Chain, hs->TimeStamp, name);
01629 DEBUG("username(s) associated with this DN: "<<name);
01630 if (name.length() <= 0) {
01631
01632 if (GMAPOpt == 2) {
01633
01634 kS_rc = kgST_error;
01635 PRINT("ERROR: grid map required, but lookup failed - failure");
01636 break;
01637 } else {
01638 DEBUG("WARNING: grid map lookup failed - use DN as name");
01639 }
01640 } else {
01641
01642
01643 XrdSutBucket *bck = 0;
01644 String user;
01645 if ((bck = bmai->GetBucket(kXRS_user))) {
01646 bck->ToString(user);
01647 bmai->Deactivate(kXRS_user);
01648 }
01649 DEBUG("target user: "<<user);
01650 if (user.length() > 0) {
01651
01652 String u;
01653 int from = 0;
01654 bool ok = 0;
01655 while ((from = name.tokenize(u, from, ',')) != -1) {
01656 if (user == u) { ok = 1; break; }
01657 }
01658 if (ok) {
01659 name = u;
01660 DEBUG("grid map: requested user is authorized: name is '"<<name<<"'");
01661 } else {
01662
01663
01664 if (name.find(',') != STR_NPOS) name.erase(name.find(','));
01665 PRINT("WARNING: grid map lookup ok, but the requested user is not"
01666 " authorized ("<<user<<"). Instead, mapped as " << name << ".");
01667 }
01668 } else {
01669
01670 if (name.find(',') != STR_NPOS) name.erase(name.find(','));
01671 DEBUG("grid map lookup successful: name is '"<<name<<"'");
01672 }
01673 Entity.name = strdup(name.c_str());
01674 }
01675 }
01676
01677 if (!Entity.name || (strlen(Entity.name) <= 0)) {
01678
01679 if (hs->Chain->EEChash()) {
01680 Entity.name = strdup(hs->Chain->EEChash());
01681 } else {
01682 DEBUG("WARNING: DN missing: corruption? ");
01683 }
01684 }
01685
01686
01687 if (AuthzPxy == 1) {
01688
01689 XrdSutBucket *b = XrdCryptosslX509ExportChain(hs->Chain, true);
01690 XrdOucString s;
01691 b->ToString(s);
01692 Entity.endorsements = strdup(s.c_str());
01693 delete b;
01694 }
01695
01696 if (hs->RemVers >= 10100) {
01697 if (hs->PxyChain) {
01698
01699 kS_rc = kgST_more;
01700 nextstep = kXGS_pxyreq;
01701 }
01702 }
01703
01704 break;
01705
01706 case kXGC_sigpxy:
01707
01708
01709 kS_rc = kgST_ok;
01710 nextstep = kXGS_none;
01711
01712
01713 if (ClntMsg.length() > 0) {
01714 PRINT(ClntMsg);
01715 }
01716 break;
01717
01718 default:
01719 return ErrS(hs->ID,ei,bpar,bmai,0, kGSErrBadOpt, stepstr);
01720 }
01721
01722 if (kS_rc == kgST_more) {
01723
01724
01725 if (ClntMsg.length() > 0)
01726 if (bmai->AddBucket(ClntMsg,kXRS_message) != 0) {
01727 DEBUG("problems adding bucket with message for client");
01728 }
01729
01730
01731 if (AddSerialized('s', nextstep, hs->ID,
01732 bpar, bmai, kXRS_main, sessionKey) != 0) {
01733
01734 bpar->Remove(hs->Cbck);
01735 return ErrS(hs->ID,ei,bpar,bmai,0, kGSErrSerialBuffer,
01736 "main / session cipher",stepstr);
01737 }
01738
01739
01740 char *bser = 0;
01741 int nser = bpar->Serialized(&bser,'f');
01742
01743
01744 if (QTRACE(Authen)) {
01745 XrdOucString msg("OUT: ");
01746 msg += ServerStepStr(bpar->GetStep());
01747 bpar->Dump(msg.c_str());
01748 msg.replace(ServerStepStr(bpar->GetStep()), "main");
01749 bmai->Dump(msg.c_str());
01750 }
01751
01752
01753 *parms = new XrdSecParameters(bser,nser);
01754
01755
01756 bpar->Remove(hs->Cbck);
01757
01758 } else {
01759
01760
01761 bpar->Remove(hs->Cbck);
01762
01763
01764 SafeDelete(hs);
01765 }
01766
01767
01768 REL2(bpar,bmai);
01769
01770
01771 return kS_rc;
01772 }
01773
01774
01775
01776
01777
01778 extern "C"
01779 {
01780 char *XrdSecProtocolgsiInit(const char mode,
01781 const char *parms, XrdOucErrInfo *erp)
01782 {
01783
01784
01785
01786
01787
01788 gsiOptions opts;
01789 char *rc = (char *)"";
01790 char *cenv = 0;
01791
01792
01793
01794 if (mode == 'c') {
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842 opts.mode = mode;
01843
01844 cenv = getenv("XrdSecDEBUG");
01845 if (cenv)
01846 if (cenv[0] >= 49 && cenv[0] <= 51) opts.debug = atoi(cenv);
01847
01848
01849 cenv = (getenv("XrdSecGSICADIR") ? getenv("XrdSecGSICADIR")
01850 : getenv("X509_CERT_DIR"));
01851 if (cenv)
01852 opts.certdir = strdup(cenv);
01853
01854
01855 cenv = (getenv("XrdSecGSICRLDIR") ? getenv("XrdSecGSICRLDIR")
01856 : getenv("X509_CERT_DIR"));
01857 if (cenv)
01858 opts.crldir = strdup(cenv);
01859
01860
01861 cenv = getenv("XrdSecGSICRLEXT");
01862 if (cenv)
01863 opts.crlext = strdup(cenv);
01864
01865
01866 cenv = (getenv("XrdSecGSIUSERCERT") ? getenv("XrdSecGSIUSERCERT")
01867 : getenv("X509_USER_CERT"));
01868 if (cenv)
01869 opts.cert = strdup(cenv);
01870
01871
01872 cenv = (getenv("XrdSecGSIUSERKEY") ? getenv("XrdSecGSIUSERKEY")
01873 : getenv("X509_USER_KEY"));
01874 if (cenv)
01875 opts.key = strdup(cenv);
01876
01877
01878 cenv = (getenv("XrdSecGSIUSERPROXY") ? getenv("XrdSecGSIUSERPROXY")
01879 : getenv("X509_USER_PROXY"));
01880 if (cenv)
01881 opts.proxy = strdup(cenv);
01882
01883
01884 cenv = getenv("XrdSecGSIPROXYVALID");
01885 if (cenv)
01886 opts.valid = strdup(cenv);
01887
01888
01889 cenv = getenv("XrdSecGSIPROXYDEPLEN");
01890 if (cenv)
01891 opts.deplen = atoi(cenv);
01892
01893
01894 cenv = getenv("XrdSecGSIPROXYKEYBITS");
01895 if (cenv)
01896 opts.bits = atoi(cenv);
01897
01898
01899 cenv = getenv("XrdSecGSICACHECK");
01900 if (cenv)
01901 opts.ca = atoi(cenv);
01902
01903
01904 cenv = getenv("XrdSecGSICRLCHECK");
01905 if (cenv)
01906 opts.crl = atoi(cenv);
01907
01908
01909 cenv = getenv("XrdSecGSIDELEGPROXY");
01910 if (cenv)
01911 opts.dlgpxy = atoi(cenv);
01912
01913
01914 cenv = getenv("XrdSecGSISIGNPROXY");
01915 if (cenv)
01916 opts.sigpxy = atoi(cenv);
01917
01918
01919 cenv = getenv("XrdSecGSISRVNAMES");
01920 if (cenv)
01921 opts.srvnames = strdup(cenv);
01922
01923
01924
01925 rc = XrdSecProtocolgsi::Init(opts,erp);
01926
01927
01928 SafeFree(opts.certdir);
01929 SafeFree(opts.crldir);
01930 SafeFree(opts.crlext);
01931 SafeFree(opts.cert);
01932 SafeFree(opts.key);
01933 SafeFree(opts.proxy);
01934 SafeFree(opts.valid);
01935 SafeFree(opts.srvnames);
01936
01937
01938 return rc;
01939 }
01940
01941
01942 cenv = getenv("XRDDEBUG");
01943 if (cenv && !strcmp(cenv,"1")) opts.debug = 1;
01944
01945
01946
01947 if (parms) {
01948
01949
01950 char parmbuff[1024];
01951 strlcpy(parmbuff, parms, sizeof(parmbuff));
01952
01953
01954 XrdOucTokenizer inParms(parmbuff);
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980 int debug = -1;
01981 String clist = "";
01982 String certdir = "";
01983 String crldir = "";
01984 String crlext = "";
01985 String cert = "";
01986 String key = "";
01987 String cipher = "";
01988 String md = "";
01989 String gridmap = "";
01990 String gmapfun = "";
01991 String gmapfunparms = "";
01992 String authzfun = "";
01993 String authzfunparms = "";
01994 String exppxy = "";
01995 int ca = 1;
01996 int crl = 1;
01997 int ogmap = 1;
01998 int gmapto = -1;
01999 int dlgpxy = 0;
02000 int authzpxy = 0;
02001 char *op = 0;
02002 while (inParms.GetLine()) {
02003 while ((op = inParms.GetToken())) {
02004 if (!strncmp(op, "-d:",3)) {
02005 debug = atoi(op+3);
02006 } else if (!strncmp(op, "-c:",3)) {
02007 clist = (const char *)(op+3);
02008 } else if (!strncmp(op, "-certdir:",9)) {
02009 certdir = (const char *)(op+9);
02010 } else if (!strncmp(op, "-crldir:",8)) {
02011 crldir = (const char *)(op+8);
02012 } else if (!strncmp(op, "-crlext:",8)) {
02013 crlext = (const char *)(op+8);
02014 } else if (!strncmp(op, "-cert:",6)) {
02015 cert = (const char *)(op+6);
02016 } else if (!strncmp(op, "-key:",5)) {
02017 key = (const char *)(op+5);
02018 } else if (!strncmp(op, "-cipher:",8)) {
02019 cipher = (const char *)(op+8);
02020 } else if (!strncmp(op, "-md:",4)) {
02021 md = (const char *)(op+4);
02022 } else if (!strncmp(op, "-ca:",4)) {
02023 ca = atoi(op+4);
02024 } else if (!strncmp(op, "-crl:",5)) {
02025 crl = atoi(op+5);
02026 } else if (!strncmp(op, "-gmapopt:",9)) {
02027 ogmap = atoi(op+9);
02028 } else if (!strncmp(op, "-gridmap:",9)) {
02029 gridmap = (const char *)(op+9);
02030 } else if (!strncmp(op, "-gmapfun:",9)) {
02031 gmapfun = (const char *)(op+9);
02032 } else if (!strncmp(op, "-gmapfunparms:",14)) {
02033 gmapfunparms = (const char *)(op+14);
02034 } else if (!strncmp(op, "-authzfun:",10)) {
02035 authzfun = (const char *)(op+10);
02036 } else if (!strncmp(op, "-authzfunparms:",15)) {
02037 authzfunparms = (const char *)(op+15);
02038 } else if (!strncmp(op, "-gmapto:",8)) {
02039 gmapto = atoi(op+8);
02040 } else if (!strncmp(op, "-dlgpxy:",8)) {
02041 dlgpxy = atoi(op+8);
02042 } else if (!strncmp(op, "-exppxy:",8)) {
02043 exppxy = (const char *)(op+8);
02044 } else if (!strncmp(op, "-authzpxy",9)) {
02045 authzpxy = 1;
02046 }
02047 }
02048 }
02049
02050
02051
02052 opts.debug = (debug > -1) ? debug : opts.debug;
02053 opts.mode = 's';
02054 opts.ca = ca;
02055 opts.crl = crl;
02056 opts.ogmap = ogmap;
02057 opts.gmapto = gmapto;
02058 opts.dlgpxy = dlgpxy;
02059 opts.authzpxy = authzpxy;
02060 if (clist.length() > 0)
02061 opts.clist = (char *)clist.c_str();
02062 if (certdir.length() > 0)
02063 opts.certdir = (char *)certdir.c_str();
02064 if (crldir.length() > 0)
02065 opts.crldir = (char *)crldir.c_str();
02066 if (crlext.length() > 0)
02067 opts.crlext = (char *)crlext.c_str();
02068 if (cert.length() > 0)
02069 opts.cert = (char *)cert.c_str();
02070 if (key.length() > 0)
02071 opts.key = (char *)key.c_str();
02072 if (cipher.length() > 0)
02073 opts.cipher = (char *)cipher.c_str();
02074 if (md.length() > 0)
02075 opts.md = (char *)md.c_str();
02076 if (gridmap.length() > 0)
02077 opts.gridmap = (char *)gridmap.c_str();
02078 if (gmapfun.length() > 0)
02079 opts.gmapfun = (char *)gmapfun.c_str();
02080 if (gmapfunparms.length() > 0)
02081 opts.gmapfunparms = (char *)gmapfunparms.c_str();
02082 if (authzfun.length() > 0)
02083 opts.authzfun = (char *)authzfun.c_str();
02084 if (authzfunparms.length() > 0)
02085 opts.authzfunparms = (char *)authzfunparms.c_str();
02086 if (exppxy.length() > 0)
02087 opts.exppxy = (char *)exppxy.c_str();
02088
02089
02090 return XrdSecProtocolgsi::Init(opts,erp);
02091 }
02092
02093
02094 return XrdSecProtocolgsi::Init(opts,erp);
02095 }}
02096
02097
02098
02099
02100
02101
02102 extern "C"
02103 {
02104 XrdSecProtocol *XrdSecProtocolgsiObject(const char mode,
02105 const char *hostname,
02106 const struct sockaddr &netaddr,
02107 const char *parms,
02108 XrdOucErrInfo *erp)
02109 {
02110 XrdSecProtocolgsi *prot;
02111 int options = XrdSecNOIPCHK;
02112
02113
02114
02115 if (!(prot = new XrdSecProtocolgsi(options, hostname, &netaddr, parms))) {
02116 char *msg = (char *)"Secgsi: Insufficient memory for protocol.";
02117 if (erp)
02118 erp->setErrInfo(ENOMEM, msg);
02119 else
02120 cerr <<msg <<endl;
02121 return (XrdSecProtocol *)0;
02122 }
02123
02124
02125 if (!erp)
02126 cerr << "protocol object instantiated" << endl;
02127 return prot;
02128 }}
02129
02130
02131
02132
02133
02134
02135
02136 int XrdSecProtocolgsi::AddSerialized(char opt, kXR_int32 step, String ID,
02137 XrdSutBuffer *bls, XrdSutBuffer *buf,
02138 kXR_int32 type,
02139 XrdCryptoCipher *cip)
02140 {
02141
02142
02143
02144 EPNAME("AddSerialized");
02145
02146 if (!bls || !buf || (opt != 0 && opt != 'c' && opt != 's')) {
02147 DEBUG("invalid inputs ("
02148 <<bls<<","<<buf<<","<<opt<<")"
02149 <<" - type: "<<XrdSutBuckStr(type));
02150 return -1;
02151 }
02152
02153
02154
02155 if (step > 0) {
02156 bls->SetStep(step);
02157 buf->SetStep(step);
02158 hs->LastStep = step;
02159 }
02160
02161
02162
02163
02164 XrdSutBucket *brt = buf->GetBucket(kXRS_rtag);
02165 if (brt && sessionKsig) {
02166
02167
02168 if (sessionKsig->EncryptPrivate(*brt) <= 0) {
02169 DEBUG("error encrypting random tag");
02170 return -1;
02171 }
02172
02173
02174 brt->type = kXRS_signed_rtag;
02175 }
02176
02177
02178
02179
02180
02181 String RndmTag;
02182 XrdSutRndm::GetRndmTag(RndmTag);
02183
02184
02185 brt = 0;
02186 if (!(brt = new XrdSutBucket(RndmTag,kXRS_rtag))) {
02187 DEBUG("error creating random tag bucket");
02188 return -1;
02189 }
02190 buf->AddBucket(brt);
02191
02192
02193 if (!hs->Cref) {
02194 DEBUG("cache entry not found: protocol error");
02195 return -1;
02196 }
02197
02198
02199 hs->Cref->buf1.SetBuf(brt->buffer,brt->size);
02200 hs->Cref->mtime = (kXR_int32)hs->TimeStamp;
02201
02202
02203 char *bser = 0;
02204 int nser = buf->Serialized(&bser);
02205
02206
02207 XrdSutBucket *bck = 0;;
02208 if (!(bck = bls->GetBucket(type))) {
02209
02210 if (!(bck = new XrdSutBucket(bser,nser,type))) {
02211 DEBUG("error creating bucket "
02212 <<" - type: "<<XrdSutBuckStr(type));
02213 return -1;
02214 }
02215
02216
02217 bls->AddBucket(bck);
02218 } else {
02219 bck->Update(bser,nser);
02220 }
02221
02222
02223 if (cip) {
02224 if (cip->Encrypt(*bck) == 0) {
02225 DEBUG("error encrypting bucket - cipher "
02226 <<" - type: "<<XrdSutBuckStr(type));
02227 return -1;
02228 }
02229 }
02230
02231 return 0;
02232 }
02233
02234
02235 int XrdSecProtocolgsi::ParseClientInput(XrdSutBuffer *br, XrdSutBuffer **bm,
02236 String &cmsg)
02237 {
02238
02239
02240 EPNAME("ParseClientInput");
02241
02242
02243 if (!br || !bm) {
02244 DEBUG("invalid inputs ("<<br<<","<<bm<<")");
02245 cmsg = "invalid inputs";
02246 return -1;
02247 }
02248
02249
02250
02251 int step = br->GetStep();
02252
02253
02254 switch (step) {
02255 case kXGS_init:
02256
02257 if (ClientDoInit(br, bm, cmsg) != 0)
02258 return -1;
02259 break;
02260 case kXGS_cert:
02261
02262 if (ClientDoCert(br, bm, cmsg) != 0)
02263 return -1;
02264 break;
02265 case kXGS_pxyreq:
02266
02267 if (ClientDoPxyreq(br, bm, cmsg) != 0)
02268 return -1;
02269 break;
02270 default:
02271 cmsg = "protocol error: unknown action: "; cmsg += step;
02272 return -1;
02273 break;
02274 }
02275
02276
02277 return 0;
02278 }
02279
02280
02281 int XrdSecProtocolgsi::ClientDoInit(XrdSutBuffer *br, XrdSutBuffer **bm,
02282 String &emsg)
02283 {
02284
02285
02286
02287 EPNAME("ClientDoInit");
02288
02289
02290
02291 if (!((*bm) = new XrdSutBuffer(br->GetProtocol(),br->GetOptions()))) {
02292 emsg = "error instantiating main buffer";
02293 return -1;
02294 }
02295
02296
02297 String opts = br->GetOptions();
02298 int ii = opts.find("v:");
02299 if (ii >= 0) {
02300 String sver(opts,ii+2);
02301 sver.erase(sver.find(','));
02302 hs->RemVers = atoi(sver.c_str());
02303 } else {
02304 hs->RemVers = Version;
02305 emsg = "server version information not found in options:"
02306 " assume same as local";
02307 }
02308
02309
02310 if (!(hs->Cref = new XrdSutPFEntry("c"))) {
02311 emsg = "error creating cache";
02312 return -1;
02313 }
02314
02315
02316 hs->Cref->status = hs->RemVers;
02317
02318
02319 hs->Options = PxyReqOpts;
02320
02321
02322 String clist;
02323 ii = opts.find("c:");
02324 if (ii >= 0) {
02325 clist.assign(opts, ii+2);
02326 clist.erase(clist.find(','));
02327 } else {
02328 DEBUG("Crypto list missing: protocol error? (use defaults)");
02329 clist = DefCrypto;
02330 }
02331
02332 if (ParseCrypto(clist) != 0) {
02333 emsg = "cannot find / load crypto requested modules :";
02334 emsg += clist;
02335 return -1;
02336 }
02337
02338
02339 String srvca;
02340 ii = opts.find("ca:");
02341 if (ii >= 0) {
02342 srvca.assign(opts, ii+3);
02343 srvca.erase(srvca.find(','));
02344 }
02345
02346 if (ParseCAlist(srvca) != 0) {
02347 emsg = "unknown CA: cannot verify server certificate";
02348 hs->Chain = 0;
02349 return -1;
02350 }
02351
02352
02353 if (XrdSutResolve(UsrCert, Entity.host, Entity.vorg, Entity.grps, Entity.name) != 0) {
02354 DEBUG("Problems resolving templates in "<<UsrCert);
02355 return -1;
02356 }
02357 if (XrdSutResolve(UsrKey, Entity.host, Entity.vorg, Entity.grps, Entity.name) != 0) {
02358 DEBUG("Problems resolving templates in "<<UsrKey);
02359 return -1;
02360 }
02361 if (XrdSutResolve(UsrProxy, Entity.host, Entity.vorg, Entity.grps, Entity.name) != 0) {
02362 DEBUG("Problems resolving templates in "<<UsrProxy);
02363 return -1;
02364 }
02365
02366
02367 ProxyIn_t pi = {UsrCert.c_str(), UsrKey.c_str(), CAdir.c_str(),
02368 UsrProxy.c_str(), PxyValid.c_str(),
02369 DepLength, DefBits};
02370 ProxyOut_t po = {hs->PxyChain, sessionKsig, hs->Cbck };
02371 if (QueryProxy(1, &cachePxy, "Proxy:0",
02372 sessionCF, hs->TimeStamp, &pi, &po) != 0) {
02373 emsg = "error getting user proxies";
02374 hs->Chain = 0;
02375 return -1;
02376 }
02377
02378 hs->PxyChain = po.chain;
02379 hs->Cbck = po.cbck;
02380 if (!(sessionKsig = sessionCF->RSA(*(po.ksig)))) {
02381 emsg = "could not get a copy of the signing key:";
02382 hs->Chain = 0;
02383 return -1;
02384 }
02385
02386
02387 return 0;
02388 }
02389
02390
02391 int XrdSecProtocolgsi::ClientDoCert(XrdSutBuffer *br, XrdSutBuffer **bm,
02392 String &emsg)
02393 {
02394
02395
02396
02397 EPNAME("ClientDoCert");
02398 XrdSutBucket *bck = 0;
02399
02400
02401
02402 if (!hs->Cref) {
02403 emsg = "cache entry not found";
02404 hs->Chain = 0;
02405 return -1;
02406 }
02407
02408
02409 int reftime = hs->TimeStamp - TimeSkew;
02410 if (hs->Cref->mtime < reftime) {
02411 emsg = "cache entry expired";
02412
02413 SafeDelete(hs->Cref);
02414 hs->Chain = 0;
02415 return -1;
02416 }
02417
02418
02419 hs->RemVers = hs->Cref->status;
02420
02421
02422
02423 String cip = "";
02424 if ((bck = br->GetBucket(kXRS_cipher_alg))) {
02425 String ciplist;
02426 bck->ToString(ciplist);
02427
02428 int from = 0;
02429 while ((from = ciplist.tokenize(cip, from, ':')) != -1) {
02430 if (cip.length() > 0)
02431 if (sessionCF->SupportedCipher(cip.c_str()))
02432 break;
02433 cip = "";
02434 }
02435 if (cip.length() > 0)
02436
02437 br->UpdateBucket(cip, kXRS_cipher_alg);
02438 } else {
02439 DEBUG("WARNING: list of ciphers supported by server missing"
02440 " - using default");
02441 }
02442
02443
02444
02445 if (!(bck = br->GetBucket(kXRS_puk))) {
02446 emsg = "server public part for session cipher missing";
02447 hs->Chain = 0;
02448 return -1;
02449 }
02450
02451
02452 SafeDelete(sessionKey);
02453 if (!(sessionKey =
02454 sessionCF->Cipher(0,bck->buffer,bck->size,cip.c_str()))) {
02455 DEBUG("could not instantiate session cipher "
02456 "using cipher public info from server");
02457 emsg = "could not instantiate session cipher ";
02458 }
02459
02460
02461 if (!(bck = br->GetBucket(kXRS_x509))) {
02462 emsg = "server certificate missing";
02463 hs->Chain = 0;
02464 return -1;
02465 }
02466
02467
02468
02469 hs->Chain = new X509Chain(hs->Chain);
02470 if (!(hs->Chain)) {
02471 emsg = "cannot duplicate reference chain";
02472 return -1;
02473 }
02474
02475 hs->Options |= kOptsDelChn;
02476
02477
02478 XrdCryptoX509ParseBucket_t ParseBucket = sessionCF->X509ParseBucket();
02479 if (!ParseBucket) {
02480 emsg = "cannot attach to ParseBucket function!";
02481 return -1;
02482 }
02483
02484 int nci = (*ParseBucket)(bck, hs->Chain);
02485 if (nci != 1) {
02486 emsg += nci;
02487 emsg += " vs 1 expected)";
02488 return -1;
02489 }
02490
02491
02492 x509ChainVerifyOpt_t vopt = { 0, hs->TimeStamp, -1, hs->Crl};
02493 XrdCryptoX509Chain::EX509ChainErr ecode = XrdCryptoX509Chain::kNone;
02494 if (!(hs->Chain->Verify(ecode, &vopt))) {
02495 emsg = "certificate chain verification failed: ";
02496 emsg += hs->Chain->LastError();
02497 return -1;
02498 }
02499
02500
02501 if (!ServerCertNameOK(hs->Chain->End()->Subject(), emsg)) {
02502 return -1;
02503 }
02504
02505
02506 sessionKver = sessionCF->RSA(*(hs->Chain->End()->PKI()));
02507 if (!sessionKver || !sessionKver->IsValid()) {
02508 emsg = "server certificate contains an invalid key";
02509 return -1;
02510 }
02511
02512
02513 br->Deactivate(kXRS_puk);
02514 br->Deactivate(kXRS_x509);
02515
02516
02517
02518 String md = "";
02519 if ((bck = br->GetBucket(kXRS_md_alg))) {
02520 String mdlist;
02521 bck->ToString(mdlist);
02522
02523 int from = 0;
02524 while ((from = mdlist.tokenize(md, from, ':')) != -1) {
02525 if (md.length() > 0)
02526 if (sessionCF->SupportedMsgDigest(md.c_str()))
02527 break;
02528 md = "";
02529 }
02530 } else {
02531 DEBUG("WARNING: list of digests supported by server missing"
02532 " - using default");
02533 md = "md5";
02534 }
02535 if (!(sessionMD = sessionCF->MsgDigest(md.c_str()))) {
02536 emsg = "could not instantiate digest object";
02537 return -1;
02538 }
02539
02540 br->UpdateBucket(md, kXRS_md_alg);
02541
02542
02543
02544
02545 XrdSutBucket *bckm = 0;
02546 if (!(bckm = br->GetBucket(kXRS_main))) {
02547 emsg = "main buffer missing";
02548 return -1;
02549 }
02550
02551
02552
02553 if (!((*bm) = new XrdSutBuffer(bckm->buffer,bckm->size))) {
02554 emsg = "error deserializing main buffer";
02555 return -1;
02556 }
02557
02558
02559
02560 return 0;
02561 }
02562
02563
02564 int XrdSecProtocolgsi::ClientDoPxyreq(XrdSutBuffer *br, XrdSutBuffer **bm,
02565 String &emsg)
02566 {
02567
02568
02569
02570 XrdSutBucket *bck = 0;
02571
02572
02573
02574
02575 XrdSutBucket *bckm = 0;
02576 if (!(bckm = br->GetBucket(kXRS_main))) {
02577 emsg = "main buffer missing";
02578 return -1;
02579 }
02580
02581
02582 if (sessionKey) {
02583 if (!(sessionKey->Decrypt(*bckm))) {
02584 emsg = "error with session cipher";
02585 return -1;
02586 }
02587 }
02588
02589
02590
02591 if (!((*bm) = new XrdSutBuffer(bckm->buffer,bckm->size))) {
02592 emsg = "error deserializing main buffer";
02593 return -1;
02594 }
02595
02596
02597
02598 if ((hs->Options & kOptsFwdPxy)) {
02599
02600 XrdCryptoX509 *pxy = 0;
02601 XrdCryptoRSA *kpxy = 0;
02602 if (!(hs->PxyChain) ||
02603 !(pxy = hs->PxyChain->End()) || !(kpxy = pxy->PKI())) {
02604 emsg = "local proxy info missing or corrupted";
02605 return 0;
02606 }
02607
02608 String pri;
02609 if (kpxy->ExportPrivate(pri) != 0) {
02610 emsg = "problems exporting private key";
02611 return 0;
02612 }
02613
02614 if ((*bm)->AddBucket(pri, kXRS_x509) != 0) {
02615 emsg = "problem adding bucket with private key to main buffer";
02616 return 0;
02617 }
02618 } else {
02619
02620 if (!(hs->Options & kOptsSigReq)) {
02621 emsg = "Not allowed to sign proxy requests";
02622 return 0;
02623 }
02624
02625 if (!(bck = (*bm)->GetBucket(kXRS_x509_req))) {
02626 emsg = "bucket with proxy request missing";
02627 return 0;
02628 }
02629 XrdCryptoX509Req *req = sessionCF->X509Req(bck);
02630 if (!req) {
02631 emsg = "could not resolve proxy request";
02632 return 0;
02633 }
02634 req->SetVersion(hs->RemVers);
02635
02636 XrdCryptoX509 *pxy = 0;
02637 XrdCryptoRSA *kpxy = 0;
02638 if (!(hs->PxyChain) ||
02639 !(pxy = hs->PxyChain->End()) || !(kpxy = pxy->PKI())) {
02640 emsg = "local proxy info missing or corrupted";
02641 return 0;
02642 }
02643
02644 XrdCryptoX509 *npxy = 0;
02645 if (XrdSslgsiX509SignProxyReq(pxy, kpxy, req, &npxy) != 0) {
02646 emsg = "problems signing the request";
02647 return 0;
02648 }
02649
02650 if ((bck = npxy->Export())) {
02651
02652 if ((*bm)->AddBucket(bck) != 0) {
02653 emsg = "problem adding signed request to main buffer";
02654 return 0;
02655 }
02656 }
02657 }
02658
02659
02660
02661 return 0;
02662
02663 }
02664
02665
02666 int XrdSecProtocolgsi::ParseServerInput(XrdSutBuffer *br, XrdSutBuffer **bm,
02667 String &cmsg)
02668 {
02669
02670
02671
02672
02673 EPNAME("ParseServerInput");
02674
02675
02676 if (!br || !bm) {
02677 DEBUG("invalid inputs ("<<br<<","<<bm<<")");
02678 cmsg = "invalid inputs";
02679 return -1;
02680 }
02681
02682
02683
02684 int step = br->GetStep();
02685
02686
02687 switch (step) {
02688 case kXGC_certreq:
02689
02690 if (ServerDoCertreq(br, bm, cmsg) != 0)
02691 return -1;
02692 break;
02693 case kXGC_cert:
02694
02695 if (ServerDoCert(br, bm, cmsg) != 0)
02696 return -1;
02697 break;
02698 case kXGC_sigpxy:
02699
02700 if (ServerDoSigpxy(br, bm, cmsg) != 0)
02701 return -1;
02702 break;
02703 default:
02704 cmsg = "protocol error: unknown action: "; cmsg += step;
02705 return -1;
02706 break;
02707 }
02708
02709
02710
02711 return 0;
02712 }
02713
02714
02715 int XrdSecProtocolgsi::ServerDoCertreq(XrdSutBuffer *br, XrdSutBuffer **bm,
02716 String &cmsg)
02717 {
02718
02719
02720
02721 XrdSutBucket *bck = 0;
02722 XrdSutBucket *bckm = 0;
02723
02724
02725
02726 if (!(bckm = br->GetBucket(kXRS_main))) {
02727 cmsg = "main buffer missing";
02728 return -1;
02729 }
02730
02731
02732 if (!(bck = br->GetBucket(kXRS_cryptomod))) {
02733 cmsg = "crypto module specification missing";
02734 return -1;
02735 }
02736 String cmod;
02737 bck->ToString(cmod);
02738
02739 if (ParseCrypto(cmod) != 0) {
02740 cmsg = "cannot find / load crypto requested module :";
02741 cmsg += cmod;
02742 return -1;
02743 }
02744
02745
02746 if (br->UnmarshalBucket(kXRS_version,hs->RemVers) != 0) {
02747 hs->RemVers = Version;
02748 cmsg = "client version information not found in options:"
02749 " assume same as local";
02750 } else {
02751 br->Deactivate(kXRS_version);
02752 }
02753
02754
02755 if (!(bck = br->GetBucket(kXRS_issuer_hash))) {
02756 cmsg = "client issuer hash missing";
02757 return -1;
02758 }
02759 String cahash;
02760 bck->ToString(cahash);
02761
02762
02763 if (ParseCAlist(cahash) != 0) {
02764 cmsg = "unknown CA: cannot verify client credentials";
02765 return -1;
02766 }
02767
02768 XrdSutPFEntry *cent = 0;
02769 if (!(cent = cacheCert.Get(sessionCF->Name()))) {
02770 cmsg = "cannot find certificate: corruption?";
02771 return -1;
02772 }
02773
02774 if (cent->mtime < hs->TimeStamp) {
02775 if (cent->status == kPFE_special) {
02776
02777 ProxyIn_t pi = {SrvCert.c_str(), SrvKey.c_str(), CAdir.c_str(),
02778 UsrProxy.c_str(), PxyValid.c_str(), 0, 512};
02779 X509Chain *ch = 0;
02780 XrdCryptoRSA *k = 0;
02781 XrdSutBucket *b = 0;
02782 ProxyOut_t po = {ch, k, b };
02783 if (QueryProxy(0, &cacheCert, sessionCF->Name(),
02784 sessionCF, hs->TimeStamp, &pi, &po) != 0) {
02785 cmsg = "proxy expired and cannot be renewed";
02786 return -1;
02787 }
02788 } else {
02789 cmsg = "certificate has expired - go and get a new one";
02790 return -1;
02791 }
02792 }
02793
02794
02795 sessionKsig = sessionCF->RSA(*((XrdCryptoRSA *)(cent->buf2.buf)));
02796 hs->Cbck = (XrdSutBucket *)(cent->buf3.buf);
02797
02798
02799 if (!(hs->Cref = new XrdSutPFEntry(hs->ID.c_str()))) {
02800 cmsg = "cannot create cache entry";
02801 return -1;
02802 }
02803
02804
02805 if (!((*bm) = new XrdSutBuffer(bckm->buffer,bckm->size))) {
02806 cmsg = "error deserializing main buffer";
02807 return -1;
02808 }
02809
02810
02811 br->Deactivate(kXRS_issuer_hash);
02812
02813
02814
02815 if (br->UnmarshalBucket(kXRS_clnt_opts, hs->Options) == 0)
02816 br->Deactivate(kXRS_clnt_opts);
02817
02818
02819
02820 if (!((*bm) = new XrdSutBuffer(bckm->buffer,bckm->size))) {
02821 cmsg = "error deserializing main buffer";
02822 return -1;
02823 }
02824
02825
02826 return 0;
02827 }
02828
02829
02830 int XrdSecProtocolgsi::ServerDoCert(XrdSutBuffer *br, XrdSutBuffer **bm,
02831 String &cmsg)
02832 {
02833
02834
02835
02836 EPNAME("ServerDoCert");
02837
02838 XrdSutBucket *bck = 0;
02839 XrdSutBucket *bckm = 0;
02840
02841
02842
02843 if (!(bckm = br->GetBucket(kXRS_main))) {
02844 cmsg = "main buffer missing";
02845 return -1;
02846 }
02847
02848
02849 String cip = "";
02850 if ((bck = br->GetBucket(kXRS_cipher_alg))) {
02851 bck->ToString(cip);
02852
02853 if (DefCipher.find(cip) == -1) {
02854 cmsg = "unsupported cipher chosen by the client";
02855 hs->Chain = 0;
02856 return -1;
02857 }
02858
02859 br->Deactivate(kXRS_cipher_alg);
02860 } else {
02861 DEBUG("WARNING: client choice for cipher missing"
02862 " - using default");
02863 }
02864
02865
02866 if ((bck = br->GetBucket(kXRS_puk))) {
02867
02868
02869 SafeDelete(sessionKey);
02870
02871
02872 if (!hs->Rcip) {
02873 cmsg = "reference cipher missing";
02874 hs->Chain = 0;
02875 return -1;
02876 }
02877
02878 if (!(sessionKey = sessionCF->Cipher(*(hs->Rcip)))) {
02879 cmsg = "cannot get reference cipher";
02880 hs->Chain = 0;
02881 return -1;
02882 }
02883
02884
02885 if (!(sessionKey->Finalize(bck->buffer,bck->size,cip.c_str()))) {
02886 cmsg = "cannot finalize session cipher";
02887 hs->Chain = 0;
02888 return -1;
02889 }
02890
02891
02892 br->Deactivate(kXRS_puk);
02893 }
02894
02895
02896 if (sessionKey) {
02897 if (!(sessionKey->Decrypt(*bckm))) {
02898 cmsg = "error decrypting main buffer with session cipher";
02899 hs->Chain = 0;
02900 return -1;
02901 }
02902 }
02903
02904
02905 if (!((*bm) = new XrdSutBuffer(bckm->buffer,bckm->size))) {
02906 cmsg = "error deserializing main buffer";
02907 hs->Chain = 0;
02908 return -1;
02909 }
02910
02911
02912 if (hs->RemVers == -1) {
02913 if ((*bm)->UnmarshalBucket(kXRS_version,hs->RemVers) != 0) {
02914 hs->RemVers = Version;
02915 cmsg = "client version information not found in options:"
02916 " assume same as local";
02917 } else {
02918 (*bm)->Deactivate(kXRS_version);
02919 }
02920 }
02921
02922
02923
02924 if (!hs->Cref) {
02925 cmsg = "session cache has gone";
02926 hs->Chain = 0;
02927 return -1;
02928 }
02929
02930
02931 int reftime = hs->TimeStamp - TimeSkew;
02932 if (hs->Cref->mtime < reftime) {
02933 cmsg = "cache entry expired";
02934 SafeDelete(hs->Cref);
02935 hs->Chain = 0;
02936 return -1;
02937 }
02938
02939
02940
02941 if (!(bck = (*bm)->GetBucket(kXRS_x509))) {
02942 cmsg = "client certificate missing";
02943 SafeDelete(hs->Cref);
02944 hs->Chain = 0;
02945 return -1;
02946 }
02947
02948
02949 hs->Chain = new X509Chain(hs->Chain);
02950 if (!(hs->Chain)) {
02951 cmsg = "cannot suplicate reference chain";
02952 return -1;
02953 }
02954
02955 hs->Options |= kOptsDelChn;
02956
02957
02958 XrdCryptoX509ParseBucket_t ParseBucket = sessionCF->X509ParseBucket();
02959 if (!ParseBucket) {
02960 cmsg = "cannot attach to ParseBucket function!";
02961 return -1;
02962 }
02963
02964 int nci = (*ParseBucket)(bck, hs->Chain);
02965 if (nci < 2) {
02966 cmsg = "wrong number of certificates in received bucket (";
02967 cmsg += nci;
02968 cmsg += " > 1 expected)";
02969 return -1;
02970 }
02971
02972
02973 x509ChainVerifyOpt_t vopt = { 0, hs->TimeStamp, -1, hs->Crl};
02974 XrdCryptoX509Chain::EX509ChainErr ecode = XrdCryptoX509Chain::kNone;
02975 if (!(hs->Chain->Verify(ecode, &vopt))) {
02976 cmsg = "certificate chain verification failed: ";
02977 cmsg += hs->Chain->LastError();
02978 return -1;
02979 }
02980
02981
02982
02983
02984
02985
02986 bool needReq =
02987 ((PxyReqOpts & kOptsSrvReq) && (hs->Options & kOptsSigReq)) ||
02988 (hs->Options & kOptsDlgPxy);
02989 if (needReq || (hs->Options & kOptsFwdPxy)) {
02990
02991 hs->PxyChain = new X509Chain();
02992
02993 if ((*ParseBucket)(bck, hs->PxyChain) > 1) {
02994
02995 hs->PxyChain->Reorder();
02996 if (needReq) {
02997
02998 XrdCryptoX509Req *rPXp = (XrdCryptoX509Req *) &(hs->RemVers);
02999 XrdCryptoRSA *krPXp = 0;
03000 if (XrdSslgsiX509CreateProxyReq(hs->PxyChain->End(), &rPXp, &krPXp) == 0) {
03001
03002 hs->Cref->buf4.buf = (char *)krPXp;
03003
03004 XrdSutBucket *bckr = rPXp->Export();
03005
03006 if ((*bm)->AddBucket(bckr) != 0) {
03007 SafeDelete(hs->PxyChain);
03008 DEBUG("WARNING: proxy req: problem adding bucket to main buffer");
03009 }
03010 } else {
03011 SafeDelete(hs->PxyChain);
03012 DEBUG("WARNING: proxy req: problem creating request");
03013 }
03014 }
03015 } else {
03016 SafeDelete(hs->PxyChain);
03017 DEBUG("WARNING: proxy req: wrong number of certificates");
03018 }
03019 }
03020
03021
03022
03023 sessionKver = sessionCF->RSA(*(hs->Chain->End()->PKI()));
03024 if (!sessionKver || !sessionKver->IsValid()) {
03025 cmsg = "server certificate contains an invalid key";
03026 return -1;
03027 }
03028
03029 (*bm)->Deactivate(kXRS_x509);
03030
03031
03032
03033 String md = "";
03034 if ((bck = br->GetBucket(kXRS_md_alg))) {
03035 String mdlist;
03036 bck->ToString(md);
03037
03038 if (DefMD.find(md) == -1) {
03039 cmsg = "unsupported MD chosen by the client";
03040 return -1;
03041 }
03042
03043 br->Deactivate(kXRS_md_alg);
03044 } else {
03045 DEBUG("WARNING: client choice for digests missing"
03046 " - using default");
03047 md = "md5";
03048 }
03049 if (!(sessionMD = sessionCF->MsgDigest(md.c_str()))) {
03050 cmsg = "could not instantiate digest object";
03051 return -1;
03052 }
03053
03054
03055 return 0;
03056 }
03057
03058
03059 int XrdSecProtocolgsi::ServerDoSigpxy(XrdSutBuffer *br, XrdSutBuffer **bm,
03060 String &cmsg)
03061 {
03062
03063
03064
03065 EPNAME("ServerDoSigpxy");
03066
03067 XrdSutBucket *bck = 0;
03068 XrdSutBucket *bckm = 0;
03069
03070
03071
03072 if (!(bckm = br->GetBucket(kXRS_main))) {
03073 cmsg = "main buffer missing";
03074 return 0;
03075 }
03076
03077
03078 if (sessionKey) {
03079 if (!(sessionKey->Decrypt(*bckm))) {
03080 cmsg = "error decrypting main buffer with session cipher";
03081 return 0;
03082 }
03083 }
03084
03085
03086 if (!((*bm) = new XrdSutBuffer(bckm->buffer,bckm->size))) {
03087 cmsg = "error deserializing main buffer";
03088 return 0;
03089 }
03090
03091
03092 if (!(bck = (*bm)->GetBucket(kXRS_x509))) {
03093 cmsg = "buffer with requested info missing";
03094
03095 if (!(bck = (*bm)->GetBucket(kXRS_message))) {
03096
03097 String m;
03098 bck->ToString(m);
03099 DEBUG("msg from client: "<<m);
03100
03101 cmsg += " :"; cmsg += m;
03102 }
03103 return 0;
03104 }
03105
03106
03107 X509Chain *pxyc = hs->PxyChain;
03108 if (!pxyc) {
03109 cmsg = "the proxy chain is gone";
03110 return 0;
03111 }
03112
03113
03114 if ((hs->Options & kOptsFwdPxy)) {
03115
03116
03117 XrdCryptoRSA *kpx = pxyc->End()->PKI();
03118 if (kpx->ImportPrivate(bck->buffer, bck->size) != 0) {
03119 cmsg = "problems importing private key";
03120 return 0;
03121 }
03122 } else {
03123
03124
03125 if (!hs->Cref) {
03126 cmsg = "session cache has gone";
03127 return 0;
03128 }
03129
03130 XrdCryptoX509 *npx = sessionCF->X509(bck);
03131 if (!npx) {
03132 cmsg = "could not resolve signed request";
03133 return 0;
03134 }
03135
03136 XrdCryptoRSA *knpx = (XrdCryptoRSA *)(hs->Cref->buf4.buf);
03137 npx->SetPKI((XrdCryptoX509data)(knpx->Opaque()));
03138
03139 pxyc->PushBack(npx);
03140 }
03141
03142 proxyChain = pxyc;
03143 hs->PxyChain = 0;
03144
03145 if (QTRACE(Authen)) { proxyChain->Dump(); }
03146
03147
03148
03149 String user;
03150 if ((bck = (*bm)->GetBucket(kXRS_user))) {
03151 bck->ToString(user);
03152 (*bm)->Deactivate(kXRS_user);
03153 }
03154 if (user.length() <= 0) user = Entity.name;
03155
03156
03157 if ((PxyReqOpts & kOptsPxFile)) {
03158 if (user.length() > 0) {
03159 String pxfile = UsrProxy, name;
03160 struct passwd *pw = getpwnam(user.c_str());
03161 if (pw) {
03162 name = pw->pw_name;
03163 } else {
03164
03165 XrdCryptoX509 *c = proxyChain->SearchBySubject(proxyChain->EECname());
03166 if (c) {
03167 name = c->SubjectHash();
03168 } else {
03169 cmsg = "proxy chain not dumped to file: could not find subject hash";
03170 return 0;
03171 }
03172 }
03173 if (XrdSutResolve(pxfile, Entity.host,
03174 Entity.vorg, Entity.grps, name.c_str()) != 0) {
03175 DEBUG("Problems resolving templates in "<<pxfile);
03176 return 0;
03177 }
03178
03179 if (pw && pxfile.find("<uid>") != STR_NPOS) {
03180 String suid; suid += (int) pw->pw_uid;
03181 pxfile.replace("<uid>", suid.c_str());
03182 }
03183
03184
03185 XrdCryptoX509ChainToFile_t ctofile = sessionCF->X509ChainToFile();
03186 if ((*ctofile)(proxyChain,pxfile.c_str()) != 0) {
03187 cmsg = "problems dumping proxy chain to file ";
03188 cmsg += pxfile;
03189 return 0;
03190 }
03191 } else {
03192 cmsg = "proxy chain not dumped to file: entity name undefined";
03193 return 0;
03194 }
03195 }
03196
03197
03198 return 0;
03199 }
03200
03201
03202 void XrdSecProtocolgsi::ErrF(XrdOucErrInfo *einfo, kXR_int32 ecode,
03203 const char *msg1, const char *msg2,
03204 const char *msg3)
03205 {
03206
03207 EPNAME("ErrF");
03208
03209 char *msgv[12];
03210 int k, i = 0, sz = strlen("Secgsi");
03211
03212
03213
03214 int cm = (ecode >= kGSErrParseBuffer &&
03215 ecode <= kGSErrError) ? (ecode-kGSErrParseBuffer) : -1;
03216 const char *cmsg = (cm > -1) ? gGSErrStr[cm] : 0;
03217
03218
03219
03220 msgv[i++] = (char *)"Secgsi";
03221 if (cmsg) {msgv[i++] = (char *)": ";
03222 msgv[i++] = (char *)cmsg;
03223 sz += strlen(msgv[i-1]) + 2;
03224 }
03225 if (msg1) {msgv[i++] = (char *)": ";
03226 msgv[i++] = (char *)msg1;
03227 sz += strlen(msgv[i-1]) + 2;
03228 }
03229 if (msg2) {msgv[i++] = (char *)": ";
03230 msgv[i++] = (char *)msg2;
03231 sz += strlen(msgv[i-1]) + 2;
03232 }
03233 if (msg3) {msgv[i++] = (char *)": ";
03234 msgv[i++] = (char *)msg3;
03235 sz += strlen(msgv[i-1]) + 2;
03236 }
03237
03238
03239 if (einfo) {
03240 einfo->setErrInfo(ecode, (const char **)msgv, i);
03241 }
03242 if (QTRACE(Debug)) {
03243 char *bout = new char[sz+10];
03244 if (bout) {
03245 bout[0] = 0;
03246 for (k = 0; k < i; k++)
03247 sprintf(bout,"%s%s",bout,msgv[k]);
03248 DEBUG(bout);
03249 } else {
03250 for (k = 0; k < i; k++)
03251 DEBUG(msgv[k]);
03252 }
03253 }
03254 }
03255
03256
03257 XrdSecCredentials *XrdSecProtocolgsi::ErrC(XrdOucErrInfo *einfo,
03258 XrdSutBuffer *b1,
03259 XrdSutBuffer *b2,
03260 XrdSutBuffer *b3,
03261 kXR_int32 ecode,
03262 const char *msg1,
03263 const char *msg2,
03264 const char *msg3)
03265 {
03266
03267
03268
03269 ErrF(einfo, ecode, msg1, msg2, msg3);
03270
03271
03272 REL3(b1,b2,b3);
03273
03274
03275 return (XrdSecCredentials *)0;
03276 }
03277
03278
03279 int XrdSecProtocolgsi::ErrS(String ID, XrdOucErrInfo *einfo,
03280 XrdSutBuffer *b1, XrdSutBuffer *b2,
03281 XrdSutBuffer *b3, kXR_int32 ecode,
03282 const char *msg1, const char *msg2,
03283 const char *msg3)
03284 {
03285
03286
03287
03288 ErrF(einfo, ecode, msg1, msg2, msg3);
03289
03290
03291 REL3(b1,b2,b3);
03292
03293
03294 return kgST_error;
03295 }
03296
03297
03298 bool XrdSecProtocolgsi::CheckRtag(XrdSutBuffer *bm, String &emsg)
03299 {
03300
03301 EPNAME("CheckRtag");
03302
03303
03304 if (!bm) {
03305 emsg = "Buffer not defined";
03306 return 0;
03307 }
03308
03309
03310 if (hs->Cref && hs->Cref->buf1.len > 0) {
03311 XrdSutBucket *brt = 0;
03312 if ((brt = bm->GetBucket(kXRS_signed_rtag))) {
03313
03314 if (!(sessionKver)) {
03315 emsg = "Session cipher undefined";
03316 return 0;
03317 }
03318
03319 if (sessionKver->DecryptPublic(*brt) <= 0) {
03320 emsg = "error decrypting random tag with public key";
03321 return 0;
03322 }
03323 } else {
03324 emsg = "random tag missing - protocol error";
03325 return 0;
03326 }
03327
03328
03329 if (memcmp(brt->buffer,hs->Cref->buf1.buf,hs->Cref->buf1.len)) {
03330 emsg = "random tag content mismatch";
03331 SafeDelete(hs->Cref);
03332
03333 return 0;
03334 }
03335
03336
03337 memset(hs->Cref->buf1.buf,0,hs->Cref->buf1.len);
03338 hs->Cref->buf1.SetBuf();
03339
03340
03341 hs->RtagOK = 1;
03342 bm->Deactivate(kXRS_signed_rtag);
03343 DEBUG("Random tag successfully checked");
03344 } else {
03345 DEBUG("Nothing to check");
03346 }
03347
03348
03349 return 1;
03350 }
03351
03352
03353 int XrdSecProtocolgsi::LoadCADir(int timestamp)
03354 {
03355
03356
03357
03358 EPNAME("LoadCADir");
03359
03360
03361 XrdSutCache *ca = &(XrdSecProtocolgsi::cacheCA);
03362 if (!ca || ca->Init(100) != 0) {
03363 DEBUG("problems init cache for CA info");
03364 return -1;
03365 }
03366
03367
03368 String cadir;
03369 int from = 0;
03370 while ((from = CAdir.tokenize(cadir, from, ',')) != -1) {
03371 if (cadir.length() <= 0) continue;
03372
03373
03374 DIR *dd = opendir(cadir.c_str());
03375 if (!dd) {
03376 DEBUG("could not open directory: "<<cadir<<" (errno: "<<errno<<")");
03377 continue;
03378 }
03379
03380
03381 int i = 0;
03382 XrdCryptoX509ParseFile_t ParseFile = 0;
03383 String enam(cadir.length()+100);
03384 struct dirent *dent = 0;
03385 while ((dent = readdir(dd))) {
03386
03387 enam = cadir + dent->d_name;
03388 DEBUG("analysing entry "<<enam);
03389
03390 for (i = 0; i < ncrypt; i++) {
03391 X509Chain *chain = new X509Chain();
03392
03393 ParseFile = cryptF[i]->X509ParseFile();
03394 int nci = (*ParseFile)(enam.c_str(), chain);
03395 bool ok = 0;
03396 XrdCryptoX509Crl *crl = 0;
03397
03398 if (chain && nci == 1) {
03399
03400 bool verified = VerifyCA(CACheck, chain, cryptF[i]);
03401 if (verified) {
03402
03403
03404 if (CRLCheck > 0)
03405 crl = LoadCRL(chain->Begin(), cryptF[i]);
03406
03407 if (CRLCheck < 2 || crl) {
03408 if (CRLCheck < 3 ||
03409 (CRLCheck == 3 && crl && !(crl->IsExpired(timestamp)))) {
03410
03411 ok = 1;
03412 } else {
03413 DEBUG("CRL is expired (CRLCheck: "<<CRLCheck<<")");
03414 }
03415 } else {
03416 DEBUG("CRL is missing (CRLCheck: "<<CRLCheck<<")");
03417 }
03418 }
03419 }
03420
03421 if (ok) {
03422
03423 String tag(chain->Begin()->SubjectHash());
03424 tag += ':';
03425 tag += cryptID[i];
03426
03427 XrdSutPFEntry *cent = ca->Add(tag.c_str());
03428 if (cent) {
03429 cent->buf1.buf = (char *)chain;
03430 cent->buf1.len = 0;
03431 if (crl) {
03432 cent->buf2.buf = (char *)crl;
03433 cent->buf2.len = 0;
03434 }
03435 cent->mtime = timestamp;
03436 cent->status = kPFE_ok;
03437 cent->cnt = 0;
03438 }
03439 } else {
03440 DEBUG("Entry "<<enam<<" does not contain a valid CA");
03441 if (chain)
03442 chain->Cleanup();
03443 SafeDelete(chain);
03444 SafeDelete(crl);
03445 }
03446 }
03447 }
03448
03449 closedir(dd);
03450 }
03451
03452
03453 ca->Rehash(1);
03454
03455
03456 return 0;
03457 }
03458
03459
03460 XrdCryptoX509Crl *XrdSecProtocolgsi::LoadCRL(XrdCryptoX509 *xca,
03461 XrdCryptoFactory *CF)
03462 {
03463
03464
03465
03466
03467 EPNAME("LoadCRL");
03468 XrdCryptoX509Crl *crl = 0;
03469
03470
03471 if (!xca || !CF) {
03472 DEBUG("Invalid inputs");
03473 return crl;
03474 }
03475
03476
03477 bool verify = 1;
03478 XrdCryptoX509 *xcasig = xca;
03479 while (xcasig && strcmp(xcasig->Issuer(), xcasig->Subject())) {
03480 String crldir;
03481 int from = 0;
03482 while ((from = CRLdir.tokenize(crldir, from, ',')) != -1) {
03483 if (crldir.length() <= 0) continue;
03484 String casigfile = crldir + xcasig->IssuerHash();
03485
03486 if ((xcasig = CF->X509(casigfile.c_str()))) break;
03487 }
03488 }
03489 if (!xcasig) {
03490 verify = 0;
03491 if (CACheck == 2) {
03492 DEBUG("CA certificate to verify the signature could not be loaded - exit");
03493 return crl;
03494 } else if (CACheck == 1) {
03495 DEBUG("CA certificate to verify the signature could not be loaded - verification skipped");
03496 }
03497 }
03498
03499
03500 String cahash = xca->SubjectHash();
03501
03502 String caroot(cahash, 0, cahash.find(".0")-1);
03503
03504
03505 String crlext = XrdSecProtocolgsi::DefCRLext;
03506
03507 String crldir;
03508 int from = 0;
03509 while ((from = CRLdir.tokenize(crldir, from, ',')) != -1) {
03510 if (crldir.length() <= 0) continue;
03511
03512 String crlfile = crldir + caroot;
03513 crlfile += crlext;
03514 DEBUG("target file: "<<crlfile);
03515
03516 if ((crl = CF->X509Crl(crlfile.c_str()))) {
03517 if (verify) {
03518
03519 if (!(strcmp(crl->Issuer(),xcasig->Subject()))) {
03520
03521 if (crl->Verify(xcasig)) {
03522
03523 return crl;
03524 }
03525 }
03526 } else {
03527
03528 return crl;
03529 }
03530 }
03531 SafeDelete(crl);
03532 }
03533
03534
03535 if (CRLCheck < 2) {
03536
03537 return crl;
03538 }
03539
03540
03541
03542
03543
03544
03545
03546 if ((crl = CF->X509Crl(xca))) {
03547 if (verify) {
03548
03549 if (!(strcmp(crl->Issuer(),xcasig->Subject()))) {
03550
03551 if (crl->Verify(xcasig)) {
03552
03553 return crl;
03554 }
03555 }
03556 } else {
03557
03558 return crl;
03559 }
03560 }
03561
03562
03563 from = 0;
03564 while ((from = CRLdir.tokenize(crldir, from, ',')) != -1) {
03565 if (crldir.length() <= 0) continue;
03566 SafeDelete(crl);
03567 String crlurl = crldir + caroot;
03568 crlurl += ".crl_url";
03569 DEBUG("target file: "<<crlurl);
03570 FILE *furl = fopen(crlurl.c_str(), "r");
03571 if (!furl) {
03572 DEBUG("could not open file: "<<crlurl);
03573 continue;
03574 }
03575 char line[2048];
03576 while ((fgets(line, sizeof(line), furl))) {
03577 if (line[strlen(line) - 1] == '\n') line[strlen(line) - 1] = 0;
03578 if ((crl = CF->X509Crl(line, 1))) {
03579 if (verify) {
03580
03581 if (!(strcmp(crl->Issuer(),xcasig->Subject()))) {
03582
03583 if (crl->Verify(xcasig)) {
03584
03585 return crl;
03586 }
03587 }
03588 } else {
03589
03590 return crl;
03591 }
03592 }
03593 }
03594 }
03595
03596
03597 from = 0;
03598 while ((from = CRLdir.tokenize(crldir, from, ',')) != -1) {
03599 if (crldir.length() <= 0) continue;
03600 SafeDelete(crl);
03601
03602 DIR *dd = opendir(crldir.c_str());
03603 if (!dd) {
03604 DEBUG("could not open directory: "<<crldir<<" (errno: "<<errno<<")");
03605 continue;
03606 }
03607
03608 struct dirent *dent = 0;
03609 while ((dent = readdir(dd))) {
03610
03611 if (!strcmp(cahash.c_str(),dent->d_name)) continue;
03612
03613 if (!strstr(dent->d_name,caroot.c_str())) continue;
03614
03615 String crlfile = crldir + dent->d_name;
03616 DEBUG("analysing entry "<<crlfile);
03617
03618 crl = CF->X509Crl(crlfile.c_str());
03619 if (!crl) continue;
03620 if (verify) {
03621
03622 if (strcmp(crl->Issuer(),xca->Subject())) {
03623 SafeDelete(crl);
03624 continue;
03625 }
03626
03627 if (!(crl->Verify(xca))) {
03628 SafeDelete(crl);
03629 continue;
03630 }
03631 }
03632
03633 break;
03634 }
03635
03636 closedir(dd);
03637
03638 if (crl) break;
03639 }
03640
03641
03642 return crl;
03643 }
03644
03645 String XrdSecProtocolgsi::GetCApath(const char *cahash)
03646 {
03647
03648
03649
03650 String path;
03651 String ent;
03652 int from = 0;
03653 while ((from = CAdir.tokenize(ent, from, ',')) != -1) {
03654 if (ent.length() > 0) {
03655 path = ent;
03656 if (!path.endswith('/'))
03657 path += "/";
03658 path += cahash;
03659 if (!path.endswith(".0"))
03660 path += ".0";
03661 if (!access(path.c_str(), R_OK))
03662 break;
03663 }
03664 path = "";
03665 }
03666
03667
03668 return path;
03669 }
03670
03671 bool XrdSecProtocolgsi::VerifyCA(int opt, X509Chain *cca, XrdCryptoFactory *CF)
03672 {
03673
03674
03675
03676
03677 EPNAME("VerifyCA");
03678
03679 bool verified = 0;
03680 XrdCryptoX509Chain::ECAStatus st = XrdCryptoX509Chain::kUnknown;
03681 cca->SetStatusCA(st);
03682
03683
03684 if (!cca) {
03685 DEBUG("Invalid input ");
03686 return 0;
03687 }
03688
03689
03690 XrdCryptoX509ParseFile_t ParseFile = CF->X509ParseFile();
03691 if (!ParseFile) {
03692 DEBUG("Cannot attach to the ParseFile function");
03693 return 0;
03694 }
03695
03696
03697 XrdCryptoX509 *xc = cca->Begin();
03698
03699 bool self = (!strcmp(xc->IssuerHash(), xc->SubjectHash())) ? 1 : 0;
03700 if (!self) {
03701 String inam;
03702 if (opt == 2) {
03703
03704 bool notdone = 1;
03705
03706 XrdCryptoX509 *xd = xc;
03707 while (notdone) {
03708 inam = GetCApath(xd->IssuerHash());
03709 if (inam.length() <= 0) break;
03710 X509Chain *ch = new X509Chain();
03711 int ncis = (*ParseFile)(inam.c_str(), ch);
03712 if (ncis < 1) break;
03713 XrdCryptoX509 *xi = ch->Begin();
03714 while (xi) {
03715 if (!strcmp(xd->IssuerHash(), xi->SubjectHash()))
03716 break;
03717 xi = ch->Next();
03718 }
03719 if (xi) {
03720
03721 ch->Remove(xi);
03722 cca->PutInFront(xi);
03723 SafeDelete(ch);
03724
03725 if (!strcmp(xi->IssuerHash(), xi->SubjectHash())) {
03726 notdone = 0;
03727 break;
03728 } else {
03729
03730 xd = xi;
03731 }
03732 } else {
03733 break;
03734 }
03735 }
03736 if (!notdone) {
03737
03738 X509Chain::EX509ChainErr e;
03739 verified = cca->Verify(e);
03740 } else {
03741 PRINT("CA certificate not self-signed: cannot verify integrity ("<<xc->SubjectHash()<<")");
03742 }
03743 } else {
03744
03745 cca->CheckCA(0);
03746
03747 verified = 1;
03748
03749 if (opt == 1) {
03750 DEBUG("Warning: CA certificate not self-signed:"
03751 " integrity not checked, assuming OK ("<<xc->SubjectHash()<<")");
03752 }
03753 }
03754 } else if (CACheck > 0) {
03755
03756 verified = cca->CheckCA();
03757 }
03758
03759
03760 st = (verified) ? XrdCryptoX509Chain::kValid : st;
03761 cca->SetStatusCA(st);
03762
03763
03764 return verified;
03765 }
03766
03767
03768 int XrdSecProtocolgsi::GetCA(const char *cahash)
03769 {
03770
03771
03772
03773 EPNAME("GetCA");
03774
03775
03776 if (!cahash) {
03777 DEBUG("Invalid input ");
03778 return -1;
03779 }
03780
03781
03782 String tag(cahash,20);
03783 tag += ':';
03784 tag += sessionCF->ID();
03785 DEBUG("Querying cache for tag: "<<tag);
03786
03787
03788 XrdSutPFEntry *cent = cacheCA.Get(tag.c_str());
03789
03790
03791 if (cent) {
03792 hs->Chain = (X509Chain *)(cent->buf1.buf);
03793 hs->Crl = (XrdCryptoX509Crl *)(cent->buf2.buf);
03794 return 0;
03795 }
03796
03797
03798 String fnam = GetCApath(cahash);
03799 DEBUG("trying to load CA certificate from "<<fnam);
03800
03801
03802 hs->Chain = new X509Chain();
03803 if (!hs->Chain ) {
03804 DEBUG("could not create new GSI chain");
03805 return -1;
03806 }
03807
03808
03809 XrdCryptoX509ParseFile_t ParseFile = sessionCF->X509ParseFile();
03810 if (ParseFile) {
03811 int nci = (*ParseFile)(fnam.c_str(), hs->Chain);
03812 bool ok = 0, verified = 0;
03813 if (nci == 1) {
03814
03815 verified = VerifyCA(CACheck, hs->Chain, sessionCF);
03816
03817 if (verified) {
03818
03819 if (CRLCheck > 0)
03820 hs->Crl = LoadCRL(hs->Chain->Begin(), sessionCF);
03821
03822 if (CRLCheck < 2 || hs->Crl) {
03823 if (CRLCheck < 3 ||
03824 (CRLCheck == 3 &&
03825 hs->Crl && !(hs->Crl->IsExpired(hs->TimeStamp)))) {
03826
03827 ok = 1;
03828 } else {
03829 DEBUG("CRL is expired (CRLCheck: "<<CRLCheck<<")");
03830 }
03831 } else {
03832 DEBUG("CRL is missing (CRLCheck: "<<CRLCheck<<")");
03833 }
03834 }
03835
03836 if (ok) {
03837
03838 cent = cacheCA.Add(tag.c_str());
03839 if (cent) {
03840 cent->buf1.buf = (char *)(hs->Chain);
03841 cent->buf1.len = 0;
03842 if (hs->Crl) {
03843 cent->buf2.buf = (char *)(hs->Crl);
03844 cent->buf2.len = 0;
03845 }
03846 cent->mtime = hs->TimeStamp;
03847 cent->status = kPFE_ok;
03848 cent->cnt = 0;
03849 }
03850 } else {
03851 return -2;
03852 }
03853 } else {
03854 DEBUG("certificate not found or invalid (nci: "<<nci<<", CA: "<<
03855 (int)(verified)<<")");
03856 return -1;
03857 }
03858 }
03859
03860
03861 cacheCA.Rehash(1);
03862
03863
03864 return 0;
03865 }
03866
03867
03868 int XrdSecProtocolgsi::InitProxy(ProxyIn_t *pi, X509Chain *ch, XrdCryptoRSA **kp)
03869 {
03870
03871
03872
03873
03874 EPNAME("InitProxy");
03875 int rc = 0;
03876
03877
03878 if (isatty(0) == 0 || isatty(1) == 0) {
03879 DEBUG("Not a tty: cannot prompt for proxies - do nothing ");
03880 return -1;
03881 }
03882
03883 #ifndef HASGRIDPROXYINIT
03884
03885
03886
03887
03888 if (!ch || !kp) {
03889 DEBUG("chain or key container undefined");
03890 return -1;
03891 }
03892
03893
03894 int valid = (pi->valid) ? XrdSutParseTime(pi->valid, 1) : -1;
03895
03896
03897 XrdProxyOpt_t pxopt = {pi->bits,
03898 valid,
03899 pi->deplen};
03900
03901
03902 rc = XrdSslgsiX509CreateProxy(pi->cert, pi->key, &pxopt,
03903 ch, kp, pi->out);
03904 #else
03905
03906 String cmd(kMAXBUFLEN);
03907
03908
03909 if (getenv("GLOBUS_LOCATION"))
03910 cmd = "source $GLOBUS_LOCATION/etc/globus-user-env.sh;";
03911
03912
03913 cmd += " grid-proxy-init";
03914
03915
03916 cmd += " -cert ";
03917 cmd += pi->cert;
03918
03919
03920 cmd += " -key ";
03921 cmd += pi->key;
03922
03923
03924 String cdir(pi->certdir);
03925 cdir.erase(cdir.find(','));
03926 cmd += " -certdir ";
03927 cmd += cdir;
03928
03929
03930 if (pi->valid) {
03931 cmd += " -valid ";
03932 cmd += pi->valid;
03933 }
03934
03935
03936 if (pi->bits > 512) {
03937 cmd += " -bits ";
03938 cmd += pi->bits;
03939 }
03940
03941
03942 if (pi->deplen > -1) {
03943 cmd += " -path-length ";
03944 cmd += pi->deplen;
03945 }
03946
03947
03948 if (pi->out) {
03949 cmd += " -out ";
03950 cmd += pi->out;
03951 }
03952
03953 DEBUG("executing: " << cmd);
03954
03955
03956 rc = system(cmd.c_str());
03957 DEBUG("return code: "<< rc << " (0x"<<(int *)rc<<")");
03958 #endif
03959
03960
03961 return rc;
03962 }
03963
03964
03965 int XrdSecProtocolgsi::ParseCAlist(String calist)
03966 {
03967
03968
03969
03970 EPNAME("ParseCAlist");
03971
03972
03973 if (calist.length() <= 0) {
03974 DEBUG("nothing to parse");
03975 return -1;
03976 }
03977 DEBUG("parsing list: "<<calist);
03978
03979
03980 hs->Chain = 0;
03981 String cahash = "";
03982
03983 if (calist.length()) {
03984 int from = 0;
03985 while ((from = calist.tokenize(cahash, from, '|')) != -1) {
03986
03987 if (cahash.length()) {
03988
03989 if (GetCA(cahash.c_str()) == 0)
03990 return 0;
03991 }
03992 }
03993 }
03994
03995
03996 return -1;
03997 }
03998
03999
04000 int XrdSecProtocolgsi::ParseCrypto(String clist)
04001 {
04002
04003
04004
04005
04006
04007
04008 EPNAME("ParseCrypto");
04009
04010
04011 if (clist.length() <= 0) {
04012 DEBUG("empty list: nothing to parse");
04013 return -1;
04014 }
04015 DEBUG("parsing list: "<<clist);
04016
04017
04018 hs->CryptoMod = "";
04019
04020
04021 int from = 0;
04022 while ((from = clist.tokenize(hs->CryptoMod, from, '|')) != -1) {
04023
04024 if (hs->CryptoMod.length() > 0) {
04025 DEBUG("found module: "<<hs->CryptoMod);
04026
04027 if ((sessionCF =
04028 XrdCryptoFactory::GetCryptoFactory(hs->CryptoMod.c_str()))) {
04029 sessionCF->SetTrace(GSITrace->What);
04030 int fid = sessionCF->ID();
04031 int i = 0;
04032
04033 while (i < ncrypt) {
04034 if (cryptID[i] == fid) break;
04035 i++;
04036 }
04037 if (i >= ncrypt) {
04038 if (ncrypt == XrdCryptoMax) {
04039 DEBUG("max number of crypto slots reached - do nothing");
04040 return 0;
04041 } else {
04042
04043 cryptF[i] = sessionCF;
04044 cryptID[i] = fid;
04045 ncrypt++;
04046 }
04047 }
04048
04049 hs->Rcip = refcip[i];
04050
04051 return 0;
04052 }
04053 }
04054 }
04055
04056
04057 return -1;
04058 }
04059
04060
04061 int XrdSecProtocolgsi::QueryProxy(bool checkcache, XrdSutCache *cache,
04062 const char *tag, XrdCryptoFactory *cf,
04063 int timestamp, ProxyIn_t *pi, ProxyOut_t *po)
04064 {
04065
04066 EPNAME("QueryProxy");
04067
04068 bool hasproxy = 0;
04069
04070 XrdSutPFEntry *cent = 0;
04071 if (checkcache) {
04072 cent = cache->Get(tag);
04073 if (cent && cent->buf1.buf) {
04074
04075 po->chain = (X509Chain *)(cent->buf1.buf);
04076
04077 if (po->chain->CheckValidity(1, timestamp) == 0) {
04078 po->ksig = (XrdCryptoRSA *)(cent->buf2.buf);
04079 po->cbck = (XrdSutBucket *)(cent->buf3.buf);
04080 hasproxy = 1;
04081 return 0;
04082 } else {
04083
04084 po->chain->Cleanup();
04085
04086 cent->buf1.buf = 0;
04087 cent->buf1.len = 0;
04088
04089
04090 cent->buf2.buf = 0;
04091 cent->buf2.len = 0;
04092
04093 if (cent->buf3.buf)
04094 delete (XrdSutBucket *)(cent->buf3.buf);
04095 cent->buf3.buf = 0;
04096 cent->buf3.len = 0;
04097 }
04098 }
04099 }
04100
04101
04102
04103
04104
04105 if (!(po->chain))
04106 po->chain = new X509Chain();
04107 if (!(po->chain)) {
04108 DEBUG("cannot create new chain!");
04109 return -1;
04110 }
04111 int ntry = 3;
04112 bool parsefile = 1;
04113 bool exportbucket = 0;
04114 XrdCryptoX509ParseFile_t ParseFile = 0;
04115 XrdCryptoX509ParseBucket_t ParseBucket = 0;
04116 while (!hasproxy && ntry > 0) {
04117
04118
04119 if (ntry == 1) {
04120
04121
04122 po->chain->Cleanup();
04123
04124 if (InitProxy(pi, po->chain, &(po->ksig)) != 0) {
04125 DEBUG("problems initializing proxy via external shell");
04126 ntry--;
04127 continue;
04128 }
04129
04130 exportbucket = 1;
04131 #ifndef HASGRIDPROXYINIT
04132
04133
04134 parsefile = 0;
04135 timestamp = (int)(time(0));
04136 #endif
04137 }
04138 ntry--;
04139
04140
04141
04142 if (ntry == 2) {
04143
04144 char *cbuf = getenv("XrdSecCREDS");
04145 if (cbuf) {
04146
04147 po->cbck = new XrdSutBucket(0, 0, kXRS_x509);
04148
04149 po->cbck->SetBuf(cbuf, strlen(cbuf));
04150
04151 if (!(ParseBucket = cf->X509ParseBucket())) {
04152 DEBUG("cannot attach to ParseBucket function!");
04153 continue;
04154 }
04155 int nci = (*ParseBucket)(po->cbck, po->chain);
04156 if (nci < 2) {
04157 DEBUG("proxy bucket must have at least two certificates"
04158 " (found: "<<nci<<")");
04159 continue;
04160 }
04161 } else {
04162
04163 ntry--;
04164 }
04165 }
04166 if (ntry == 1) {
04167 if (parsefile) {
04168 if (!ParseFile) {
04169 if (!(ParseFile = cf->X509ParseFile())) {
04170 DEBUG("cannot attach to ParseFile function!");
04171 continue;
04172 }
04173 }
04174
04175 int nci = (*ParseFile)(pi->out, po->chain);
04176 if (nci < 2) {
04177 DEBUG("proxy files must have at least two certificates"
04178 " (found: "<<nci<<")");
04179 continue;
04180 }
04181
04182 bool checkselfsigned = (CACheck > 1) ? 1 : 0;
04183 po->chain->CheckCA(checkselfsigned);
04184 exportbucket = 1;
04185 }
04186 }
04187
04188
04189 if (po->chain->CheckValidity(1, timestamp) != 0) {
04190 DEBUG("proxy files contains expired certificates");
04191 continue;
04192 }
04193
04194
04195 if (po->chain->Reorder() != 0) {
04196 DEBUG("proxy files contains inconsistent certificates");
04197 continue;
04198 }
04199
04200
04201 po->ksig = po->chain->End()->PKI();
04202 if (po->ksig->status != XrdCryptoRSA::kComplete) {
04203 DEBUG("proxy files contain invalid key pair");
04204 continue;
04205 }
04206
04207 XrdCryptoX509ExportChain_t ExportChain = cf->X509ExportChain();
04208 if (!ExportChain) {
04209 DEBUG("cannot attach to ExportChain function!");
04210 continue;
04211 }
04212
04213
04214 if (exportbucket) {
04215 po->cbck = (*ExportChain)(po->chain, 0);
04216 if (!(po->cbck)) {
04217 DEBUG("could not create bucket for export");
04218 continue;
04219 }
04220 }
04221
04222
04223 if (!(cent = cache->Add(tag))) {
04224 DEBUG("could not create entry in cache");
04225 continue;
04226 }
04227
04228
04229 cent->mtime = po->chain->End()->NotAfter();
04230 cent->status = kPFE_special;
04231 cent->cnt = 0;
04232
04233 cent->buf1.buf = (char *)(po->chain);
04234 cent->buf1.len = 0;
04235
04236 cent->buf2.buf = (char *)(po->chain->End()->PKI());
04237 cent->buf2.len = 0;
04238
04239 cent->buf3.buf = (char *)(po->cbck);
04240 cent->buf3.len = 0;
04241
04242
04243 cache->Rehash(1);
04244
04245
04246 hasproxy = 1;
04247 }
04248
04249
04250 if (!hasproxy) {
04251
04252 po->chain->Cleanup();
04253 SafeDelete(po->chain);
04254 SafeDelete(po->cbck);
04255 return -1;
04256 }
04257 return 0;
04258 }
04259
04260
04261 int XrdSecProtocolgsi::LoadGMAP(int now)
04262 {
04263
04264
04265
04266
04267 EPNAME("LoadGMAP");
04268
04269
04270 static int lastCheck = -1;
04271
04272
04273 if (GMAPFile.length() <= 0)
04274 return 0;
04275
04276
04277 struct stat st;
04278 if (stat(GMAPFile.c_str(), &st) != 0) {
04279 PRINT("error 'stat'-ing file "<<GMAPFile);
04280 return -1;
04281 }
04282
04283
04284 if (lastCheck > st.st_mtime)
04285
04286 return 0;
04287
04288
04289 if (cacheGMAP.Empty()) {
04290 if (cacheGMAP.Init(100) != 0) {
04291 PRINT("error initializing cache");
04292 return -1;
04293 }
04294 } else {
04295 if (cacheGMAP.Reset() != 0) {
04296 PRINT("error resetting cache");
04297 return -1;
04298 }
04299 }
04300
04301
04302 FILE *fm = fopen(GMAPFile.c_str(),"r");
04303 if (!fm) {
04304 PRINT("error opening file "<<GMAPFile);
04305 return -1;
04306 }
04307
04308
04309 char line[2048] = {0};
04310 while (fgets(line,sizeof(line),fm)) {
04311
04312 if (line[0] == '#') continue;
04313
04314 if (line[strlen(line)-1] == '\n')
04315 line[strlen(line)-1] = 0;
04316
04317 char *p0 = (line[0] == '"') ? &line[1] : &line[0];
04318 int l0 = 0;
04319 while (p0[l0] != '"')
04320 l0++;
04321 String udn(p0, l0);
04322 p0 = (p0 + l0 + 1);
04323 while (*p0 == ' ')
04324 p0++;
04325
04326
04327 String usr(p0);
04328
04329
04330 DEBUG("Found: udn: "<<udn<<", usr: "<<usr);
04331
04332
04333 XrdSutPFEntry *cent = cacheGMAP.Add(udn.c_str());
04334 if (cent) {
04335 cent->status = kPFE_ok;
04336 cent->cnt = 0;
04337 cent->mtime = now;
04338
04339 SafeFree(cent->buf1.buf);
04340 cent->buf1.buf = strdup(usr.c_str());
04341 cent->buf1.len = usr.length();
04342 }
04343 }
04344 fclose(fm);
04345
04346
04347 cacheGMAP.Rehash(1);
04348
04349
04350 lastCheck = now;
04351
04352
04353 return 0;
04354 }
04355
04356
04357 void XrdSecProtocolgsi::QueryGMAP(XrdCryptoX509Chain *chain, int now, String &usrs)
04358 {
04359
04360
04361
04362
04363
04364
04365
04366 EPNAME("QueryGMAP");
04367
04368
04369 usrs = "";
04370
04371
04372 if (!chain) {
04373 PRINT("input chain undefined!");
04374 return;
04375 }
04376
04377
04378 if (AuthzFun) {
04379
04380
04381
04382
04383 XrdSutBucket *bucket = XrdCryptosslX509ExportChain(chain, true);
04384 XrdOucString s;
04385 bucket->ToString(s);
04386 delete bucket;
04387 char *name = (*AuthzFun)(s.c_str(), now);
04388 if (name) {
04389 usrs = name;
04390 delete [] name;
04391 }
04392
04393 return;
04394 }
04395
04396
04397
04398 XrdSutPFEntry *cent = 0;
04399 const char *dn = chain->EECname();
04400 if (GMAPFun) {
04401
04402 cent = cacheGMAPFun.Get(dn);
04403
04404 if (GMAPCacheTimeOut > 0 &&
04405 (cent && (now - cent->mtime) > GMAPCacheTimeOut)) {
04406
04407 cacheGMAPFun.Remove(dn);
04408 cent = 0;
04409 }
04410
04411 if (!cent) {
04412 char *name = (*GMAPFun)(dn, now);
04413 if ((cent = cacheGMAPFun.Add(dn))) {
04414 if (name) {
04415 cent->status = kPFE_ok;
04416
04417 SafeFree(cent->buf1.buf);
04418 cent->buf1.buf = name;
04419 cent->buf1.len = strlen(name);
04420 } else {
04421
04422 cent->status = kPFE_allowed;
04423 }
04424
04425 cent->cnt = 0;
04426 cent->mtime = now;
04427
04428 cacheGMAPFun.Rehash(1);
04429 }
04430 }
04431
04432 if (cent && (cent->status != kPFE_ok))
04433 cent = 0;
04434 }
04435
04436
04437 if (cent)
04438 usrs = (const char *)(cent->buf1.buf);
04439
04440
04441 if (LoadGMAP(now) != 0) {
04442 DEBUG("error loading/ refreshing grid map file");
04443 return;
04444 }
04445
04446
04447 cent = cacheGMAP.Get(dn);
04448
04449
04450 if (cent) {
04451 if (usrs.length() > 0) usrs += ",";
04452 usrs += (const char *)(cent->buf1.buf);
04453 }
04454
04455
04456 return;
04457 }
04458
04459
04460 XrdSecgsiGMAP_t XrdSecProtocolgsi::LoadGMAPFun(const char *plugin,
04461 const char *parms)
04462 {
04463
04464 EPNAME("LoadGMAPFun");
04465
04466
04467 if (!plugin || strlen(plugin) <= 0) {
04468 PRINT("plug-in file undefined");
04469 return (XrdSecgsiGMAP_t)0;
04470 }
04471
04472
04473 if (!(GMAPPlugin = new XrdSysPlugin(&XrdSecProtocolgsi::eDest, plugin))) {
04474 PRINT("could not create plugin instance for "<<plugin);
04475 return (XrdSecgsiGMAP_t)0;
04476 }
04477
04478
04479 bool useglobals = 0;
04480 XrdOucString params, ps(parms), p;
04481 int from = 0;
04482 while ((from = ps.tokenize(p, from, '|')) != -1) {
04483 if (p == "useglobals") {
04484 useglobals = 1;
04485 } else {
04486 if (params.length() > 0) params += " ";
04487 params += p;
04488 }
04489 }
04490 DEBUG("params: '"<< params<<"'; useglobals: "<<useglobals);
04491
04492
04493 XrdSecgsiGMAP_t ep = 0;
04494 if (useglobals) {
04495 ep = (XrdSecgsiGMAP_t) GMAPPlugin->getPlugin("XrdSecgsiGMAPFun", 0, true);
04496 } else {
04497 ep = (XrdSecgsiGMAP_t) GMAPPlugin->getPlugin("XrdSecgsiGMAPFun");
04498 }
04499 if (!ep) {
04500 PRINT("could not find 'XrdSecgsiGMAPFun()' in "<<plugin);
04501 return (XrdSecgsiGMAP_t)0;
04502 }
04503
04504
04505 if ((*ep)(params.c_str(), 0) == (char *)-1) {
04506 PRINT("could not initialize 'XrdSecgsiGMAPFun()'");
04507 return (XrdSecgsiGMAP_t)0;
04508 }
04509
04510
04511 PRINT("using 'XrdSecgsiGMAPFun()' from "<<plugin);
04512
04513
04514 return ep;
04515 }
04516
04517
04518 XrdSecgsiAuthz_t XrdSecProtocolgsi::LoadAuthzFun(const char *plugin,
04519 const char *parms)
04520 {
04521
04522 EPNAME("LoadAuthzFun");
04523
04524
04525 if (!plugin || strlen(plugin) <= 0) {
04526 PRINT("plug-in file undefined");
04527 return (XrdSecgsiAuthz_t)0;
04528 }
04529
04530
04531 if (!(AuthzPlugin = new XrdSysPlugin(&XrdSecProtocolgsi::eDest, plugin))) {
04532 PRINT("could not create plugin instance for "<<plugin);
04533 return (XrdSecgsiAuthz_t)0;
04534 }
04535
04536
04537 bool useglobals = 0;
04538 XrdOucString params, ps(parms), p;
04539 int from = 0;
04540 while ((from = ps.tokenize(p, from, '|')) != -1) {
04541 if (p == "useglobals") {
04542 useglobals = 1;
04543 } else {
04544 if (params.length() > 0) params += " ";
04545 params += p;
04546 }
04547 }
04548 DEBUG("params: '"<< params<<"'; useglobals: "<<useglobals);
04549
04550
04551 XrdSecgsiAuthz_t ep = 0;
04552 if (useglobals)
04553 ep = (XrdSecgsiAuthz_t) AuthzPlugin->getPlugin("XrdSecgsiAuthzFun", 0, true);
04554 else
04555 ep = (XrdSecgsiAuthz_t) AuthzPlugin->getPlugin("XrdSecgsiAuthzFun");
04556 if (!ep) {
04557 PRINT("could not find 'XrdSecgsiAuthzFun()' in "<<plugin);
04558 return (XrdSecgsiAuthz_t)0;
04559 }
04560
04561
04562 if ((*ep)(params.c_str(), 0) == (char *)-1) {
04563 PRINT("could not initialize 'XrdSecgsiGMAPFun()'");
04564 return (XrdSecgsiAuthz_t)0;
04565 }
04566
04567
04568 PRINT("using 'XrdSecgsiAuthzFun()' from "<<plugin);
04569
04570
04571 return ep;
04572 }
04573
04574
04575 bool XrdSecProtocolgsi::ServerCertNameOK(const char *subject, XrdOucString &emsg)
04576 {
04577
04578
04579
04580
04581 if (!subject || strlen(subject) <= 0) return 0;
04582
04583 bool allowed = 0;
04584 emsg = "";
04585
04586
04587 String srvsubj(subject);
04588 String srvcn;
04589 int cnidx = srvsubj.find("CN=");
04590 if (cnidx != STR_NPOS) srvcn.assign(srvsubj, cnidx + 3);
04591
04592
04593 if (Entity.host) {
04594 if (srvcn != (const char *) Entity.host) {
04595 int ih = srvcn.find((const char *) Entity.host);
04596 if (ih == 0 || (ih > 0 && srvcn[ih-1] == '/')) {
04597 ih += strlen(Entity.host);
04598 if (ih >= srvcn.length() ||
04599 srvcn[ih] == '\0' || srvcn[ih] == '/') allowed = 1;
04600 }
04601 } else {
04602 allowed = 1;
04603 }
04604
04605 if (!allowed) {
04606 if (emsg.length() <= 0) {
04607 emsg = "server certificate CN '"; emsg += srvcn;
04608 emsg += "' does not match the expected format(s):";
04609 }
04610 String defcn("[*/]"); defcn += Entity.host; defcn += "[/*]";
04611 emsg += " '"; emsg += defcn; emsg += "' (default)";
04612 }
04613 }
04614
04615
04616 if (SrvAllowedNames.length() > 0) {
04617
04618
04619
04620
04621
04622 String allowedfmts(SrvAllowedNames);
04623 allowedfmts.replace("<host>", (const char *) Entity.host);
04624 allowedfmts.replace("<fqdn>", (const char *) Entity.host);
04625 int from = 0;
04626 String fmt;
04627 while ((from = allowedfmts.tokenize(fmt, from, '|')) != -1) {
04628
04629 bool deny = 0;
04630 if (fmt.beginswith("-")) {
04631 deny = 1;
04632 fmt.erasefromstart(1);
04633 }
04634 if (srvcn.matches(fmt.c_str()) > 0) allowed = (deny) ? 0 : 1;
04635 }
04636
04637 if (!allowed) {
04638 if (emsg.length() <= 0) {
04639 emsg = "server certificate CN '"; emsg += srvcn;
04640 emsg += "' does not match the expected format:";
04641 }
04642 emsg += " '"; emsg += SrvAllowedNames; emsg += "' (exceptions)";
04643 }
04644 }
04645
04646 if (allowed)
04647 emsg = "";
04648 else
04649 emsg += "; exceptions are controlled by the env XrdSecGSISRVNAMES";
04650
04651
04652 return allowed;
04653 }
04654