00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00035 #include "OW_config.h"
00036 #include "OW_LocalAuthenticationCommon.hpp"
00037 #include "OW_String.hpp"
00038 #include "OW_Array.hpp"
00039 #include "OW_FileSystem.hpp"
00040 #include "OW_File.hpp"
00041 #include "OW_Format.hpp"
00042 
00043 #include <unistd.h>
00044 #include <sys/types.h>
00045 #include <pwd.h>
00046 #include <sys/stat.h>
00047 
00048 #include <cstring>
00049 #include <cstdio>
00050 #include <cerrno>
00051 #include <ctime>
00052 #include <iostream>
00053 
00054 namespace OW_NAMESPACE
00055 {
00056 
00057 namespace LocalAuthenticationCommon
00058 {
00059 
00060 OW_DEFINE_EXCEPTION(LocalAuthentication);
00061 
00065 void initializeDir()
00066 {
00067    StringArray dirParts = String(LOCAL_AUTH_DIR).tokenize(OW_FILENAME_SEPARATOR);
00068    String curDir;
00069    for (size_t i = 0; i < dirParts.size(); ++i)
00070    {
00071       
00072       curDir += OW_FILENAME_SEPARATOR;
00073       curDir += dirParts[i];
00074       int rv = ::mkdir(curDir.c_str(), 0755);
00075       if (rv == -1 && errno != EEXIST)
00076       {
00077          OW_THROW_ERRNO_MSG(LocalAuthenticationException, Format("LocalAuthentication::initializeDir(): mkdir(%1, 0755)", curDir).c_str());
00078       }
00079       if (rv == 0)
00080       {
00081          
00082          
00083          struct stat statbuf;
00084          if (lstat(curDir.c_str(), &statbuf) == -1)
00085          {
00086             OW_THROW_ERRNO_MSG(LocalAuthenticationException, Format("LocalAuthentication::initializeDir(): lstat(%1, ...)", curDir).c_str());
00087          }
00088          
00089          ::mode_t newmode(statbuf.st_mode);
00090          newmode &= ~S_ISGID;
00091          newmode |= S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
00092          if (chmod(curDir.c_str(), newmode) == -1)
00093          {
00094             OW_THROW_ERRNO_MSG(LocalAuthenticationException, Format("LocalAuthentication::initializeDir(): chmod(%1, ...)", curDir).c_str());
00095          }
00096 
00097          if (chown(curDir.c_str(), 0, 0) == -1)
00098          {
00099             OW_THROW_ERRNO_MSG(LocalAuthenticationException, Format("LocalAuthentication::initializeDir(): chown(%1, 0, 0)", curDir).c_str());
00100          }
00101       }
00102 
00103       
00104       struct stat statbuf;
00105       if (lstat(curDir.c_str(), &statbuf) == -1)
00106       {
00107          OW_THROW_ERRNO_MSG(LocalAuthenticationException, Format("LocalAuthentication::initializeDir(): lstat(%1, ...)", curDir).c_str());
00108       }
00109 
00110       int necessaryMask = S_IROTH | S_IXOTH;
00111       if (statbuf.st_mode & necessaryMask != necessaryMask)
00112       {
00113          OW_THROW(LocalAuthenticationException, Format("LocalAuthentication::initializeDir(): directory permissions on %1"
00114             " are %2. That is insufficient", curDir, statbuf.st_mode).c_str());
00115       }
00116    }
00117 
00118    
00119    StringArray files;
00120    if (!FileSystem::getDirectoryContents(LOCAL_AUTH_DIR, files))
00121    {
00122       OW_THROW_ERRNO_MSG(LocalAuthenticationException, Format("LocalAuthentication::initializeDir(): getDirectoryContents(%1, ...) failed", curDir).c_str());
00123    }
00124 
00125    for (size_t i = 0; i < files.size(); ++i)
00126    {
00127       struct stat statbuf;
00128       String curFilePath = String(LOCAL_AUTH_DIR) + OW_FILENAME_SEPARATOR + files[i];
00129       if (lstat(curFilePath.c_str(), &statbuf) == -1)
00130       {
00131          OW_THROW_ERRNO_MSG(LocalAuthenticationException, Format("LocalAuthentication::initializeDir(): lstat(%1, ...)", curFilePath).c_str());
00132       }
00133 
00134       if (S_ISREG(statbuf.st_mode))
00135       {
00136          time_t curTime = ::time(NULL);
00137          const time_t ONE_DAY = 24 * 60 * 60;
00138          if ((statbuf.st_ctime < curTime - ONE_DAY) || statbuf.st_ctime > curTime)
00139          {
00140             if (::unlink(curFilePath.c_str()) == -1)
00141             {
00142                OW_THROW_ERRNO_MSG(LocalAuthenticationException, Format("LocalAuthentication::initializeDir(): unlink(%1)", curFilePath).c_str());
00143             }
00144          }
00145       }
00146    }
00147 }
00148 
00149 namespace
00150 {
00151    class UmaskRestorer
00152    {
00153    public:
00154       UmaskRestorer(::mode_t oldumask) 
00155          : m_oldumask(oldumask) 
00156       {
00157       }
00158       ~UmaskRestorer()
00159       {
00160          ::umask(m_oldumask);
00161       }
00162    private:
00163       ::mode_t m_oldumask;
00164    };
00165 
00166    class FileDeleter
00167    {
00168    public:
00169       FileDeleter(const String& filename)
00170          : m_filename(filename)
00171          , m_delete(true)
00172       {
00173       }
00174       ~FileDeleter()
00175       {
00176          if (m_delete)
00177          {
00178             FileSystem::removeFile(m_filename);
00179          }
00180       }
00181       void dontDelete()
00182       {
00183          m_delete = false;
00184       }
00185    private:
00186       String m_filename;
00187       bool m_delete;
00188    };
00189 }
00190 
00191 String createFile(const String& uid, const String& cookie)
00192 {
00193    uid_t userid = ~0;
00194    try
00195    {
00196       if (sizeof(userid) == sizeof(UInt16))
00197       {
00198          userid = uid.toUInt16();
00199       }
00200       else if (sizeof(userid) == sizeof(UInt32))
00201       {
00202          userid = uid.toUInt32();
00203       }
00204       else if (sizeof(userid) == sizeof(UInt64))
00205       {
00206          userid = uid.toUInt64();
00207       }
00208    }
00209    catch (StringConversionException& e)
00210    {
00211       OW_THROW(LocalAuthenticationException, Format("LocalAuthenticationCommon::createFile(): uid \"%1\" is not a valid uid_t", uid).c_str());
00212    }
00213 
00214    
00215 
00216    
00217 
00218    String tfname = Format("%1/%2XXXXXX", LOCAL_AUTH_DIR, ::getpid());
00219    int authfd;
00220 
00221    {
00222       
00223       
00224       
00225       ::mode_t oldumask = ::umask(0077);
00226       UmaskRestorer umaskRestorer(oldumask);
00227       authfd = ::mkstemp(&tfname[0]);
00228    }
00229 
00230    if (authfd == -1)
00231    {
00232       OW_THROW_ERRNO_MSG(LocalAuthenticationException, Format("LocalAuthenticationCommon::createFile(): mkstemp(%1)", tfname).c_str());
00233    }
00234 
00235    FileDeleter fileDeleter(tfname);
00236    File file(authfd);
00237 
00238    
00239    if (::fchmod(authfd, 0400) == -1)
00240    {
00241       OW_THROW_ERRNO_MSG(LocalAuthenticationException, Format("LocalAuthenticationCommon::createFile(): fchmod on %1", tfname).c_str());
00242    }
00243    
00244    
00245    if (::fchown(authfd, userid, static_cast<gid_t>(-1)) == -1)
00246    {
00247       OW_THROW_ERRNO_MSG(LocalAuthenticationException, Format("LocalAuthenticationCommon::createFile(): fchown on %1 to %2", tfname, userid).c_str());
00248    }
00249    
00250    
00251    if (file.write(cookie.c_str(), cookie.length()) != cookie.length())
00252    {
00253       OW_THROW_ERRNO_MSG(LocalAuthenticationException, Format("LocalAuthenticationCommon::createFile(): failed to write() the cookie to %1", tfname).c_str());
00254    }
00255    
00256    fileDeleter.dontDelete();
00257 
00258    return tfname;
00259 }
00260 
00261 } 
00262 } 
00263 
00264