XrdSecPManager.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                     X r d S e c P M a n a g e r . c c                      */
00004 /*                                                                            */
00005 /* (c) 2003 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-AC03-76-SFO0515 with the Department of Energy              */
00009 /******************************************************************************/
00010 
00011 //       $Id: XrdSecPManager.cc 28902 2009-06-11 12:36:21Z ganis $
00012 
00013 const char *XrdSecPManagerCVSID = "$Id: XrdSecPManager.cc 28902 2009-06-11 12:36:21Z ganis $";
00014 
00015 // Bypass Solaris ELF madness
00016 //
00017 #ifdef __solaris__
00018 #include <sys/isa_defs.h>
00019 #if defined(_ILP32) && (_FILE_OFFSET_BITS != 32)
00020 #undef  _FILE_OFFSET_BITS
00021 #define _FILE_OFFSET_BITS 32
00022 #undef  _LARGEFILE_SOURCE
00023 #endif
00024 #endif
00025 
00026 #include <dlfcn.h>
00027 #if !defined(__macos__) && !defined(__CYGWIN__)
00028 #include <link.h>
00029 #endif
00030 #include <strings.h>
00031 #include <sys/stat.h>
00032 #include <sys/types.h>
00033 #include <errno.h>
00034 
00035 #include "XrdSys/XrdSysHeaders.hh"
00036 #include "XrdSec/XrdSecInterface.hh"
00037 #include "XrdSec/XrdSecPManager.hh"
00038 #include "XrdSec/XrdSecProtocolhost.hh"
00039 #include "XrdOuc/XrdOucErrInfo.hh"
00040 
00041 /******************************************************************************/
00042 /*                 M i s c e l l a n e o u s   D e f i n e s                  */
00043 /******************************************************************************/
00044 
00045 #define DEBUG(x) {if (DebugON) cerr <<"sec_PM: " <<x <<endl;}
00046   
00047 /******************************************************************************/
00048 /*                         L o c a l   C l a s s e s                          */
00049 /******************************************************************************/
00050   
00051 class XrdSecProtList
00052 {
00053 public:
00054 
00055 XrdSecPMask_t    protnum;
00056 char             protid[XrdSecPROTOIDSIZE+1];
00057 char            *protargs;
00058 XrdSecProtocol  *(*ep)(PROTPARMS);
00059 XrdSecProtList  *Next;
00060 
00061                 XrdSecProtList(const char *pid, const char *parg)
00062                       {strncpy(protid, pid, sizeof(protid)-1);
00063                        protid[XrdSecPROTOIDSIZE] = '\0'; ep = 0; Next = 0;
00064                        protargs = (parg ? strdup(parg): (char *)"");
00065                       }
00066                ~XrdSecProtList() {} // ProtList objects never get freed!
00067 };
00068 
00069 /******************************************************************************/
00070 /*                X r d S e c P M a n a g e r   M e t h o d s                 */
00071 /******************************************************************************/
00072 /******************************************************************************/
00073 /*                                  F i n d                                   */
00074 /******************************************************************************/
00075   
00076 XrdSecPMask_t XrdSecPManager::Find(const char *pid, char **parg)
00077 {
00078    XrdSecProtList *plp;
00079 
00080    if ((plp = Lookup(pid)))
00081       {if (parg) *parg = plp->protargs;
00082        return plp->protnum;
00083       }
00084    return 0;
00085 }
00086 
00087 /******************************************************************************/
00088 /*                                   G e t                                    */
00089 /******************************************************************************/
00090 
00091 XrdSecProtocol *XrdSecPManager::Get(const char     *hname,
00092                                     const sockaddr &netaddr,
00093                                     const char     *pname,
00094                                     XrdOucErrInfo  *erp)
00095 {
00096    XrdSecProtList *pl;
00097    const char *msgv[2];
00098 
00099 // Find the protocol and get an instance of the protocol object
00100 //
00101    if ((pl = Lookup(pname)))
00102       {DEBUG("Using " <<pname <<" protocol, args='"
00103               <<(pl->protargs ? pl->protargs : "") <<"'");
00104        return pl->ep('s', hname, netaddr, 0, erp);
00105       }
00106 
00107 // Protocol is not supported
00108 //
00109    msgv[0] = pname;
00110    msgv[1] = " security protocol is not supported.";
00111    erp->setErrInfo(EPROTONOSUPPORT, msgv, 2);
00112    return 0;
00113 }
00114 
00115 XrdSecProtocol *XrdSecPManager::Get(const char       *hname,
00116                                     const sockaddr   &netaddr,
00117                                     XrdSecParameters &secparm)
00118 {
00119    char secbuff[4096], *nscan, *pname, *pargs, *bp = secbuff;
00120    const char *wantProt = getenv("XrdSecPROTOCOL");
00121    XrdSecProtList *pl;
00122    XrdSecProtocol *pp;
00123    XrdOucErrInfo   erp;
00124    int i;
00125 
00126 // We only scan the buffer once
00127 //
00128    if (secparm.size <= 0) return (XrdSecProtocol *)0;
00129 
00130 // Copy the string into a local buffer so that we can simplify some comparisons
00131 // and isolate ourselves from server protocol errors.
00132 //
00133    if (secparm.size < (int)sizeof(secbuff)) i = secparm.size;
00134       else i = sizeof(secbuff)-1;
00135    strncpy(secbuff, secparm.buffer, i);
00136    secbuff[i] = '\0';
00137 
00138 // Find a protocol marker in the info block and check if acceptable
00139 //
00140    while(*bp)
00141         {if (*bp != '&') {bp++; continue;}
00142             else if (!*(++bp) || *bp != 'P' || !*(++bp) || *bp != '=') continue;
00143          bp++; pname = bp; pargs = 0;
00144          while(*bp && *bp != ',' && *bp != '&') bp++;
00145          if (!*bp) nscan = 0;
00146             else {if (*bp == '&') {*bp = '\0'; pargs = 0; nscan = bp;}
00147                      else {*bp = '\0'; pargs = ++bp;
00148                            while (*bp && *bp != '&') bp++;
00149                            if (*bp) {*bp ='\0'; nscan = bp;}
00150                               else nscan = 0;
00151                           }
00152                   }
00153          if (!wantProt or !strcmp(pname, wantProt))
00154             {if ((pl = Lookup(pname)) || (pl = ldPO(&erp, 'c', pname)))
00155                 {DEBUG("Using " <<pname <<" protocol, args='"
00156                        <<(pargs ? pargs : "") <<"'");
00157                  if ((pp = pl->ep('c', hname, netaddr, pargs, &erp)))
00158                     {if (nscan) {i = nscan - secbuff;
00159                                  secparm.buffer += i; secparm.size -= i;
00160                                 } else secparm.size = -1;
00161                      return pp;
00162                     }
00163                 }
00164              if (erp.getErrInfo() != ENOENT) cerr <<erp.getErrText() <<endl;
00165             } else {DEBUG("Skipping " <<pname <<" only want " <<wantProt);}
00166          if (!nscan) break;
00167          *nscan = '&'; bp = nscan;
00168          }
00169     secparm.size = -1;
00170     return (XrdSecProtocol *)0;
00171 }
00172  
00173 /******************************************************************************/
00174 /*                       P r i v a t e   M e t h o d s                        */
00175 /******************************************************************************/
00176 /******************************************************************************/
00177 /*                                   A d d                                    */
00178 /******************************************************************************/
00179   
00180 XrdSecProtList *XrdSecPManager::Add(XrdOucErrInfo  *eMsg, const char *pid,
00181                                     XrdSecProtocol *(*ep)(PROTPARMS),
00182                                     const char *parg)
00183 {
00184    XrdSecProtList *plp;
00185 
00186 // Make sure we did not overflow the protocol stack
00187 //
00188    if (!protnum)
00189       {eMsg->setErrInfo(-1, "XrdSec: Too many protocols defined.");
00190        return 0;
00191       }
00192 
00193 // Add this protocol to our protocol stack
00194 //
00195    plp = new XrdSecProtList((char *)pid, parg);
00196    plp->ep = ep;
00197    myMutex.Lock();
00198    if (Last) {Last->Next = plp; Last = plp;}
00199       else First = Last = plp;
00200    plp->protnum = protnum; 
00201    if (protnum & 0x40000000) protnum = 0;
00202       else protnum = protnum<<1;
00203    myMutex.UnLock();
00204 
00205 // All went well
00206 //
00207    return plp;
00208 }
00209 
00210 /******************************************************************************/
00211 /*                                  l d P O                                   */
00212 /******************************************************************************/
00213 
00214 #define INITPARMS const char, const char *, XrdOucErrInfo *
00215   
00216 XrdSecProtList *XrdSecPManager::ldPO(XrdOucErrInfo *eMsg,  // In
00217                                      const char     pmode, // In 'c' | 's'
00218                                      const char    *pid,   // In
00219                                      const char    *parg,  // In
00220                                      const char    *spath) // In
00221 {
00222    extern XrdSecProtocol *XrdSecProtocolhostObject(PROTPARMS);
00223    void *libhandle;
00224    XrdSecProtocol *(*ep)(PROTPARMS);
00225    char           *(*ip)(INITPARMS);
00226    const char *tlist[8];
00227    char  poname[80], libfn[80], libpath[2048], *libloc, *newargs;
00228    int i, k = 1;
00229 
00230 // The "host" protocol is builtin.
00231 //
00232    if (!strcmp(pid, "host")) return Add(eMsg,pid,XrdSecProtocolhostObject,0);
00233    tlist[0] = "XrdSec: ";
00234 
00235 // Form library name
00236 //
00237    snprintf(libfn, sizeof(libfn)-1, "libXrdSec%s.so", pid);
00238    libfn[sizeof(libfn)-1] = '\0';
00239 
00240 // Determine path
00241 //
00242    if (!spath || (i = strlen(spath)) < 2) libloc = libfn;
00243       else {char *sep = (spath[i-1] == '/' ? (char *)"" : (char *)"/");
00244             snprintf(libpath, sizeof(libpath)-1, "%s%s%s", spath, sep, libfn);
00245             libpath[sizeof(libpath)-1] = '\0';
00246             libloc = libpath;
00247            }
00248    DEBUG("Loading " <<pid <<" protocol object from " <<libloc);
00249 
00250 // For clients, verify if the library exists (don't complain, if not)
00251 //
00252    if (pmode == 'c')
00253       {struct stat buf;
00254        if (!stat(libloc, &buf) && errno == ENOENT)
00255           {eMsg->setErrInfo(ENOENT, ""); return 0;}
00256       }
00257 
00258 // Open the security library
00259 //
00260    if (!(libhandle = dlopen(libloc, RTLD_NOW)))
00261       {tlist[k++] = dlerror();
00262        tlist[k++] = " opening shared library ";
00263        tlist[k++] = libloc;
00264        eMsg->setErrInfo(-1, tlist, k);
00265        return 0;
00266       }
00267 
00268 // Get the protocol object creator
00269 //
00270    sprintf(poname, "XrdSecProtocol%sObject", pid);
00271    if (!(ep = (XrdSecProtocol *(*)(PROTPARMS))dlsym(libhandle, poname)))
00272       {tlist[k++] = dlerror();
00273        tlist[k++] = " finding ";
00274        tlist[k++] = poname;
00275        tlist[k++] = " in ";
00276        tlist[k++] = libloc;
00277        eMsg->setErrInfo(-1, tlist, k);
00278        return 0;
00279       }
00280 
00281 // Get the protocol initializer
00282 //
00283    sprintf(poname, "XrdSecProtocol%sInit", pid);
00284    if (!(ip = (char *(*)(INITPARMS))dlsym(libhandle, poname)))
00285       {tlist[k++] = dlerror();
00286        tlist[k++] = " finding ";
00287        tlist[k++] = poname;
00288        tlist[k++] = " in ";
00289        tlist[k++] = libloc;
00290        eMsg->setErrInfo(-1, tlist, k);
00291        return 0;
00292       }
00293 
00294 // Invoke the one-time initialization
00295 //
00296    if (!(newargs = ip(pmode, (pmode == 'c' ? 0 : parg), eMsg))) return 0;
00297 
00298 // Add this protocol to our protocol stack
00299 //
00300    return Add(eMsg, pid, ep, newargs);
00301 }
00302  
00303 /******************************************************************************/
00304 /*                                L o o k u p                                 */
00305 /******************************************************************************/
00306   
00307 XrdSecProtList *XrdSecPManager::Lookup(const char *pid)   // In
00308 {
00309    XrdSecProtList *plp;
00310 
00311 // Since we only add protocols and never remove them, we need only to lock
00312 // the protocol list to get the first item.
00313 //
00314    myMutex.Lock();
00315    plp = First;
00316    myMutex.UnLock();
00317 
00318 // Now we can go and find a matching protocol
00319 //
00320    while(plp && strcmp(plp->protid, pid)) plp = plp->Next;
00321 
00322    return plp;
00323 }

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