XrdSutAux.cc

Go to the documentation of this file.
00001 // $Id: XrdSutAux.cc 31508 2009-12-02 19:11:01Z brun $
00002 
00003 const char *XrdSutAuxCVSID = "$Id: XrdSutAux.cc 31508 2009-12-02 19:11:01Z brun $";
00004 /******************************************************************************/
00005 /*                                                                            */
00006 /*                        X r d S u t A u x . c c                             */
00007 /*                                                                            */
00008 /* (c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University  */
00009 /*       All Rights Reserved. See XrdInfo.cc for complete License Terms       */
00010 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00011 /*              DE-AC03-76-SFO0515 with the Department of Energy              */
00012 /******************************************************************************/
00013 
00014 #include <stdio.h>
00015 #include <stdlib.h>
00016 #include <string.h>
00017 #include <unistd.h>
00018 #include <errno.h>
00019 #include <netinet/in.h>
00020 #include <time.h>
00021 #include <pwd.h>
00022 #include <sys/types.h>
00023 #include <sys/stat.h>
00024 #include <fcntl.h>
00025 
00026 #include <XrdSys/XrdSysLogger.hh>
00027 #include <XrdSys/XrdSysError.hh>
00028 #include <XrdOuc/XrdOucString.hh>
00029 
00030 #include <XrdSut/XrdSutAux.hh>
00031 #include <XrdSut/XrdSutTrace.hh>
00032 
00033 static const char *gXRSBucketTypes[] = {
00034    "kXRS_none",
00035    "kXRS_inactive",
00036    "kXRS_cryptomod",
00037    "kXRS_main",
00038    "kXRS_srv_seal",
00039    "kXRS_clnt_seal",
00040    "kXRS_puk",
00041    "kXRS_cipher",
00042    "kXRS_rtag",
00043    "kXRS_signed_rtag",
00044    "kXRS_user",
00045    "kXRS_host",
00046    "kXRS_creds",
00047    "kXRS_message",
00048    "kXRS_srvID",
00049    "kXRS_sessionID",
00050    "kXRS_version",
00051    "kXRS_status",
00052    "kXRS_localstatus",
00053    "kXRS_othercreds",
00054    "kXRS_cache_idx",
00055    "kXRS_clnt_opts",
00056    "kXRS_error_code",
00057    "kXRS_timestamp",
00058    "kXRS_x509",
00059    "kXRS_issuer_hash",
00060    "kXRS_x509_req",
00061    "kXRS_cipher_alg",
00062    "kXRS_md_alg",
00063    "kXRS_afsinfo",
00064    "kXRS_reserved"
00065 };
00066 
00067 //
00068 // For error logging and tracing
00069 static XrdSysLogger Logger;
00070 static XrdSysError eDest(0,"sut_");
00071 XrdOucTrace *sutTrace = 0;
00072 
00073 /******************************************************************************/
00074 /*  X r d S u t S e t T r a c e                                               */
00075 /******************************************************************************/
00076 //______________________________________________________________________________
00077 void XrdSutSetTrace(kXR_int32 trace)
00078 {
00079    // Set trace flags according to 'trace'
00080 
00081    //
00082    // Initiate error logging and tracing
00083    eDest.logger(&Logger);
00084    if (!sutTrace)
00085       sutTrace = new XrdOucTrace(&eDest);
00086    if (sutTrace) {
00087       // Set debug mask
00088       sutTrace->What = 0;
00089       // Low level only
00090       if ((trace & sutTRACE_Notify))
00091          sutTrace->What |= sutTRACE_Notify;
00092       // Medium level
00093       if ((trace & sutTRACE_Debug))
00094          sutTrace->What |= (sutTRACE_Notify | sutTRACE_Debug);
00095       // High level
00096       if ((trace & sutTRACE_Dump))
00097          sutTrace->What |= sutTRACE_ALL;
00098    }
00099 }
00100 
00101 /******************************************************************************/
00102 /*  X r d S u t B u c k S t r                                                 */
00103 /******************************************************************************/
00104 //______________________________________________________________________________
00105 const char *XrdSutBuckStr(int kbck)
00106 {
00107    // Return bucket string
00108    static const char *ukn = "Unknown";
00109 
00110    kbck = (kbck < 0) ? 0 : kbck;
00111    kbck = (kbck > kXRS_reserved) ? 0 : kbck;
00112    kbck = (kbck >= kXRS_cryptomod) ?  (kbck - kXRS_cryptomod + 2) : kbck;
00113 
00114    if (kbck < 0 || kbck > (kXRS_reserved - kXRS_cryptomod + 2))
00115       return ukn;  
00116    else
00117       return gXRSBucketTypes[kbck];  
00118 }
00119 
00120 /******************************************************************************/
00121 /*  X r d S u t M e m S e t                                                   */
00122 /******************************************************************************/
00123 //______________________________________________________________________________
00124 volatile void *XrdSutMemSet(volatile void *dst, int c, int len)
00125 {
00126    // To avoid problems due to compiler optmization
00127    // Taken from Viega&Messier, "Secure Programming Cookbook", O'Really, #13.2
00128    // (see discussion there)
00129    volatile char *buf;
00130 
00131    for (buf = (volatile char *)dst; len; buf[--len] = c);
00132    return dst;
00133 }
00134 
00135 #ifndef USE_EXTERNAL_GETPASS
00136 /******************************************************************************/
00137 /*  X r d S u t G e t P a s s                                                 */
00138 /******************************************************************************/
00139 //_____________________________________________________________________________
00140 int XrdSutGetPass(const char *prompt, XrdOucString &passwd)
00141 {
00142    // Get password from command line using getpass
00143    // *** Use only if you cannot provide a better alternative ***
00144    // User will be prompted for 'prompt'; the entered password
00145    // is returned in 'passwd'.
00146    // Returns 0 if ok, -1 if any error occurs.
00147    EPNAME("GetPass");
00148 
00149    char *pw = getpass(prompt);
00150    if (pw) {
00151       // Get rid of special chars, if any
00152       int k = 0, i = 0, len = strlen(pw);
00153       for (; i<len ; i++)
00154          if (pw[i] > 0x20) pw[k++] = pw[i];
00155       pw[k] = 0;
00156       passwd = pw;
00157       XrdSutMemSet((volatile void *)pw,0,len);
00158    } else {
00159       DEBUG("error from getpass");
00160       return -1;
00161    }
00162    return 0;
00163 }
00164 #endif
00165 
00166 /******************************************************************************/
00167 /*  X r d S u t G e t L i n e                                                 */
00168 /******************************************************************************/
00169 int XrdSutGetLine(XrdOucString &line, const char *prompt)
00170 {
00171    // Get line from main input stream.
00172    // Prompt 'prompt' if this is defined.
00173    // Returns number of chars entered.
00174    // NB: at most XrdSutMAXBUF-1 chars will be accepted
00175    char bin[XrdSutMAXBUF] = {0};
00176    
00177    // Print prompt, if requested
00178    if (prompt)
00179       cout << prompt;
00180 
00181    // Get line
00182    cin.getline(bin,XrdSutMAXBUF-1);
00183 
00184    // Fill input
00185    line = bin;
00186 
00187    return line.length();
00188 }
00189 
00190 /******************************************************************************/
00191 /*  X r d S u t A s k C o n f i r m                                           */
00192 /******************************************************************************/
00193 bool XrdSutAskConfirm(const char *msg1, bool defact, const char *msg2)
00194 {
00195    // Prompt for confirmation of action
00196    // If defined, msg1 is printed as prompt, followed by the default action
00197    // (  [y] == do-act, for defact = true; 
00198    //    [n] == do-not-act, for defact = false)
00199    // If defined, msg2 is printed before prompting.
00200 
00201    bool rc = defact;
00202 
00203    if (msg2)
00204       cout << msg2;
00205    XrdOucString ask;
00206    XrdOucString prompt = defact ? " [y]: " : " [n]: ";
00207    if (msg1)
00208       prompt.insert(msg1,0);
00209    XrdSutGetLine(ask,prompt.c_str());
00210    ask.lower(0);
00211    if (ask.length()) {
00212       if (defact && (ask == 'n' || ask == "no")) {
00213          rc = 0;
00214       } else if (!defact && (ask == 'y' || ask == "yes")) {
00215          rc = 1;
00216       }
00217    }
00218    // we are done
00219    return rc;
00220 }
00221 
00222 /******************************************************************************/
00223 /*  X r d S u t T o H e x                                                     */
00224 /******************************************************************************/
00225 int XrdSutToHex(const char *in, int lin, char *out)
00226 {
00227    // Content of lin bytes at in are transformed into an hexadecimal,
00228    // null-terminated, string of length 2*lin; the result is returned
00229    // in the buffer pointed by out, which must be allocated by the caller
00230    // to contain at least 2*lin+1 bytes. 
00231    // Return 0 in case of success, -1 in case of error (errno set to EINVAL if
00232    // any of in or out are not defined).
00233 
00234    if (!in || !out) {
00235       errno = EINVAL;
00236       return -1;
00237    }
00238 
00239    int lbuf = 2*lin+1;
00240    int i = 0;
00241    out[0] = 0;
00242    for ( ; i < lin; i++)
00243       sprintf(out,"%s%02x",out,(0xFF & in[i]));
00244    // Null termination
00245    out[lbuf-1] = 0;
00246 
00247    // ok
00248    return 0;
00249 }
00250 
00251 /******************************************************************************/
00252 /*  X r d S u t F r o m H e x                                                 */
00253 /******************************************************************************/
00254 int XrdSutFromHex(const char *in, char *out, int &lout)
00255 {
00256    // Content of the hexadecimal, null-terminated, string at in, is
00257    // transformed into lout bytes returned in out.
00258    // The output buffer should be allocated by the caller to contain
00259    // at least lin/2 bytes if lin=strlen(in) is even, and lin/2+1 bytes
00260    // if lin is odd (in this case an additional char equal 0 is appended
00261    // to in).
00262    // Return 0 in case of success, -1 in case of error (errno set to EINVAL if
00263    // any of in or out are not defined).
00264 
00265    lout = 0;
00266    if (!in || !out) {
00267       errno = EINVAL;
00268       return -1;
00269    }
00270 
00271    int lin = strlen(in);
00272    char st[3] = {0};
00273    int i = 0, k = 0;
00274    for ( ; i<lin; i += 2) {
00275       st[0] = in[i];
00276       st[1] = ((i+1) < lin) ? in[i+1] : 0;
00277       int c;
00278       sscanf(st,"%x",&c);
00279       out[k++] = (char)(0x000000FF & c);
00280    }
00281 
00282    lout = k;
00283 
00284    return 0;
00285 }
00286 
00287 /******************************************************************************/
00288 /*  X r d S u t T i m e S t r i n g                                           */
00289 /*                                                                            */
00290 /******************************************************************************/
00291 int XrdSutTimeString(int t, char *st, int opt)
00292 {
00293    //  Trasform a time in secs since 1Jan1970 in a string of the format
00294    //     24Apr2006:09:10:23       (opt = 0, default)
00295    //     24Apr2006-091023         (opt = 1)
00296    // The buffer st must be supplied by the caller to contain at least 20.
00297    // This length is returned when calling the function with t=-1 
00298    static char month[12][4] = {"Jan","Feb","Mar","Apr","May","Jun",
00299                                "Jul","Aug","Sep","Oct","Nov","Dec"};
00300    static short flen = strlen("24Apr2006:09:10:23");
00301 
00302    // Check if the length is required
00303    if (t == -1)
00304       return (flen+1);
00305 
00306    // Now check inputs
00307    if (t < 0 || !st)
00308       return -1;
00309 
00310    // Get the breakdown
00311    struct tm tst;
00312    time_t ttmp = t;
00313    if (!localtime_r(&ttmp,&tst))
00314       return -2;
00315 
00316    // Now fill the output
00317    if (opt == 1) {
00318       sprintf(st,"%2d%3s%4d-%2d%2d%2d",tst.tm_mday,month[tst.tm_mon],
00319                                     1900+tst.tm_year,
00320                                     tst.tm_hour,tst.tm_min,tst.tm_sec);
00321       // Make sure is null terminated at the right point
00322       st[flen-2] = '\0';
00323    } else {
00324       sprintf(st,"%2d%3s%4d:%2d:%2d:%2d",tst.tm_mday,month[tst.tm_mon],
00325                                          1900+tst.tm_year,
00326                                          tst.tm_hour,tst.tm_min,tst.tm_sec);
00327    }
00328 
00329    // Make sure there are no empty spaces
00330    if (st[0] == 0x20) st[0] = 0x30;
00331    int i = 10;
00332    for (; i <= 16; i++ )
00333        if (st[i] == 0x20) st[i] = 0x30;
00334 
00335 
00336    // Null termination
00337    st[flen] = 0;
00338 
00339    // Ok
00340    return 0;
00341 }
00342 
00343 /******************************************************************************/
00344 /*  X r d S u t E x p a n d                                                   */
00345 /******************************************************************************/
00346 int XrdSutExpand(XrdOucString &path)
00347 {
00348    // Expand '~' or $PWD for incomplete absolute path specification
00349    // Returns 0 in case of success, -EINVAL if path is not defined;
00350    // -errno if failure of the pwnam functions; -ENOENT if PWD is not
00351    // defined
00352    EPNAME("Expand");
00353 
00354    // Path must be defined
00355    if (!path.length())
00356       return -EINVAL;
00357 
00358    // If path is absolute, do nothing
00359    if (path[0] == '/')
00360       return 0;
00361 
00362    if (path[0] == '~') {
00363       XrdOucString unam, home;
00364       XrdOucString sdir(path);
00365       int iu = path.find('/');
00366       if (iu != STR_NPOS) {
00367          if (iu > 1)
00368             unam.assign(path, 1, iu-1);
00369          sdir.erase(0, iu);
00370       } else
00371          sdir = '/';
00372       if (unam.length() > 0) {
00373          struct passwd *pw = 0;
00374          if (!(pw = getpwnam(unam.c_str()))) {
00375             DEBUG("cannot pwnam information for local user "<<
00376                  ((unam.length() > 0) ? unam : XrdOucString("")));
00377             return -errno;
00378          }
00379          home = pw->pw_dir;
00380       } else
00381          home = XrdSutHome();
00382       if (home.length() > 0) {
00383          sdir.insert(home.c_str(),0);
00384          path = sdir;
00385       }
00386    } else {
00387       // relative path, add local dir
00388       char *pwd = getenv("PWD");
00389       if (pwd) {
00390          path.insert('/',0);
00391          path.insert(pwd,0);
00392          path.erase("//");
00393       } else {
00394          DEBUG("PWD undefined ");
00395          return -ENOENT;
00396       }
00397    }
00398    return 0;
00399 }
00400 
00401 /******************************************************************************/
00402 /*  X r d S u t R e s o l v e                                                 */
00403 /******************************************************************************/
00404 int XrdSutResolve(XrdOucString &path,
00405                   const char *ho, const char *vo, const char *gr, const char *us)
00406 {
00407    // Resolve templates <host>, <vo>, <group>, <user> (if any)
00408    // Returns 0 in case of success, -EINVAL if path is not defined.
00409 
00410    // Path must be defined
00411    if (!path.length())
00412       return -EINVAL;
00413 
00414    // No templates, nothing to do
00415    if (path.find("<") == STR_NPOS)
00416       return 0;
00417 
00418    // Replace <host>, if defined
00419    if (ho && strlen(ho) > 0) path.replace("<host>", ho);
00420 
00421    // Replace <vo>, if defined
00422    if (vo && strlen(vo) > 0) path.replace("<vo>", vo);
00423 
00424    // Replace <group>, if defined
00425    if (gr && strlen(gr) > 0) path.replace("<group>", gr);
00426 
00427    // Replace <user>, if defined
00428    if (us && strlen(us) > 0) path.replace("<user>", us);
00429 
00430    // Done
00431    return 0;
00432 }
00433 
00434 /******************************************************************************/
00435 /*  X r d S u t H o m e                                                       */
00436 /******************************************************************************/
00437 const char *XrdSutHome()
00438 {
00439    // Gets the home directory preferentially from HOME or from getpwuid()
00440    EPNAME("Home");
00441 
00442    // Use the save value, if any
00443    static XrdOucString homedir;
00444    if (homedir.length() <= 0) {
00445       // Check the HOME environment variable
00446       if (getenv("HOME"))
00447          homedir = getenv("HOME");
00448       if (homedir.length() <= 0) {
00449          struct passwd *pw = getpwuid(getuid());
00450          homedir = pw->pw_dir;
00451       }
00452       if (homedir.length() <= 0)
00453          DEBUG("Warning: home directory undefined! ");
00454    }
00455 
00456    // Done
00457    return homedir.c_str();
00458 }
00459 
00460 /******************************************************************************/
00461 /*  X r d S u t M k d i r                                                     */
00462 /*                                                                            */
00463 /******************************************************************************/
00464 int XrdSutMkdir(const char *dir, unsigned int mode, const char *opt)
00465 {
00466    //  Make directory dir
00467    //  mode specifies permissions
00468    //  opt == "-p" : make parent directories as needed
00469 
00470    if (!dir) {
00471       errno = EINVAL;
00472       return -1;
00473    }
00474 
00475    if (!strncmp(opt,"-p",2)) {
00476       //
00477       //  make also parent directories, if needed
00478       XrdOucString dd(dir);
00479       XrdSutExpand(dd);
00480       if (dd[dd.length()-1] != '/')
00481          dd.append('/');
00482       int lsl = dd.find('/',1);
00483       while (lsl > -1) {
00484          XrdOucString pd(dd,0,lsl-1);
00485          struct stat st;
00486          if (stat(pd.c_str(),&st) == -1) {
00487             if (errno == ENOENT) {
00488                // path does not exists: create it
00489                if (mkdir(pd.c_str(),mode) != 0)
00490                   return -1;
00491             } else {
00492                return -1;
00493             }
00494          }
00495          // Go to next
00496          lsl = dd.find('/',lsl+1);
00497       }      
00498 
00499    } else {
00500       return mkdir(dir,mode);
00501    }
00502 
00503    return 0;
00504 }
00505 
00506 /******************************************************************************/
00507 /*  X r d S u t P a r s e T i m e                                             */
00508 /*                                                                            */
00509 /******************************************************************************/
00510 //______________________________________________________________________  
00511 int XrdSutParseTime(const char *tstr, int opt)
00512 {
00513    // Parse time string of the form "<val1><unit1>:<val2><unit2>:..."
00514    // with <val> any integer and <unit> one of the following chars:
00515    //       'y'     for years
00516    //       'd'     for days
00517    //       'h'     for hours
00518    //       'm'     for minutes
00519    //       's'     for seconds
00520    // (e.g. "34d:10h:20s")
00521    // If opt == 1, assume a string in the form "<hh>[:<ss>[:<mm>]]"
00522    // (e.g. "12:24:35" for 12 hours, 24 minutes and 35 secs)
00523    // Return the corresponding number of seconds
00524    EPNAME("ParseTime");
00525 
00526    XrdOucString ts = tstr;
00527    XrdOucString fr = "";
00528    int i = 0;
00529    int tsec = 0;
00530    // Parse list
00531    if (ts.length()) {
00532       int ls = 0;
00533       int ld = ts.find(':',1);
00534       ld = (ld == -1) ? ts.length() - 1 : ld;
00535       while (ld >= ls) {
00536          fr.assign(ts, ls, ld);
00537          fr.erase(":");
00538          // Check this fraction
00539          if (opt == 0) {
00540             if (fr.length() > 1) {
00541                // The unit must be known
00542                char u = fr[fr.length()-1];
00543                fr.erase(fr.length()-1);
00544                if (u == 'y') {
00545                   tsec += atoi(fr.c_str())*31536000;
00546                } else if (u == 'd') {
00547                   tsec += atoi(fr.c_str())*86400;
00548                } else if (u == 'h') {
00549                   tsec += atoi(fr.c_str())*3600;
00550                } else if (u == 'm') {
00551                   tsec += atoi(fr.c_str())*60;
00552                } else if (u == 's') {
00553                   tsec += atoi(fr.c_str());
00554                } else {
00555                   DEBUG("unknown unit: "<<u);
00556                }
00557             } else {
00558                DEBUG("Incomplete fraction: "<<fr.c_str());
00559             }
00560          } else {
00561             if (i == 0) {
00562                tsec += atoi(fr.c_str())*3600;
00563             } else if (i == 1) {
00564                tsec += atoi(fr.c_str())*60;
00565             } else if (i == 2) {
00566                tsec += atoi(fr.c_str());
00567             }
00568          }
00569          i++;
00570          ls = ld + 1;
00571          ld = ts.find(':',ls);
00572          ld = (ld == -1) ? ts.length() - 1 : ld;
00573       }
00574    }
00575    return tsec;
00576 }
00577 
00578 /******************************************************************************/
00579 /*  X r d S u t F i l e L o c k e r                                           */
00580 /*                                                                            */
00581 /*  Guard class for file locking                                              */
00582 /*  Usage:                                                                    */
00583 /*  {                                                                         */
00584 /*     XrdSutFileLocker fl(filename,1);                                       */
00585 /*     // File exclusively locked                                             */
00586 /*     ...                                                                    */
00587 /*  } // Unlocks file 'filename'                                              */
00588 /*        's'     for seconds                                                 */
00589 /*                                                                            */
00590 /******************************************************************************/
00591 //______________________________________________________________________________
00592 XrdSutFileLocker::XrdSutFileLocker(int fd, ELockType lock)
00593 {
00594    // Constructor: locks the file in 'lock' mode.
00595    // Use IsValid() to test success.
00596 
00597    valid = 0;
00598    fdesk = fd;
00599 
00600    // Exclusive lock of the whole file
00601    int lockmode = (lock == XrdSutFileLocker::kExcl) ? (F_WRLCK | F_RDLCK)
00602                                                     :  F_RDLCK;
00603 #ifdef __macos__
00604    struct flock flck = {0, 0, 0, lockmode, SEEK_SET};
00605 #else
00606    struct flock flck = {lockmode, SEEK_SET, 0, 0};
00607 #endif
00608    if (fcntl(fdesk, F_SETLK, &flck) != 0)
00609       // Failure
00610       return;
00611 
00612    // Success
00613    valid = 1;
00614 }
00615 //______________________________________________________________________________
00616 XrdSutFileLocker::~XrdSutFileLocker()
00617 {
00618    // Destructor: unlocks the file if locked.
00619 
00620    if (fdesk < 0 || !IsValid())
00621       return;
00622    //
00623    // Unlock the file
00624 #ifdef __macos__
00625    struct flock flck = {0, 0, 0, F_UNLCK, SEEK_SET};
00626 #else
00627    struct flock flck = {F_UNLCK, SEEK_SET, 0, 0};
00628 #endif
00629    fcntl(fdesk, F_SETLK, &flck);
00630 }
00631 

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