00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "RConfigure.h"
00018
00019 #include <errno.h>
00020 #include <signal.h>
00021 #include <string.h>
00022
00023
00024 #include "TSocket.h"
00025 #include "TAuthenticate.h"
00026 #include "THostAuth.h"
00027 #include "TDatime.h"
00028 #include "TError.h"
00029 #include "TSystem.h"
00030 #include "TROOT.h"
00031 #include "TApplication.h"
00032 #include "TEnv.h"
00033 #include "Getline.h"
00034 #include "NetErrors.h"
00035
00036 #define HAVE_MEMMOVE 1
00037 extern "C" {
00038 #ifdef IOV_MAX
00039 #undef IOV_MAX
00040 #endif
00041 #include <globus_common.h>
00042 #include <globus_gss_assist.h>
00043 #include <openssl/x509.h>
00044 #include <openssl/pem.h>
00045 #include <sys/ipc.h>
00046 #include <sys/shm.h>
00047 }
00048
00049 static gss_cred_id_t gGlbCredHandle = GSS_C_NO_CREDENTIAL;
00050 static gss_cred_id_t gGlbDelCredHandle = GSS_C_NO_CREDENTIAL;
00051 static int gShmIdCred = -1;
00052
00053 Int_t GlobusAuthenticate(TAuthenticate *, TString &, TString &);
00054 Int_t GlobusCheckSecContext(const char *, gss_ctx_id_t);
00055 Int_t GlobusCheckSecCtx(const char *, TRootSecContext *);
00056 Int_t GlobusCleanupContext(gss_ctx_id_t);
00057 void GlobusCleanupShm();
00058 Int_t GlobusIssuerName(TString &);
00059 void GlobusError(const char *, OM_uint32, OM_uint32, Int_t);
00060 Int_t GlobusGetCredHandle(Int_t, gss_cred_id_t *);
00061 Int_t GlobusGetDelCred();
00062 void GlobusGetDetails(Int_t, Int_t, TString &);
00063 Int_t GlobusGetLocalEnv(Int_t *, TString);
00064 Int_t GlobusGetSecContLifeTime(gss_ctx_id_t);
00065 Int_t GlobusNameFromCred(gss_cred_id_t, TString &);
00066
00067 class GlobusAuthInit {
00068 public:
00069 GlobusAuthInit() {
00070 TAuthenticate::SetGlobusAuthHook(&GlobusAuthenticate);
00071 }};
00072 static GlobusAuthInit globusauth_init;
00073
00074
00075 Int_t GlobusAuthenticate(TAuthenticate * tAuth, TString & user,
00076 TString & details)
00077 {
00078
00079
00080
00081
00082
00083
00084
00085
00086 int auth = 0, rc;
00087 int retval = 0, kind = 0, type = 0, server_auth = 0, brcv = 0, bsnd = 0;
00088 gss_ctx_id_t glbContextHandle = GSS_C_NO_CONTEXT;
00089 OM_uint32 majStat = 0;
00090 OM_uint32 minStat = 0;
00091 OM_uint32 gssRetFlags = 0;
00092 OM_uint32 gssReqFlags = 0;
00093 int glbTokenStatus = 0;
00094 char *host_subj = 0;
00095 TDatime expDate = TDatime();
00096
00097
00098 if (user == "-1") {
00099 if (gDebug > 2)
00100 Info("GlobusAuthenticate", " cleanup call (%s)",details.Data());
00101
00102 if (details == "context") {
00103
00104 GlobusCleanupContext((gss_ctx_id_t)tAuth);
00105 } else if (details == "shm") {
00106
00107 GlobusCleanupShm();
00108 }
00109 return 1;
00110 }
00111
00112
00113 TSocket *sock = tAuth->GetSocket();
00114 TString protocol = tAuth->GetProtocol();
00115
00116 if (gDebug > 2)
00117 Info("GlobusAuthenticate", " enter: protocol:'%s' user:'%s'", protocol.Data(),
00118 user.Data());
00119
00120
00121 const char *hostFQDN = sock->GetInetAddress().GetHostName();
00122
00123
00124 Int_t localCallEnv = -1;
00125 if ((rc = GlobusGetLocalEnv(&localCallEnv, protocol))) {
00126 if (gDebug > 0)
00127 Error("GlobusAuthenticate",
00128 "unable to set relevant environment variables (rc=%d)",
00129 rc);
00130 return -1;
00131 }
00132 if (gDebug > 3)
00133 Info("GlobusAuthenticate", " localCallEnv is %d", localCallEnv);
00134
00135
00136 if (GlobusGetCredHandle(localCallEnv, &gGlbCredHandle)) {
00137 if (gDebug > 0)
00138 Error("GlobusAuthenticate", "unable to acquire valid credentials");
00139 return -1;
00140 }
00141 if (gDebug > 3)
00142 Info("GlobusAuthenticate", " Credential Handle is 0x%x",
00143 gGlbCredHandle);
00144
00145
00146 TString ssuj;
00147 if ((rc = GlobusNameFromCred(gGlbCredHandle, ssuj))) {
00148 if (gDebug > 0)
00149 Error("GlobusAuthenticate",
00150 "PROOF Master: unable to determine name from cred (rc=%d)", rc);
00151 return -1;
00152 }
00153
00154
00155 Int_t opt = TAuthenticate::GetAuthReUse() * kAUTH_REUSE_MSK +
00156 tAuth->GetRSAKeyType() * kAUTH_RSATY_MSK;
00157 TString options(Form("%d %d %s", opt, ssuj.Length(), ssuj.Data()));
00158
00159
00160 kind = kROOTD_GLOBUS;
00161 retval = TAuthenticate::GetAuthReUse();
00162 if ((rc = tAuth->AuthExists(ssuj, TAuthenticate::kGlobus, options,
00163 &kind, &retval, &GlobusCheckSecCtx)) == 1) {
00164
00165 return 1;
00166 }
00167
00168 if (rc == -2) {
00169 return rc;
00170 }
00171 if (kind == kROOTD_ERR) {
00172 return 0;
00173 }
00174
00175 if (retval == 0 || kind != kROOTD_GLOBUS) {
00176 if (gDebug > 2)
00177 Info("GlobusAuthenticate", "server does not support Globus authentication");
00178 return -1;
00179 }
00180
00181 if (sock->GetRemoteProtocol() < 18) {
00182 TString isuj;
00183 if (GlobusIssuerName(isuj)) {
00184 if (gDebug > 0)
00185 Error("GlobusAuthenticate",
00186 "unable to determine issuer name from certificate");
00187 return 0;
00188 }
00189
00190 char buf[20];
00191 sprintf(buf, "%d", (int) (isuj.Length() + 1));
00192 if ((bsnd = sock->Send(buf, kMESS_STRING)) != (int) (strlen(buf)+1)) {
00193 if (gDebug > 0)
00194 Error("GlobusAuthenticate",
00195 "Length of Issuer name not send correctly: bytes sent: %d (tot len: %d)",
00196 bsnd - 1, strlen(buf));
00197 return 0;
00198 }
00199
00200 if ((bsnd = sock->Send(isuj.Data(), kMESS_STRING)) < (Int_t)(isuj.Length()+1)) {
00201 if (gDebug > 0)
00202 Error("GlobusAuthenticate",
00203 "Issuer name not send correctly: bytes sent: %d (tot len: %d)",
00204 bsnd - 1, isuj.Length());
00205 return 0;
00206 }
00207 }
00208
00209 sock->Recv(retval, kind);
00210 if (kind == kROOTD_ERR) {
00211 if (gDebug > 0)
00212 Error("GlobusAuthenticate",
00213 "recv host subj: host unable init credentials");
00214 return 3;
00215 }
00216 if (kind != kROOTD_GLOBUS) {
00217 if (gDebug > 0)
00218 Error("GlobusAuthenticate",
00219 "recv host subj: unexpected message from daemon:"
00220 " kind: %d (expecting: %d)",kind, kROOTD_GLOBUS);
00221 } else {
00222 if (retval == 0) {
00223 if (gDebug > 0)
00224 Error("GlobusAuthenticate",
00225 "recv host subj: host not able to authenticate this CA");
00226 return 0;
00227 } else {
00228 if (gDebug > 3)
00229 Info("GlobusAuthenticate",
00230 "recv host subj: buffer length is: %d", retval);
00231 host_subj = new char[retval + 1];
00232 brcv = sock->Recv(host_subj, retval, kind);
00233 if (gDebug > 3)
00234 Info("GlobusAuthenticate",
00235 "received host_subj: %s: (%d)", host_subj, brcv);
00236 if (strlen(host_subj) < (UInt_t)(retval - 1) ||
00237 retval <= 1) {
00238 if (gDebug > 0) {
00239 Error("GlobusAuthenticate",
00240 "recv host subj: did not receive all the bytes"
00241 " (recv: %d, due >%d)", brcv, retval);
00242 Error("GlobusAuthenticate", "recv host subj: (%d) %s",
00243 strlen(host_subj), host_subj);
00244 }
00245 if (host_subj) delete[] host_subj;
00246 return 0;
00247 }
00248 }
00249 }
00250
00251 if (gDebug > 2)
00252 Info("GlobusAuthenticate", "Host subject: %s", host_subj);
00253
00254
00255
00256 int sockFd = sock->GetDescriptor();
00257 FILE *sockStream = fdopen(sockFd, "w+");
00258
00259
00260 gssReqFlags =
00261 localCallEnv >
00262 0 ? (GSS_C_DELEG_FLAG | GSS_C_MUTUAL_FLAG) : GSS_C_MUTUAL_FLAG;
00263 if (gDebug > 3)
00264 Info("GlobusAuthenticate",
00265 " gssReqFlags: %p, GlbCredentials: %p", gssReqFlags, gGlbCredHandle);
00266
00267
00268 if ((majStat =
00269 globus_gss_assist_init_sec_context(&minStat, gGlbCredHandle,
00270 &glbContextHandle, host_subj,
00271 gssReqFlags, &gssRetFlags,
00272 &glbTokenStatus,
00273 globus_gss_assist_token_get_fd,
00274 (void *) sockStream,
00275 globus_gss_assist_token_send_fd,
00276 (void *) sockStream)) !=
00277 GSS_S_COMPLETE) {
00278 if (gDebug > 0)
00279 GlobusError("GlobusAuthenticate: gss_assist_init_sec_context",
00280 majStat, minStat, glbTokenStatus);
00281 if (host_subj) delete[] host_subj;
00282 sock->Send(0,kROOTD_ERR);
00283 return 0;
00284 } else {
00285
00286 expDate.Set(expDate.Convert() + GlobusGetSecContLifeTime(glbContextHandle));
00287 if (gDebug > 2) {
00288 Info("GlobusAuthenticate", "authenticated to host %s", hostFQDN);
00289 Info("GlobusAuthenticate", "expiring on '%s'", expDate.AsString());
00290 }
00291 if (fflush(sockStream) != 0) {
00292 Warning("GlobusAuthenticate", "unable to fflush socket:"
00293 " may cause authentication problems on server side");
00294 }
00295 auth = 1;
00296 }
00297
00298
00299 if (host_subj) delete[] host_subj;
00300
00301
00302 int nrec = sock->Recv(retval, type);
00303
00304 Int_t rsaKey = 0;
00305 if (type == kROOTD_RSAKEY) {
00306 if (retval <= 0 || retval > 2)
00307 Warning("GlobusAuthenticate",
00308 "problems recvn RSA key flag: got message %d, retval: %d",
00309 type, retval);
00310 rsaKey = retval - 1;
00311
00312
00313 TAuthenticate::SendRSAPublicKey(sock,rsaKey);
00314
00315
00316 nrec = sock->Recv(retval, type);
00317 }
00318
00319 if (type != kROOTD_GLOBUS || retval < 1)
00320 Warning("GlobusAuthenticate",
00321 "problems recvn (user,offset) length (%d:%d bytes:%d)", type,
00322 retval, nrec);
00323 char *rfrm = new char[retval + 1];
00324 nrec = sock->Recv(rfrm, retval + 1, type);
00325 if (type != kMESS_STRING)
00326 Warning("GlobusAuthenticate",
00327 "username and offset not received (%d:%d)", type, nrec);
00328 else if (gDebug > 2)
00329 Info("GlobusAuthenticate", "logging remotely as %s ", rfrm);
00330
00331
00332 char *lUser = new char[retval];
00333 Int_t offSet = -1;
00334 sscanf(rfrm, "%s %d", lUser, &offSet);
00335
00336
00337 user = lUser;
00338
00339
00340 char *token = 0;
00341 if (TAuthenticate::GetAuthReUse() == 1 && offSet > -1) {
00342 if (TAuthenticate::SecureRecv(sock, 1, rsaKey, &token) == -1) {
00343 Warning("GlobusAuthenticate",
00344 "Problems secure-receiving token -"
00345 " may result in corrupted token");
00346 }
00347 if (gDebug > 3)
00348 Info("GlobusAuthenticate", "received from server: token: '%s' ",
00349 token);
00350 } else {
00351 token = StrDup("");
00352 }
00353
00354
00355 GlobusGetDetails(localCallEnv, 0, details);
00356 TRootSecContext *ctx =
00357 tAuth->GetHostAuth()->CreateSecContext((const char *)lUser,
00358 hostFQDN, (Int_t)TAuthenticate::kGlobus, offSet,
00359 details, (const char *)token, expDate,
00360 (void *)glbContextHandle, rsaKey);
00361
00362 tAuth->SetSecContext(ctx);
00363
00364
00365 sock->Recv(server_auth, kind);
00366 if (gDebug > 2)
00367 Info("GlobusAuthenticate", "received auth status from server: %d (%d)",
00368 server_auth, kind);
00369
00370 if (auth && !server_auth) {
00371 Warning("GlobusAuthenticate",
00372 " it looks like server did not authenticate: probably a problem with mapping");
00373 auth = 0;
00374 }
00375
00376
00377 if (rfrm) delete[] rfrm;
00378 if (lUser) delete[] lUser;
00379 if (token) delete[] token;
00380
00381
00382 return auth;
00383 }
00384
00385
00386 int GlobusGetDelCred()
00387 {
00388
00389
00390
00391
00392 struct shmid_ds shm_ds;
00393 OM_uint32 majStat = 0;
00394 OM_uint32 minStat = 0;
00395
00396 if (gDebug > 2)
00397 Info("GlobusGetDelCred:", "Enter ...");
00398
00399
00400 gss_buffer_t databuf = (gss_buffer_t) shmat(gShmIdCred, 0, 0);
00401
00402
00403
00404 gss_buffer_t credential =
00405 (gss_buffer_t) new char[sizeof(gss_buffer_desc) + databuf->length];
00406 credential->length = databuf->length;
00407 credential->value =
00408 (void *) ((char *) credential + sizeof(size_t) + sizeof(void *));
00409 void *dbufval =
00410 (void *) ((char *) databuf + sizeof(size_t) + sizeof(void *));
00411 memmove(credential->value, dbufval, credential->length);
00412 if ((majStat =
00413 gss_import_cred(&minStat, &gGlbDelCredHandle, 0, 0, credential, 0,
00414 0)) != GSS_S_COMPLETE) {
00415 if (gDebug > 0)
00416 GlobusError("GlobusGetDelCred: gss_import_cred", majStat, minStat, 0);
00417 return 1;
00418 } else if (gDebug > 3)
00419 Info("GlobusGetDelCred:",
00420 "Globus Credentials successfully imported (0x%x)",
00421 gGlbDelCredHandle);
00422
00423 if (credential) delete[] credential;
00424
00425
00426 int rc = shmdt((const void *) databuf);
00427 if (rc != 0) {
00428 if (gDebug > 0)
00429 Info("GlobusGetDelCred:",
00430 "unable to detach from shared memory segment (rc=%d)", rc);
00431 }
00432 if (gDebug > 3) {
00433 rc = shmctl(gShmIdCred, IPC_STAT, &shm_ds);
00434 Info("GlobusGetDelCred:",
00435 "Process: uid: %d, euid: %d - Buffer: uid: %d, cuid: %d",
00436 getuid(), geteuid(), shm_ds.shm_perm.uid, shm_ds.shm_perm.cuid);
00437 }
00438
00439 rc = shmctl(gShmIdCred, IPC_RMID, &shm_ds);
00440 if (rc == 0) {
00441 if (gDebug > 2)
00442 Info("GlobusGetDelCred:",
00443 "shared memory segment successfully marked as destroyed");
00444 } else {
00445 Warning("GlobusGetDelCred:",
00446 "unable to mark segment %d as destroyed", gShmIdCred);
00447 }
00448
00449 return 0;
00450 }
00451
00452
00453 void GlobusError(const char *mess, OM_uint32 majs, OM_uint32 mins, int toks)
00454 {
00455
00456
00457 char *glbErr = 0;
00458
00459 if (!globus_gss_assist_display_status_str
00460 (&glbErr, (char *)mess, majs, mins, toks)) {
00461 Error("GlobusError:","%s (majst=%d,minst=%d,tokst:%d)",
00462 glbErr, majs, mins, toks);
00463 } else {
00464 Error("GlobusError:","%s (not resolved) (majst=%d,minst=%d,tokst:%d)",
00465 mess, majs, mins, toks);
00466 }
00467
00468 if (glbErr) delete[] glbErr;
00469 }
00470
00471
00472 Int_t GlobusGetLocalEnv(Int_t *localEnv, TString protocol)
00473 {
00474
00475
00476
00477 int retval = 0;
00478
00479
00480 TApplication *lApp = gROOT->GetApplication();
00481 if (gDebug > 2) {
00482 int i = 0;
00483 for (; i < lApp->Argc(); i++) {
00484 Info("GlobusGetLocalEnv", "application arguments: %d: %s", i,
00485 lApp->Argv(i));
00486 }
00487 }
00488
00489 *localEnv = 0;
00490 if (lApp != 0) {
00491 if (gROOT->IsProofServ()) {
00492
00493 if (gDebug > 3) {
00494 Info("GlobusGetLocalEnv",
00495 "PROOF environment, called by the MASTER/SLAVE");
00496 Info("GlobusGetLocalEnv",
00497 "string with pointer to del cred is 0x%x",
00498 gGlbDelCredHandle);
00499 }
00500 *localEnv = 2;
00501 gShmIdCred = -1;
00502 const char *p = gSystem->Getenv("ROOTSHMIDCRED");
00503 if (p)
00504 gShmIdCred = strtol(p, (char **)0, 10);
00505 if (gShmIdCred <= 0) {
00506 Info("GlobusGetLocalEnv",
00507 "delegate credentials undefined");
00508 retval = 1;
00509 }
00510 } else {
00511 if (strstr(protocol.Data(), "proof") != 0) {
00512 if (gDebug > 3)
00513 Info("GlobusGetLocalEnv",
00514 "PROOF environment, called by the CLIENT");
00515 *localEnv = 1;
00516 } else if (strstr(protocol.Data(), "root") != 0 ||
00517 strstr(protocol.Data(), "sock") != 0) {
00518 if (gDebug > 3)
00519 Info("GlobusGetLocalEnv",
00520 "ROOT environment (%s)", protocol.Data());
00521 } else {
00522 if (gDebug > 0)
00523 Info("GlobusGetLocalEnv",
00524 "unable to recognize the environment"
00525 " (protocol: %s)-> assume ROOT",protocol.Data());
00526 }
00527 }
00528 } else {
00529 if (gDebug > 0)
00530 Info("GlobusGetLocalEnv",
00531 "unable to get pointer to current application"
00532 " -> assume ROOT environment");
00533 }
00534
00535 return retval;
00536 }
00537
00538
00539 Int_t GlobusNameFromCred(gss_cred_id_t cred, TString &subjName)
00540 {
00541
00542
00543
00544 if (gDebug > 2)
00545 Info("GlobusNamesFromCred", "Enter: Handle: 0x%p", cred);
00546
00547
00548 OM_uint32 majStat = 0;
00549 OM_uint32 minStat = 0;
00550 gss_name_t name;
00551 OM_uint32 lifeTime;
00552 gss_cred_usage_t credUsage;
00553 gss_OID_set mech;
00554 if ((majStat = gss_inquire_cred(&minStat, cred, &name,
00555 &lifeTime, &credUsage, &mech)) != GSS_S_COMPLETE) {
00556 if (gDebug > 0)
00557 GlobusError("GlobusNameFromCred: gss_inquire_cred",
00558 majStat, minStat,0);
00559 return 1;
00560 }
00561 gss_buffer_desc outBuf;
00562 gss_OID nameType;
00563 if ((majStat = gss_display_name(&minStat, name, &outBuf,
00564 &nameType)) != GSS_S_COMPLETE) {
00565 if (gDebug > 0)
00566 GlobusError("GlobusNameFromCred: gss_display_name",
00567 majStat, minStat, 0);
00568 return 2;
00569 } else
00570 subjName = TString((const char *)outBuf.value);
00571
00572
00573 if (gDebug > 2)
00574 Info("GlobusNameFromCred", "subject name: %s", subjName.Data());
00575
00576
00577 return 0;
00578 }
00579
00580
00581 Int_t GlobusGetSecContLifeTime(gss_ctx_id_t ctx)
00582 {
00583
00584
00585 OM_uint32 majStat = 0;
00586 OM_uint32 minStat = 0;
00587 OM_uint32 gssRetFlags = 0;
00588 OM_uint32 glbContLifeTime = 0;
00589 gss_OID mechType;
00590 gss_name_t *targName = 0, *name = 0;
00591 int dum1, dum2;
00592
00593 if (ctx != 0 && ctx != GSS_C_NO_CONTEXT) {
00594 if ((majStat = gss_inquire_context(&minStat, ctx, name,
00595 targName, &glbContLifeTime, &mechType, &gssRetFlags,
00596 &dum1, &dum2)) != GSS_S_COMPLETE) {
00597 if (gDebug > 0)
00598 GlobusError("GlobusGetSecContLifeTime: gss_inquire_context",
00599 majStat, minStat, 0);
00600 return 0;
00601 } else {
00602 if (gDebug > 3)
00603 Info("GlobusGetSecContLifeTime"," remaining lifetime: %d sec",
00604 glbContLifeTime);
00605 return (Int_t)glbContLifeTime;
00606 }
00607 }
00608 return 0;
00609 }
00610
00611
00612 Int_t GlobusCleanupContext(gss_ctx_id_t ctx)
00613 {
00614
00615
00616 OM_uint32 majStat = 0;
00617 OM_uint32 minStat = 0;
00618
00619
00620 if ((majStat = gss_delete_sec_context(&minStat, &ctx,
00621 GSS_C_NO_BUFFER)) != GSS_S_COMPLETE) {
00622 if (gDebug > 0)
00623 GlobusError("GlobusCleanupContext: gss_delete_sec_context",
00624 majStat,minStat, 0);
00625 return 0;
00626 }
00627
00628 return 1;
00629 }
00630
00631
00632 Int_t GlobusCheckSecCtx(const char *subj, TRootSecContext *ctx)
00633 {
00634
00635
00636
00637
00638
00639 Int_t rc = 0;
00640
00641 if (ctx->IsActive())
00642 rc = GlobusCheckSecContext(subj,(gss_ctx_id_t)(ctx->GetContext()));
00643
00644 return rc;
00645 }
00646
00647
00648 void GlobusCleanupShm()
00649 {
00650
00651
00652 if (gROOT->IsProofServ()) {
00653 struct shmid_ds shm_ds;
00654 int rc;
00655
00656 gShmIdCred = -1;
00657 const char *p = gSystem->Getenv("ROOTSHMIDCRED");
00658 if (p)
00659 gShmIdCred = strtol(p, (char **)0, 10);
00660 if (gShmIdCred != -1) {
00661 if ((rc = shmctl(gShmIdCred, IPC_RMID, &shm_ds)) != 0) {
00662 if ((rc == EINVAL) || (rc == EIDRM)) {
00663 if (gDebug > 3)
00664 Info("GlobusCleanupShm:",
00665 "credentials shared memory segment %s"
00666 "already marked as destroyed");
00667 } else {
00668 Warning("GlobusCleanupShm:",
00669 "unable to mark segment as destroyed (error: 0x%x)",
00670 rc);
00671 }
00672 } else if (gDebug > 3)
00673 Info("GlobusCleanupShm:",
00674 "shared memory segment %d marked for destruction",
00675 gShmIdCred);
00676 } else if (gDebug > 3) {
00677 Info("GlobusCleanupShm:",
00678 "gShmIdCred not defined in this session");
00679 }
00680 }
00681 }
00682
00683
00684 Int_t GlobusCheckSecContext(const char *subjName, gss_ctx_id_t ctx)
00685 {
00686
00687
00688
00689
00690
00691 if (!ctx)
00692 return 0;
00693
00694 int rc = 0;
00695 OM_uint32 majStat = 0;
00696 OM_uint32 minStat = 0;
00697 OM_uint32 gssRetFlags = 0;
00698 OM_uint32 glbContLifeTime = 0;
00699
00700 if (gDebug > 2)
00701 Info("GlobusCheckSecContext", "checking subj:%s", subjName);
00702
00703
00704 Int_t dum1, dum2;
00705 gss_OID mechType;
00706 gss_name_t *targName = 0;
00707 gss_name_t name;
00708 if (ctx != 0 && ctx != GSS_C_NO_CONTEXT) {
00709
00710 if ((majStat = gss_inquire_context(&minStat, ctx, &name,
00711 targName, &glbContLifeTime, &mechType,
00712 &gssRetFlags, &dum1, &dum2)) != GSS_S_COMPLETE) {
00713 if (gDebug > 0)
00714 GlobusError("GlobusCheckSecContext: gss_inquire_context",
00715 majStat, minStat, 0);
00716 rc = -1;
00717 } else {
00718 gss_buffer_desc nameBuffer;
00719
00720 if ((majStat = gss_display_name(&minStat, name, &nameBuffer,
00721 GLOBUS_NULL)) != GSS_S_COMPLETE) {
00722 if (gDebug > 0)
00723 GlobusError("GlobusCheckSecContext: gss_display_name",
00724 majStat, minStat, 0);
00725 nameBuffer.length = 0;
00726 nameBuffer.value = GLOBUS_NULL;
00727 } else {
00728 char *theName = new char[nameBuffer.length+1];
00729 strncpy(theName,(char *)(nameBuffer.value),(Int_t)(nameBuffer.length));
00730 theName[nameBuffer.length]= '\0';
00731 if (gDebug > 2)
00732 Info("GlobusCheckSecContext","with subject name: %s (%d)",
00733 theName, nameBuffer.length);
00734 if (!strcmp(theName, subjName)) {
00735 if (gDebug > 2)
00736 Info("GlobusCheckSecContext",
00737 "client already authenticated (remaining lifetime: %d sec)",
00738 glbContLifeTime);
00739 rc = 1;
00740 }
00741
00742 if (theName)
00743 delete[] theName;
00744 if ((majStat = gss_release_name(&minStat, &name))
00745 != GSS_S_COMPLETE) {
00746 if (gDebug > 0)
00747 GlobusError("GlobusCheckSecContext: gss_release_name",
00748 majStat, minStat, 0);
00749 }
00750 }
00751 }
00752
00753 } else {
00754 rc = -1;
00755 }
00756
00757 return rc;
00758 }
00759
00760
00761 int GlobusGetCredHandle(Int_t localEnv, gss_cred_id_t * credHandle)
00762 {
00763
00764
00765
00766 int retval = 0;
00767 OM_uint32 majStat = 0;
00768 OM_uint32 minStat = 0;
00769
00770 if (gDebug > 2)
00771 Info("GlobusGetCredHandle", "Enter: LocalEnv: %d", localEnv);
00772
00773 if (localEnv == 2) {
00774
00775
00776
00777 if (gGlbDelCredHandle == GSS_C_NO_CREDENTIAL) {
00778 if (GlobusGetDelCred()) {
00779 if (gDebug > 0)
00780 Error("GlobusGetCredHandle",
00781 "unable to fetch valid credentials from the shared memory segment");
00782 retval = 1;
00783 goto exit;
00784 }
00785 }
00786 *credHandle = gGlbDelCredHandle;
00787 } else {
00788
00789
00790
00791
00792 if ((majStat =
00793 globus_gss_assist_acquire_cred(&minStat, GSS_C_INITIATE,
00794 credHandle)) != GSS_S_COMPLETE) {
00795
00796
00797 if (isatty(0) && isatty(1)) {
00798
00799
00800 TString det;
00801 GlobusGetDetails(localEnv, 1, det);
00802
00803 if (gDebug > 3) {
00804 GlobusError("GlobusNameFromCred: gss_display_name",
00805 majStat, minStat, 0);
00806 Info("GlobusGetCredHandle",
00807 "Failed to acquire credentials: trying to initialize proxies ...");
00808 }
00809
00810
00811
00812 TString initDur(gEnv->GetValue("Globus.ProxyDuration", "default"));
00813 if (!initDur.Contains("default")) {
00814 initDur.Insert(0,"-hours ");
00815 if (gDebug > 2)
00816 Info("GlobusGetCredHandle", "initDur: %s (%s)", initDur.Data(),
00817 gEnv->GetValue("Globus.ProxyDuration", "default"));
00818 } else
00819 initDur = TString("");
00820
00821
00822 TString initBit(gEnv->GetValue("Globus.ProxyKeyBits", "default"));
00823 if (!initBit.Contains("default")) {
00824 initBit.Insert(0,"-bits ");
00825 if (gDebug > 2)
00826 Info("GlobusGetCredHandle", "initBit: %s (%s)", initBit.Data(),
00827 gEnv->GetValue("Globus.ProxyKeyBits", "default"));
00828 } else
00829 initBit = TString("");
00830
00831
00832 TString initPxy;
00833 if (gSystem->Getenv("X509_USER_PROXY")) {
00834 initPxy = Form("-out %s", gSystem->Getenv("X509_USER_PROXY"));
00835 if (gDebug > 3)
00836 Info("GlobusGetCredHandle", "initPxy: %s", initPxy.Data());
00837 }
00838
00839
00840 TString initEnv(Form("export X509_CERT_DIR=%s",
00841 gSystem->Getenv("X509_CERT_DIR")));
00842 initEnv += TString(Form("; export X509_USER_CERT=%s",
00843 gSystem->Getenv("X509_USER_CERT")));
00844 initEnv += TString(Form("; export X509_USER_KEY=%s",
00845 gSystem->Getenv("X509_USER_KEY")));
00846 if (gDebug > 3)
00847 Info("GlobusGetCredHandle", "initEnv: %s", initEnv.Data());
00848
00849
00850
00851 TString proxyInit;
00852 if (gSystem->Getenv("GLOBUS_LOCATION"))
00853 proxyInit = TString("source $GLOBUS_LOCATION/etc/globus-user-env.sh; ");
00854 proxyInit += initEnv;
00855 proxyInit += Form("; grid-proxy-init %s %s %s",
00856 initDur.Data(), initBit.Data(), initPxy.Data());
00857 gSystem->Exec(proxyInit);
00858
00859
00860 if ((majStat =
00861 globus_gss_assist_acquire_cred(&minStat, GSS_C_INITIATE,
00862 credHandle)) !=
00863 GSS_S_COMPLETE) {
00864 if (gDebug > 0)
00865 GlobusError("GlobusGetCredHandle: gss_assist_acquire_cred",
00866 majStat, minStat, 0);
00867 retval = 3;
00868 goto exit;
00869 }
00870 } else {
00871 Warning("GlobusGetCredHandle",
00872 "not a tty: cannot prompt for credentials, returning failure");
00873 retval = 3;
00874 goto exit;
00875 }
00876 }
00877 }
00878
00879 exit:
00880 return retval;
00881 }
00882
00883
00884 void GlobusGetDetails(Int_t localEnv, Int_t opt, TString &details)
00885 {
00886
00887
00888
00889
00890 if (localEnv < 2) {
00891
00892
00893 Int_t reUse = TAuthenticate::GetAuthReUse();
00894 Int_t prompt = TAuthenticate::GetPromptUser();
00895 if (gDebug > 2)
00896 Info("GlobusGetDetails", "prompt: %d, reUse: %d", prompt, reUse);
00897
00898
00899 TString ddir = "~/.globus";
00900 TString dcer = "usercert.pem";
00901 TString dkey = "userkey.pem";
00902 TString dadi = "/etc/grid-security/certificates";
00903
00904
00905 if (strlen(TAuthenticate::GetDefaultUser()) > 0) {
00906 TString dets = TAuthenticate::GetDefaultUser();
00907 TString t;
00908 Int_t from = 0;
00909 while (dets.Tokenize(t,from," ")) {
00910 if (t.BeginsWith("cd:"))
00911 ddir = t.ReplaceAll("cd:", "");
00912 else if (t.BeginsWith("cf:"))
00913 dcer = t.ReplaceAll("cf:", "");
00914 else if (t.BeginsWith("kf:"))
00915 dkey = t.ReplaceAll("kf:", "");
00916 else if (t.BeginsWith("ad:"))
00917 dadi = t.ReplaceAll("ad:", "");
00918 }
00919 }
00920
00921
00922 if (TAuthenticate::GetPromptUser()) {
00923 TString ppt(Form(" Local Globus settings (%s %s %s %s)\n"
00924 " Enter <key>:<new value> to change: ",
00925 ddir.Data(), dcer.Data(), dkey.Data(), dadi.Data()));
00926
00927 TString indet;
00928 if (!gROOT->IsProofServ()) {
00929 indet = Getline(ppt);
00930
00931 indet.Remove(TString::kTrailing, '\n');
00932 if (indet.Length() > 0) {
00933 TString t;
00934 Int_t from = 0;
00935 while (indet.Tokenize(t,from," ")) {
00936 if (t.BeginsWith("cd:"))
00937 ddir = t.ReplaceAll("cd:", "");
00938 else if (t.BeginsWith("cf:"))
00939 dcer = t.ReplaceAll("cf:", "");
00940 else if (t.BeginsWith("kf:"))
00941 dkey = t.ReplaceAll("kf:", "");
00942 else if (t.BeginsWith("ad:"))
00943 dadi = t.ReplaceAll("ad:", "");
00944 }
00945 }
00946 } else {
00947 Warning("GlobusGetDetails",
00948 "proofserv: cannot prompt for info");
00949 }
00950 }
00951
00952
00953 details = Form("pt:%d ru:%d %s %s %s %s",
00954 TAuthenticate::GetPromptUser(),
00955 TAuthenticate::GetAuthReUse(),
00956 ddir.Data(), dcer.Data(), dkey.Data(), dadi.Data());
00957
00958
00959 if (opt > 0) {
00960
00961
00962 gSystem->ExpandPathName(ddir);
00963 gSystem->ExpandPathName(dcer);
00964 gSystem->ExpandPathName(dkey);
00965 gSystem->ExpandPathName(dadi);
00966
00967
00968 if (!ddir.BeginsWith("/"))
00969 ddir.Insert(0, Form("%s/.globus/", gSystem->HomeDirectory()));
00970 if (!dcer.BeginsWith("/"))
00971 dcer.Insert(0, Form("%s/", ddir.Data()));
00972 if (!dkey.BeginsWith("/"))
00973 dkey.Insert(0, Form("%s/", ddir.Data()));
00974 if (!dadi.BeginsWith("/"))
00975 dadi.Insert(0, Form("%s/.globus/", gSystem->HomeDirectory()));
00976
00977 if (gDebug > 3)
00978 Info("GlobusSetCertificates", "after expansion: %s %s %s",
00979 dcer.Data(), dkey.Data(), dadi.Data());
00980
00981 gSystem->Setenv("X509_CERT_DIR", dadi);
00982 gSystem->Setenv("X509_USER_CERT", dcer);
00983 gSystem->Setenv("X509_USER_KEY", dkey);
00984 }
00985 }
00986
00987
00988 return;
00989 }
00990
00991
00992 Int_t GlobusIssuerName(TString &issuerName)
00993 {
00994
00995
00996
00997
00998 if (gDebug > 2)
00999 Info("GlobusIssuerName", "enter");
01000
01001
01002 TString fn = gSystem->Getenv("X509_USER_PROXY");
01003 if (fn.Length() <= 0)
01004 fn = Form("/tmp/x509up_u%d",gSystem->GetUid());
01005 if (gSystem->AccessPathName(fn, kReadPermission)) {
01006 TString emsg = Form("cannot read requested file(s): %s ", fn.Data());
01007
01008 fn = gSystem->Getenv("X509_USER_CERT");
01009 if (fn.Length() <= 0)
01010 fn = Form("%s/.globus/usercert.pem",gSystem->HomeDirectory());
01011 if (gSystem->AccessPathName(fn, kReadPermission)) {
01012 emsg += fn;
01013 Error("GlobusIssuerName", emsg.Data());
01014 return 1;
01015 }
01016 }
01017
01018
01019 X509 *xcert = 0;
01020 FILE *fcert = fopen(fn.Data(), "r");
01021 if (!fcert) {
01022 Error("GlobusIssuerName", "unable to open file %s", fn.Data());
01023 return 1;
01024 }
01025
01026
01027 Bool_t notfound = kTRUE;
01028 while (notfound && PEM_read_X509(fcert, &xcert, 0, 0)) {
01029
01030 char *in = X509_NAME_oneline(X509_get_issuer_name(xcert), 0, 0);
01031
01032 char *cn = X509_NAME_oneline(X509_get_subject_name(xcert), 0, 0);
01033 if (strncmp(in, cn, strlen(in))) {
01034
01035 issuerName = in;
01036 notfound = kFALSE;
01037 }
01038 free(in); free(cn);
01039 }
01040 fclose(fcert);
01041
01042
01043 if (notfound) {
01044 Error("GlobusIssuerName", "certificate not found in file %s", fn.Data());
01045 return 1;
01046 }
01047
01048
01049 if (gDebug > 2)
01050 Info("GlobusIssuerName", "issuer name: %s", issuerName.Data());
01051
01052
01053 return 0;
01054 }