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