/******************************************************************************/
/* */
/* 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 " <