/******************************************************************************/ /* */ /* X r d S e c s s s A d m i n . c c */ /* */ /* (c) 2008 by the Board of Trustees of the Leland Stanford, Jr., University */ /* All Rights Reserved */ /* Produced by Andrew Hanushevsky for Stanford University under contract */ /* DE-AC02-76-SFO0515 with the Department of Energy */ /* */ /* This file is part of the XRootD software suite. */ /* */ /* XRootD is free software: you can redistribute it and/or modify it under */ /* the terms of the GNU Lesser General Public License as published by the */ /* Free Software Foundation, either version 3 of the License, or (at your */ /* option) any later version. */ /* */ /* XRootD is distributed in the hope that it will be useful, but WITHOUT */ /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */ /* License for more details. */ /* */ /* You should have received a copy of the GNU Lesser General Public License */ /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ /* COPYING (GPL license). If not, see . */ /* */ /* The copyright holder's institutional names and contributor's names may not */ /* be used to endorse or promote products derived from this software without */ /* specific prior written permission of the institution or contributor. */ /******************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include "XrdOuc/XrdOucErrInfo.hh" #include "XrdSys/XrdSysHeaders.hh" #include "XrdSys/XrdSysPlatform.hh" #include "XrdSys/XrdSysTimer.hh" #include "XrdSecsss/XrdSecsssKT.hh" /******************************************************************************/ /* D e f i n e s */ /******************************************************************************/ #define eMsg(x) cerr < 1 && '-' == *argv[1]) while ((c = getopt(argc,argv,validOpts)) && ((unsigned char)c != 0xff)) { switch(c) { case 'd': Opt.Debug = 1; break; case 'g': Opt.KeyGrup = optarg; break; case 'h': if ((Opt.Keep = atoi(optarg)) <= 0) Usage(1, "-s", optarg); break; case 'k': Opt.KeyName = optarg; break; case 'l': if ((Opt.KeyLen = atoi(optarg)) <= 0 || Opt.KeyLen > XrdSecsssKT::ktEnt::maxKLen) Usage(1, "-l", optarg); break; case 'n': if ((Opt.KeyNum = atoi(optarg)) <= 0) Usage(1, "-n", optarg); break; case 's': if ((int)strlen(optarg) > 1 || !index("cgknux", *optarg)) Usage(1, "-s", optarg); Opt.Sort = *optarg; break; case 'u': Opt.KeyUser = optarg; break; case 'x': if ((Opt.Expdt = getXDate(optarg)) < 0 || Opt.Expdt < (time(0)+60)) Usage(1, "-x", optarg); break; default: if (index(validOpts, optopt)) Usage(1, argv[optind-1], optarg); else {eMsg("Invalid option '" <= argc) {eMsg("Action not specified."); Usage(1);} // Verify the action // if (!strcmp(argv[optind], "add")) doIt = doAdd; else if (!strcmp(argv[optind], "install")) doIt = doInst; else if (!strcmp(argv[optind], "del")) doIt = doDel; else if (!strcmp(argv[optind], "list")) doIt = doList; else Usage(1, "parameter", argv[optind]); Opt.Action = argv[optind++]; // Make sure keyname is not too long // if (Opt.KeyName && (int)strlen(Opt.KeyName) >= XrdSecsssKT::ktEnt::NameSZ) {eMsg("Key name must be less than " <= XrdSecsssKT::ktEnt::UserSZ) {eMsg("User name must be less than " <= XrdSecsssKT::ktEnt::GrupSZ) {eMsg("group name must be less than " <(theVal); } // Do a date conversion // eP = strptime(cDate, "%D", &myTM); if (*eP) return -1; return mktime(&myTM); } /******************************************************************************/ /* i s N o */ /******************************************************************************/ int isNo(int dflt, const char *Msg1, const char *Msg2, const char *Msg3) { char Answer[8]; cerr <Data.Name, (Opt.KeyName ? Opt.KeyName : "nowhere")); strcpy(ktEnt->Data.User, (Opt.KeyUser ? Opt.KeyUser : "nobody")); strcpy(ktEnt->Data.Grup, (Opt.KeyGrup ? Opt.KeyGrup : "nogroup")); if (Opt.KeyLen > XrdSecsssKT::ktEnt::maxKLen) ktEnt->Data.Len = XrdSecsssKT::ktEnt::maxKLen; else if (Opt.KeyLen < 4) ktEnt->Data.Len = 4; else ktEnt->Data.Len = Opt.KeyLen/4*4; ktEnt->Data.Exp = Opt.Expdt; Opt.kTab->addKey(*ktEnt); // Now rewrite the file // if ((retc = Opt.kTab->Rewrite(Opt.Keep, numKeys, numTot, numExp))) {eMsg("Unable to add key to '" <(Opt.KeyNum); // Delete the keys from the key table // if (!(numDel = Opt.kTab->delKey(ktEnt))) {eMsg("No matching key(s) found."); return 4; } // It's possible that all of the keys were deleted. Check for that // if (Opt.kTab->keyList() == 0) {if (isNo(1, "No keys will remain in ", Opt.KeyFile, ". Delete file? (n | y): ")) {eMsg("No keys deleted!"); return 2;} unlink(Opt.KeyFile); return 0; } // Now rewrite the file // if ((retc = Opt.kTab->Rewrite(Opt.Keep, numKeys, numTot, numExp))) {eMsg("Unable to del key from '" <keyList(); while(ktP) {if (!XrdSecsssAdmin_isKey(Opt, ktP)) ktP->Data.Name[0] = '\0'; else numKeys++; ktP = ktP->Next; } if (!numKeys) {eMsg("No keys named " <setPath(Opt.KeyFile); if ((retc = Opt.kTab->Rewrite(Opt.Keep, numKeys, numTot, numExp))) {eMsg("Unable to install keytab '" <Data.Name, Opt.KeyName)) return 0; if (Opt.KeyUser && strcmp(ktP->Data.User, Opt.KeyUser)) return 0; if (Opt.KeyGrup && strcmp(ktP->Data.Grup, Opt.KeyGrup)) return 0; return 1; } /******************************************************************************/ /* X r d S e c s s s A d m i n _ H e r e */ /******************************************************************************/ int XrdSecsssAdmin_Here(char sType, XrdSecsssKT::ktEnt *ktX, XrdSecsssKT::ktEnt *ktS) { int n; char *sf1, *sf2; switch(sType) {case 'c': return ktX->Data.Crt < ktS->Data.Crt; case 'g': sf1 = ktX->Data.Grup; sf2 = ktS->Data.Grup; break; case 'k': sf1 = ktX->Data.Name; sf2 = ktS->Data.Name; break; case 'n': return (ktX->Data.ID & 0x7fffffff) < (ktS->Data.ID & 0x7fffffff); case 'u': sf1 = ktX->Data.User; sf2 = ktS->Data.User; break; case 'x': return ktX->Data.Exp < ktS->Data.Exp; default: return 0; } if ((n = strcmp(sf1, sf2))) return n < 0; return (ktX->Data.ID & 0x7fffffff) < (ktS->Data.ID & 0x7fffffff); } /******************************************************************************/ /* X r d S e c s s s A d m i n _ l s t K e y */ /******************************************************************************/ int XrdSecsssAdmin_lstKey(XrdsecsssAdmin_Opts &Opt) { static const char Hdr1[] = " Number Len Date/Time Created Expires Keyname User & Group\n"; // 12345678901 123 mm/dd/yy hh:mm:ss mm/dd/yy static const char Hdr2[] = " ------ --- --------- ------- -------- -------\n"; extern int XrdSecsssAdmin_isKey(XrdsecsssAdmin_Opts &Opt, XrdSecsssKT::ktEnt *ktP); XrdOucErrInfo eInfo; XrdSecsssKT::ktEnt *ktP, *ktSort = 0, *ktS, *ktSP, *ktX; char crfmt[] = "%D %T", exfmt[] = "%D"; char buff[128], crbuff[64], exbuff[16]; int retc, pHdr = 1; // Allocate the initial keytab // Opt.kTab = new XrdSecsssKT(&eInfo, Opt.KeyFile, XrdSecsssKT::isAdmin); if ((retc = eInfo.getErrInfo())) {if (retc == ENOENT) {eMsg("Keyfile '" <keyList())) {ktSort = ktP; ktP = ktP->Next; ktSort->Next = 0;} // Sort the list // while(ktP) {ktS = ktSort; ktSP = 0; ktX = ktP; ktP = ktP->Next; ktX->Next = 0; while(ktS) {if (XrdSecsssAdmin_Here(Opt.Sort, ktX, ktS)) {if (ktSP) {ktX->Next = ktS; ktSP->Next = ktX;} else {ktX->Next = ktSort; ktSort = ktX;} break; } ktSP = ktS; ktS = ktS->Next; } if (!ktS) ktSP->Next = ktX; } // List the keys // ktP = ktSort; while(ktP) {if (XrdSecsssAdmin_isKey(Opt, ktP)) {if (pHdr) {cout <Data.ID & 0x7fffffff), ktP->Data.Len); strftime(crbuff, sizeof(crbuff), crfmt, localtime(&ktP->Data.Crt)); if (!ktP->Data.Exp) strcpy(exbuff, "--------"); else strftime(exbuff,sizeof(exbuff),exfmt,localtime(&ktP->Data.Exp)); cout <Data.Name <<' ' <Data.User <<' ' <Data.Grup <Next; } // Check if we printed anything // if (pHdr) {if (Opt.KeyName) eMsg(Opt.KeyName <<" key not found in " <