OW_LocalAuthenticationCommon.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2005 Vintela, Inc. All rights reserved.
00003 *
00004 * Redistribution and use in source and binary forms, with or without
00005 * modification, are permitted provided that the following conditions are met:
00006 *
00007 *  - Redistributions of source code must retain the above copyright notice,
00008 *    this list of conditions and the following disclaimer.
00009 *
00010 *  - Redistributions in binary form must reproduce the above copyright notice,
00011 *    this list of conditions and the following disclaimer in the documentation
00012 *    and/or other materials provided with the distribution.
00013 *
00014 *  - Neither the name of Vintela, Inc. nor the names of its
00015 *    contributors may be used to endorse or promote products derived from this
00016 *    software without specific prior written permission.
00017 *
00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc. OR THE CONTRIBUTORS
00022 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028 * POSSIBILITY OF SUCH DAMAGE.
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       // for each intermediary dir, try to create it.
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          // if we actually created the directory, remove the set-group-id bit & fix any permissions removed by the current umask 
00082          // and change the file & group ownership to the real user/group id
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       // check that all intermediary dirs have at least a+rx perms, otherwise fail.
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    // for each file in the dir, check it's creation time and delete it if its more than a day old or newer than the current time.
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    //-- Create temporary file for auth process
00215 
00216    // Some old implementations of mkstemp() create a file with mode 0666.
00217 
00218    String tfname = Format("%1/%2XXXXXX", LOCAL_AUTH_DIR, ::getpid());
00219    int authfd;
00220 
00221    {
00222       // The fact that the umask is set to 0077 makes this safe from prying eyes.
00223       // Note that this could cause a problem for the calling code, especially if it's threaded.
00224       // however, owcimomd has a 0077 mask anyway, and owlocalhelper is single threaded.
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    //-- Change file permission on temp file to read/write for user only
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    //-- Change file so the user connecting is the owner
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    // Write the servers random number to the temp file
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 } // end namespace LocalAuthenticationCommon
00262 } // end namespace OW_NAMESPACE
00263 
00264 

Generated on Thu Feb 9 08:48:03 2006 for openwbem by  doxygen 1.4.6