XrdSecsssAdmin.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                     X r d S e c s s s A d m i n . c c                      */
00004 /*                                                                            */
00005 /* (c) 2008 by the Board of Trustees of the Leland Stanford, Jr., University  */
00006 /*                            All Rights Reserved                             */
00007 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00008 /*              DE-AC02-76-SFO0515 with the Department of Energy              */
00009 /******************************************************************************/
00010   
00011 //       $Id: XrdSecsssAdmin.cc 27487 2009-02-18 13:17:34Z ganis $
00012 
00013 const char *XrdSecsssAdminCVSID = "$Id: XrdSecsssAdmin.cc 27487 2009-02-18 13:17:34Z ganis $";
00014   
00015 #include <ctype.h>
00016 #include <limits.h>
00017 #include <stdlib.h>
00018 #include <stdio.h>
00019 #include <errno.h>
00020 #include <fcntl.h>
00021 #include <time.h>
00022 #include <sys/param.h>
00023 #include <sys/types.h>
00024 #include <sys/stat.h>
00025 
00026 #include "XrdOuc/XrdOucErrInfo.hh"
00027 #include "XrdSys/XrdSysHeaders.hh"
00028 #include "XrdSys/XrdSysPlatform.hh"
00029 #include "XrdSys/XrdSysTimer.hh"
00030 
00031 #include "XrdSecsss/XrdSecsssKT.hh"
00032   
00033 /******************************************************************************/
00034 /*                               D e f i n e s                                */
00035 /******************************************************************************/
00036   
00037 #define eMsg(x) cerr <<XrdpgmName <<": " <<x << endl
00038 
00039 struct XrdsecsssAdmin_Opts
00040       {XrdSecsssKT *kTab;
00041        const char  *Action;
00042        const char  *KeyName;
00043        const char  *KeyUser;
00044        const char  *KeyGrup;
00045        const char  *KeyFile;
00046        time_t       Expdt;
00047        int          Debug;
00048        int          Keep;
00049        int          KeyLen;
00050        int          KeyNum;
00051        char         Sort;
00052 
00053        XrdsecsssAdmin_Opts() : kTab(0), Action(0), KeyName(0), KeyUser(0),
00054                                KeyGrup(0), KeyFile(0),
00055                                Expdt(0), Debug(0), Keep(3), KeyLen(32),
00056                                KeyNum(-1), Sort('k') {}
00057       ~XrdsecsssAdmin_Opts() {}
00058 };
00059 
00060 /******************************************************************************/
00061 /*                               G l o b a l s                                */
00062 /******************************************************************************/
00063   
00064 static const char *XrdpgmName;
00065 
00066 /******************************************************************************/
00067 /*                                  m a i n                                   */
00068 /******************************************************************************/
00069   
00070 int main(int argc, char **argv)
00071 {
00072    extern char  *optarg;
00073    extern int    optopt, optind, opterr;
00074    extern int    XrdSecsssAdmin_addKey(XrdsecsssAdmin_Opts &Opt);
00075    extern int    XrdSecsssAdmin_delKey(XrdsecsssAdmin_Opts &Opt);
00076    extern int    XrdSecsssAdmin_insKey(XrdsecsssAdmin_Opts &Opt);
00077    extern int    XrdSecsssAdmin_lstKey(XrdsecsssAdmin_Opts &Opt);
00078    extern time_t getXDate(const char *cDate);
00079    extern void   Usage(int rc, const char *opn=0, const char *opv=0);
00080 
00081    XrdsecsssAdmin_Opts Opt;
00082    enum What2Do {doAdd, doInst, doDel, doList};
00083    char c, *sp;
00084    const char *validOpts = "dg:h:k:l:n:s:u:x:";
00085    int rc;
00086    What2Do doIt = doList;
00087 
00088 // Get the name of our program
00089 //
00090    XrdpgmName = ((sp = rindex(argv[0], '/')) ?  sp+1 : argv[0]);
00091 
00092 // Process the options
00093 //
00094    opterr = 0;
00095    if (argc > 1 && '-' == *argv[1]) 
00096       while ((c = getopt(argc,argv,validOpts))
00097          && ((unsigned char)c != 0xff))
00098      { switch(c)
00099        {
00100        case 'd': Opt.Debug = 1;
00101                  break;
00102        case 'g': Opt.KeyGrup = optarg;
00103                  break;
00104        case 'h': if ((Opt.Keep   = atoi(optarg)) <= 0) Usage(1, "-s", optarg);
00105                  break;
00106        case 'k': Opt.KeyName = optarg;
00107                  break;
00108        case 'l': if ((Opt.KeyLen = atoi(optarg)) <= 0 
00109                  ||   Opt.KeyLen > XrdSecsssKT::ktEnt::maxKLen)
00110                     Usage(1, "-l", optarg);
00111                  break;
00112        case 'n': if ((Opt.KeyNum = atoi(optarg)) <= 0) Usage(1, "-n", optarg);
00113                  break;
00114        case 's': if ((int)strlen(optarg) > 1 || !index("cgknux", *optarg))
00115                     Usage(1, "-s", optarg);
00116                  Opt.Sort = *optarg;
00117                  break;
00118        case 'u': Opt.KeyUser = optarg;
00119                  break;
00120        case 'x': if ((Opt.Expdt = getXDate(optarg)) < 0
00121                  ||   Opt.Expdt < (time(0)+60)) Usage(1, "-x", optarg);
00122                  break;
00123        default:  if (index(validOpts, optopt)) Usage(1, argv[optind-1], optarg);
00124                     else {eMsg("Invalid option '" <<argv[optind-1] <<"'");
00125                           Usage(1);
00126                          }
00127        }
00128      }
00129 
00130 // Make sure and opreration has been specified
00131 //
00132    if (optind >= argc) {eMsg("Action not specified."); Usage(1);}
00133 
00134 // Verify the action
00135 //
00136         if (!strcmp(argv[optind], "add"))      doIt = doAdd;
00137    else if (!strcmp(argv[optind], "install"))  doIt = doInst;
00138    else if (!strcmp(argv[optind], "del"))      doIt = doDel;
00139    else if (!strcmp(argv[optind], "list"))     doIt = doList;
00140    else Usage(1, "parameter", argv[optind]);
00141    Opt.Action = argv[optind++];
00142 
00143 // Make sure keyname is not too long
00144 //
00145    if (Opt.KeyName && (int)strlen(Opt.KeyName) >= XrdSecsssKT::ktEnt::NameSZ)
00146       {eMsg("Key name must be less than " <<XrdSecsssKT::ktEnt::NameSZ
00147             << " characters.");
00148        exit(4);
00149       }
00150 
00151 // Make sure username is not too long
00152 //
00153    if (Opt.KeyUser && (int)strlen(Opt.KeyUser) >= XrdSecsssKT::ktEnt::UserSZ)
00154       {eMsg("User name must be less than " <<XrdSecsssKT::ktEnt::UserSZ
00155             << " characters.");
00156        exit(4);
00157       }
00158 
00159 // Make sure group name is not too long
00160 //
00161    if (Opt.KeyGrup && (int)strlen(Opt.KeyGrup) >= XrdSecsssKT::ktEnt::GrupSZ)
00162       {eMsg("group name must be less than " <<XrdSecsssKT::ktEnt::GrupSZ
00163             << " characters.");
00164        exit(4);
00165       }
00166 
00167 // Provide default keyfile if none specified
00168 //
00169    if (optind < argc) Opt.KeyFile = argv[optind++];
00170       else            Opt.KeyFile = XrdSecsssKT::genFN();
00171 
00172 // Perform the action
00173 //
00174    switch(doIt)
00175          {case doAdd:  rc = XrdSecsssAdmin_addKey(Opt); break;
00176           case doDel:  rc = XrdSecsssAdmin_delKey(Opt); break;
00177           case doInst: rc = XrdSecsssAdmin_insKey(Opt); break;
00178           case doList: rc = XrdSecsssAdmin_lstKey(Opt); break;
00179           default:     rc = 16; eMsg("Internal processing error!");
00180          }
00181 
00182 // All done
00183 //
00184    if (Opt.kTab) delete Opt.kTab;
00185    exit(rc);
00186 }
00187 
00188 /******************************************************************************/
00189 /*                              g e t X D a t e                               */
00190 /******************************************************************************/
00191 
00192 time_t getXDate(const char *cDate)
00193 {
00194    struct tm myTM;
00195    char *eP;
00196    long  theVal;
00197 
00198 // if no slashes then this is number of days
00199 //
00200    if (!index(cDate, '/'))
00201       {theVal = strtol(cDate, &eP, 10);
00202        if (errno || *eP) return -1;
00203        if (theVal) theVal = XrdSysTimer::Midnight() + (86400*theVal);
00204        return static_cast<time_t>(theVal);
00205       }
00206 
00207 // Do a date conversion
00208 //
00209    eP = strptime(cDate, "%D", &myTM);
00210    if (*eP) return -1;
00211    return mktime(&myTM);
00212 }
00213   
00214 /******************************************************************************/
00215 /*                                  i s N o                                   */
00216 /******************************************************************************/
00217   
00218 int isNo(int dflt, const char *Msg1, const char *Msg2, const char *Msg3)
00219 {
00220    char Answer[8];
00221 
00222    cerr <<XrdpgmName <<": " <<Msg1 <<Msg2 <<Msg3;
00223    cin.getline(Answer, sizeof(Answer));
00224    if (!*Answer) return dflt;
00225 
00226    if (!strcmp("y",Answer) || !strcmp("ye",Answer) || !strcmp("yes",Answer))
00227       return 0;
00228    return 1;
00229 }
00230 
00231 /******************************************************************************/
00232 /*                                 U s a g e                                  */
00233 /******************************************************************************/
00234   
00235 void Usage(int rc, const char *opn, const char *opv)
00236 {
00237 // Check if we need to issue a message here
00238 //
00239    if (opn)
00240       {if (opv) eMsg("Invalid " <<opn <<" argument - " <<opv);
00241           else  eMsg(opn <<" argument not specified.");
00242       }
00243 
00244 cerr <<"\nUsage:   " <<XrdpgmName <<" [options] action\n";
00245 cerr <<"\nOptions: [-d] [-g grpname] [-h hold] [-k keyname] [-l keylen] [-n keynum]";
00246 cerr <<"\n         [-s {c|g|k|n|u|x}] [-u usrname] [-x {days | mm/dd/yy}]" <<endl;
00247 cerr <<"\nActions: {add | del | install | list} [keyfn]" <<endl;
00248 exit(rc);
00249 }
00250 
00251 /******************************************************************************/
00252 /*                 X r d S e c s s s A d m i n _ a d d K e y                  */
00253 /******************************************************************************/
00254   
00255 int  XrdSecsssAdmin_addKey(XrdsecsssAdmin_Opts &Opt)
00256 {
00257    XrdOucErrInfo eInfo;
00258    XrdSecsssKT::ktEnt *ktEnt;
00259    int retc, numKeys, numTot, numExp;
00260 
00261 // Allocate the initial keytab
00262 //
00263    Opt.kTab = new XrdSecsssKT(&eInfo, Opt.KeyFile, XrdSecsssKT::isAdmin);
00264    if ((retc = eInfo.getErrInfo()))
00265       {if (retc != ENOENT || isNo(0, "Keyfile '", Opt.KeyFile,
00266            "' does not exist. Create it? (y | n): ")) return 4;
00267       }
00268 
00269 // Construct a new KeyTab entry
00270 //
00271    ktEnt = new XrdSecsssKT::ktEnt;
00272    strcpy(ktEnt->Data.Name, (Opt.KeyName ? Opt.KeyName : "nowhere"));
00273    strcpy(ktEnt->Data.User, (Opt.KeyUser ? Opt.KeyUser : "nobody"));
00274    strcpy(ktEnt->Data.Grup, (Opt.KeyGrup ? Opt.KeyGrup : "nogroup"));
00275         if (Opt.KeyLen > XrdSecsssKT::ktEnt::maxKLen)
00276            ktEnt->Data.Len = XrdSecsssKT::ktEnt::maxKLen;
00277    else if (Opt.KeyLen < 4) ktEnt->Data.Len = 4;
00278    else ktEnt->Data.Len = Opt.KeyLen/4*4;
00279    ktEnt->Data.Exp = Opt.Expdt;
00280    Opt.kTab->addKey(*ktEnt);
00281 
00282 // Now rewrite the file
00283 //
00284    if ((retc = Opt.kTab->Rewrite(Opt.Keep, numKeys, numTot, numExp)))
00285       {eMsg("Unable to add key to '" <<Opt.KeyFile <<"'; " <<strerror(retc));
00286        retc = 8;
00287       } else {
00288        eMsg(numKeys <<(numKeys == 1 ? " key":" keys") <<" out of "
00289             <<numTot <<" kept (" <<numExp <<" expired).");
00290       }
00291 
00292 // All done
00293 //
00294    return retc;
00295 }
00296 
00297 /******************************************************************************/
00298 /*                 X r d S e c s s s A d m i n _ d e l K e y                  */
00299 /******************************************************************************/
00300   
00301 int  XrdSecsssAdmin_delKey(XrdsecsssAdmin_Opts &Opt)
00302 {
00303    XrdOucErrInfo eInfo;
00304    XrdSecsssKT::ktEnt ktEnt;
00305    int retc, numKeys, numTot, numExp, numDel;
00306 
00307 // Allocate the initial keytab
00308 //
00309    Opt.kTab = new XrdSecsssKT(&eInfo, Opt.KeyFile, XrdSecsssKT::isAdmin);
00310    if ((retc = eInfo.getErrInfo()))
00311       {if (retc == ENOENT) 
00312           {eMsg("Keyfile '" <<Opt.KeyFile <<"' does not exist.");}
00313        return 4;
00314       }
00315 
00316 // Construct deletion reference
00317 //
00318    if (Opt.KeyName) strcpy(ktEnt.Data.Name, Opt.KeyName);
00319    if (Opt.KeyUser) strcpy(ktEnt.Data.User, Opt.KeyUser);
00320    if (Opt.KeyGrup) strcpy(ktEnt.Data.Grup, Opt.KeyGrup);
00321    ktEnt.Data.ID = static_cast<long long>(Opt.KeyNum);
00322 
00323 // Delete the keys from the key table
00324 //
00325    if (!(numDel = Opt.kTab->delKey(ktEnt)))
00326       {eMsg("No matching key(s) found.");
00327        return 4;
00328       }
00329 
00330 // It's possible that all of the keys were deleted. Check for that
00331 //
00332    if (Opt.kTab->keyList() == 0)
00333       {if (isNo(1, "No keys will remain in ", Opt.KeyFile,
00334                    ". Delete file? (n | y): "))
00335           {eMsg("No keys deleted!"); return 2;}
00336        unlink(Opt.KeyFile);
00337        return 0;
00338       }
00339 
00340 // Now rewrite the file
00341 //
00342    if ((retc = Opt.kTab->Rewrite(Opt.Keep, numKeys, numTot, numExp)))
00343       {eMsg("Unable to del key from '" <<Opt.KeyFile <<"'; " <<strerror(retc));
00344        retc = 8;
00345       } else {
00346        eMsg(numKeys <<(numKeys == 1 ? " key":" keys") <<" out of "
00347             <<(numTot+numDel) <<" kept (" <<numExp <<" expired).");
00348       }
00349 
00350 // All done
00351 //
00352    return retc;
00353 }
00354 
00355 /******************************************************************************/
00356 /*                 X r d S e c s s s A d m i n _ i n s K e y                  */
00357 /******************************************************************************/
00358   
00359 int  XrdSecsssAdmin_insKey(XrdsecsssAdmin_Opts &Opt)
00360 {
00361    extern int XrdSecsssAdmin_isKey(XrdsecsssAdmin_Opts &Opt,
00362                                    XrdSecsssKT::ktEnt *ktP);
00363    XrdOucErrInfo eInfo;
00364    XrdSecsssKT::ktEnt *ktP;
00365    int retc, numKeys = 0, numTot, numExp;
00366 
00367 // Allocate the initial keytab
00368 //
00369    Opt.kTab = new XrdSecsssKT(&eInfo, 0, XrdSecsssKT::isAdmin);
00370    if ((retc = eInfo.getErrInfo())) return 4;
00371 
00372 // Check if we need to trim the keytab to a particular key
00373 //
00374    if (Opt.KeyName || Opt.KeyUser || Opt.KeyGrup)
00375       {ktP = Opt.kTab->keyList();
00376        while(ktP)
00377             {if (!XrdSecsssAdmin_isKey(Opt, ktP)) ktP->Data.Name[0] = '\0';
00378                 else numKeys++;
00379              ktP = ktP->Next;
00380             }
00381        if (!numKeys)
00382           {eMsg("No keys named " <<Opt.KeyName <<" found to install.");
00383            return 8;
00384           }
00385       }
00386 
00387 // Now rewrite the file
00388 //
00389    Opt.kTab->setPath(Opt.KeyFile);
00390    if ((retc = Opt.kTab->Rewrite(Opt.Keep, numKeys, numTot, numExp)))
00391       {eMsg("Unable to install keytab '" <<Opt.KeyFile <<"'; " <<strerror(retc));
00392        retc = 8;
00393       } else {
00394        eMsg(numKeys <<(numKeys == 1 ? " key":" keys") <<" out of "
00395             <<numTot <<" installed (" <<numExp <<" expired).");
00396       }
00397 
00398 // All done
00399 //
00400    return retc;
00401 }
00402 
00403 /******************************************************************************/
00404 /*                  X r d S e c s s s A d m i n _ i s K e y                   */
00405 /******************************************************************************/
00406   
00407 int  XrdSecsssAdmin_isKey(XrdsecsssAdmin_Opts &Opt,
00408                           XrdSecsssKT::ktEnt *ktP)
00409 {
00410    if (Opt.KeyName && strcmp(ktP->Data.Name, Opt.KeyName)) return 0;
00411    if (Opt.KeyUser && strcmp(ktP->Data.User, Opt.KeyUser)) return 0;
00412    if (Opt.KeyGrup && strcmp(ktP->Data.Grup, Opt.KeyGrup)) return 0;
00413    return 1;
00414 }
00415 
00416 /******************************************************************************/
00417 /*                   X r d S e c s s s A d m i n _ H e r e                    */
00418 /******************************************************************************/
00419   
00420 int XrdSecsssAdmin_Here(char sType, XrdSecsssKT::ktEnt *ktX,
00421                                     XrdSecsssKT::ktEnt *ktS)
00422 {
00423    int n;
00424    char *sf1, *sf2;
00425 
00426    switch(sType)
00427          {case 'c': return ktX->Data.Crt < ktS->Data.Crt;
00428           case 'g': sf1 = ktX->Data.Grup; sf2 = ktS->Data.Grup; break;
00429           case 'k': sf1 = ktX->Data.Name; sf2 = ktS->Data.Name; break;
00430           case 'n': return (ktX->Data.ID & 0x7fffffff) < (ktS->Data.ID & 0x7fffffff);
00431           case 'u': sf1 = ktX->Data.User; sf2 = ktS->Data.User; break;
00432           case 'x': return ktX->Data.Exp < ktS->Data.Exp;
00433           default:  return 0;
00434          }
00435 
00436    if ((n = strcmp(sf1, sf2))) return n < 0;
00437    return (ktX->Data.ID & 0x7fffffff) < (ktS->Data.ID & 0x7fffffff);
00438 }
00439 
00440 /******************************************************************************/
00441 /*                 X r d S e c s s s A d m i n _ l s t K e y                  */
00442 /******************************************************************************/
00443   
00444 int  XrdSecsssAdmin_lstKey(XrdsecsssAdmin_Opts &Opt)
00445 {
00446    static const char Hdr1[] =
00447    "     Number Len Date/Time Created Expires  Keyname User & Group\n";
00448 //  12345678901 123 mm/dd/yy hh:mm:ss mm/dd/yy
00449    static const char Hdr2[] =
00450    "     ------ --- --------- ------- -------- -------\n";
00451 
00452    extern int XrdSecsssAdmin_isKey(XrdsecsssAdmin_Opts &Opt,
00453                                    XrdSecsssKT::ktEnt *ktP);
00454    XrdOucErrInfo eInfo;
00455    XrdSecsssKT::ktEnt *ktP, *ktSort = 0, *ktS, *ktSP, *ktX;
00456    char crfmt[] = "%D %T", exfmt[] = "%D";
00457    char buff[128], crbuff[64], exbuff[16];
00458    int retc, pHdr = 1;
00459 
00460 // Allocate the initial keytab
00461 //
00462    Opt.kTab = new XrdSecsssKT(&eInfo, Opt.KeyFile, XrdSecsssKT::isAdmin);
00463    if ((retc = eInfo.getErrInfo()))
00464       {if (retc == ENOENT)
00465           {eMsg("Keyfile '" <<Opt.KeyFile <<"' does not exist.");}
00466        return 4;
00467       }
00468 
00469 // Obtain the keytab list
00470 //
00471    if ((ktP = Opt.kTab->keyList()))
00472       {ktSort = ktP; ktP = ktP->Next; ktSort->Next = 0;}
00473 
00474 // Sort the list
00475 //
00476    while(ktP)
00477         {ktS = ktSort; ktSP = 0; ktX = ktP; ktP = ktP->Next; ktX->Next = 0;
00478          while(ktS)
00479               {if (XrdSecsssAdmin_Here(Opt.Sort, ktX, ktS))
00480                   {if (ktSP) {ktX->Next = ktS; ktSP->Next = ktX;}
00481                       else   {ktX->Next = ktSort; ktSort  = ktX;}
00482                    break;
00483                   }
00484                ktSP = ktS; ktS = ktS->Next;
00485               }
00486          if (!ktS) ktSP->Next = ktX;
00487         }
00488 
00489 // List the keys
00490 //
00491    ktP = ktSort;
00492    while(ktP)
00493         {if (XrdSecsssAdmin_isKey(Opt, ktP))
00494             {if (pHdr) {cout <<Hdr1 <<Hdr2; pHdr = 0;}
00495              sprintf(buff, "%11lld %3d ", (ktP->Data.ID & 0x7fffffff), ktP->Data.Len);
00496              strftime(crbuff, sizeof(crbuff), crfmt, localtime(&ktP->Data.Crt));
00497              if (!ktP->Data.Exp) strcpy(exbuff, "--------");
00498                 else strftime(exbuff,sizeof(exbuff),exfmt,localtime(&ktP->Data.Exp));
00499              cout <<buff <<crbuff <<' ' <<exbuff <<' ' <<ktP->Data.Name <<' '
00500                   <<ktP->Data.User <<' ' <<ktP->Data.Grup <<endl;
00501             }
00502          ktP = ktP->Next;
00503         }
00504 
00505 // Check if we printed anything
00506 //
00507    if (pHdr)
00508       {if (Opt.KeyName) eMsg(Opt.KeyName <<" key not found in " <<Opt.KeyFile);
00509           else eMsg("No keys found in " <<Opt.KeyFile);
00510       }
00511    return 0;
00512 }
00513 
00514 

Generated on Tue Jul 5 14:47:01 2011 for ROOT_528-00b_version by  doxygen 1.5.1