blocxx
|
00001 /******************************************************************************* 00002 * Copyright (C) 2005, Vintela, Inc. All rights reserved. 00003 * Copyright (C) 2006, Novell, Inc. All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * * Redistributions of source code must retain the above copyright notice, 00009 * this list of conditions and the following disclaimer. 00010 * * Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * * Neither the name of 00014 * Vintela, Inc., 00015 * nor Novell, Inc., 00016 * nor the names of its contributors or employees may be used to 00017 * endorse or promote products derived from this software without 00018 * specific prior written permission. 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00021 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00022 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00023 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00024 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00025 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00026 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00027 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00028 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00029 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00030 * POSSIBILITY OF SUCH DAMAGE. 00031 *******************************************************************************/ 00032 00033 00039 #include "blocxx/BLOCXX_config.h" 00040 #include "blocxx/Mutex.hpp" 00041 #include "blocxx/MutexLock.hpp" 00042 #include "blocxx/GlobalMutex.hpp" 00043 #include "blocxx/UserUtils.hpp" 00044 00045 #ifdef BLOCXX_HAVE_UNISTD_H 00046 #include <unistd.h> 00047 #endif 00048 00049 #ifdef BLOCXX_HAVE_SYS_TYPES_H 00050 #include <sys/types.h> 00051 #endif 00052 00053 #ifdef BLOCXX_HAVE_PWD_H 00054 #include <pwd.h> 00055 #endif 00056 00057 #include <cerrno> 00058 #include <vector> 00059 00060 #ifdef BLOCXX_WIN32 00061 00062 BLOCXX_NAMESPACE::UserId geteuid(void ) 00063 { 00064 // SID/uid Win32/NIX wrapper 00065 BLOCXX_NAMESPACE::UserId sid = (BLOCXX_NAMESPACE::UserId)NULL; 00066 HANDLE pToken = (HANDLE)0L; 00067 DWORD bufLength = 256; 00068 static int* tkUser[256]; // only a static buffer we need with no SID copy privileges :( 00069 00070 if ( ::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &pToken) ) 00071 { 00072 ::GetTokenInformation(pToken, TokenUser, tkUser, bufLength, &bufLength); 00073 sid = ((TOKEN_USER*)tkUser)->User.Sid; 00074 TCHAR sName[MAX_PATH], sDName[MAX_PATH]; 00075 DWORD sNameLen, sDNameLen = sNameLen = MAX_PATH; 00076 SID_NAME_USE eUse; 00077 ::LookupAccountSid( NULL, sid, sName, &sNameLen, sDName, &sDNameLen, &eUse); 00078 CloseHandle(pToken); 00079 } 00080 return sid; 00081 } 00082 #endif //BLOCXX_WIN32 00083 00084 namespace BLOCXX_NAMESPACE 00085 { 00086 00087 namespace UserUtils 00088 { 00089 00091 String getEffectiveUserId() 00092 { 00093 #ifdef BLOCXX_WIN32 00094 // TODO 00095 // The user ID is represented by a SID on Win32. Going to return 0 for 00096 // admin user on win32 for now. Eventually blocxx will 00097 // deal with userid on Win32 the proper way. 00098 00099 // 20070625 Anton Afanasiev - maybe the better idea is to use ConvertSidToStringSid routing 00100 // the code below implements the same 00101 PSID_IDENTIFIER_AUTHORITY psia; 00102 DWORD dwSubAuthorities; 00103 DWORD dwSidRev=SID_REVISION; 00104 DWORD dwCounter; 00105 DWORD dwSidSize; 00106 UserId uid = ::geteuid(); 00107 String strResult, strSubResult; 00108 00109 if (!uid || !IsValidSid(uid)) 00110 return String(); 00111 psia = GetSidIdentifierAuthority(uid); 00112 dwSubAuthorities = *GetSidSubAuthorityCount(uid); 00113 dwSidSize = (15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR); 00114 if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) ) 00115 { 00116 strSubResult.format( 00117 TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"), 00118 (USHORT)psia->Value[0], 00119 (USHORT)psia->Value[1], 00120 (USHORT)psia->Value[2], 00121 (USHORT)psia->Value[3], 00122 (USHORT)psia->Value[4], 00123 (USHORT)psia->Value[5]); 00124 } 00125 else 00126 { 00127 strSubResult.format( 00128 TEXT("%lu"), 00129 (ULONG)(psia->Value[5] ) + 00130 (ULONG)(psia->Value[4] << 8) + 00131 (ULONG)(psia->Value[3] << 16) + 00132 (ULONG)(psia->Value[2] << 24) ); 00133 } 00134 00135 for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++) 00136 { 00137 strSubResult.format( 00138 TEXT("%s-%lu"), strSubResult.c_str(), 00139 *GetSidSubAuthority(uid, dwCounter) ); 00140 } 00141 00142 strResult.format(TEXT("S-%lu-%s"), dwSidRev, strSubResult); 00143 return strResult; 00144 #else 00145 return String(Int64(::geteuid())); 00146 #endif 00147 } 00148 00150 String getCurrentUserName() 00151 { 00152 bool ok; 00153 #ifdef BLOCXX_WIN32 00154 return getUserName(geteuid(), ok); 00155 #else 00156 return getUserName(getuid(),ok); 00157 #endif 00158 } 00159 00160 namespace 00161 { 00162 GlobalMutex g_getpwMutex = BLOCXX_GLOBAL_MUTEX_INIT(); 00163 } 00164 00165 namespace // anonymous 00166 { 00167 // Get a sysconf value. If no value is set (or another error occurs), return the default value. 00168 long getSysconfValue(int name, long default_value, int& error) 00169 { 00170 #ifdef BLOCXX_WIN32 00171 #pragma message(Reminder "TODO: Implement for Win if you use getSysconfValue not only for _SC_GETPW_R_SIZE_MAX") 00172 error = 0; 00173 return default_value; 00174 #else 00175 errno = 0; 00176 00177 long l = sysconf(name); 00178 00179 if( l == -1 ) 00180 { 00181 if( errno == 0 ) 00182 { 00183 // The POSIX standard says this means the limit is indefinite (not infinite). 00184 error = 0; 00185 return default_value; 00186 } 00187 else 00188 { 00189 error = errno; 00190 return default_value; 00191 } 00192 } 00193 else 00194 { 00195 error = 0; 00196 return l; 00197 } 00198 #endif 00199 } 00200 00201 long getSysconfValue(int name, long default_value) 00202 { 00203 int unused; 00204 return getSysconfValue(name, default_value, unused); 00205 } 00206 } // end annymous namespace 00207 00209 String getUserName(uid_t uid,bool& ok) 00210 { 00211 #ifdef BLOCXX_WIN32 00212 // TODO 00213 // Ignore uid for right now. Just return the current User (WRONG!) 00214 // Need to come back to this later when the uid_t stuff is worked out. 00215 00216 // 20070625 Anton Afanasiev 00217 TCHAR cchName[256], cchDomainName[256]; 00218 SID_NAME_USE snuOutVar; 00219 DWORD cchNameBufLen = sizeof(cchName), cchDomainNameBufLen = sizeof(cchDomainName); 00220 00221 ok = ::LookupAccountSid(NULL, 00222 uid, 00223 cchName, 00224 &cchNameBufLen, 00225 cchDomainName, 00226 &cchDomainNameBufLen, 00227 &snuOutVar); 00228 return String(cchName); 00229 #else 00230 00231 #ifdef BLOCXX_HAVE_GETPWUID_R 00232 passwd pw; 00233 size_t const additionalSize = 00234 #ifdef _SC_GETPW_R_SIZE_MAX 00235 getSysconfValue(_SC_GETPW_R_SIZE_MAX, 10240); 00236 #else 00237 10240; 00238 #endif 00239 std::vector<char> additional(additionalSize); 00240 passwd* result; 00241 int rv = 0; 00242 do 00243 { 00244 rv = ::getpwuid_r(uid, &pw, &additional[0], additional.size(), &result); 00245 if (rv == ERANGE) 00246 { 00247 additional.resize(additional.size() * 2); 00248 } 00249 } while (rv == ERANGE); 00250 #else 00251 MutexLock lock(g_getpwMutex); 00252 passwd* result = ::getpwuid(uid); 00253 #endif 00254 if (result) 00255 { 00256 ok = true; 00257 return result->pw_name; 00258 } 00259 ok = false; 00260 return ""; 00261 #endif 00262 } 00263 00265 UserID 00266 getUserId(const String& userName, bool& validUserName) 00267 { 00268 validUserName = false; 00269 00270 #ifdef BLOCXX_WIN32 00271 // 20070625 Anton Afanasiev 00272 static DWORD uid[64]; // AA: do we really need for 'static' here? 00273 DWORD cbUid = sizeof(uid) * sizeof(DWORD); 00274 SID_NAME_USE snuOutVar; 00275 DWORD cbDomainBufSize = MAX_PATH; 00276 TCHAR strDomainBuf[MAX_PATH] = {0}; 00277 00278 return (validUserName=::LookupAccountName( 00279 NULL, 00280 userName.c_str(), 00281 &uid, 00282 &cbUid, 00283 strDomainBuf, 00284 &cbDomainBufSize, 00285 &snuOutVar))? &uid : NULL; 00286 00287 #else 00288 00289 00290 #ifdef BLOCXX_HAVE_GETPWNAM_R 00291 size_t bufsize = 00292 #ifdef _SC_GETPW_R_SIZE_MAX 00293 getSysconfValue(_SC_GETPW_R_SIZE_MAX, 10240); 00294 #else 00295 1024; 00296 #endif 00297 std::vector<char> buf(bufsize); 00298 struct passwd pwd; 00299 passwd* result = 0; 00300 int rv = 0; 00301 do 00302 { 00303 rv = ::getpwnam_r(userName.c_str(), &pwd, &buf[0], bufsize, &result); 00304 if (rv == ERANGE) 00305 { 00306 buf.resize(buf.size() * 2); 00307 } 00308 } while (rv == ERANGE); 00309 00310 if (rv != 0) 00311 { 00312 return INVALID_USERID; 00313 } 00314 00315 #else 00316 MutexLock ml(g_getpwMutex); 00317 struct passwd* result; 00318 result = ::getpwnam(userName.c_str()); 00319 #endif 00320 if (result) 00321 { 00322 validUserName = true; 00323 return result->pw_uid; 00324 } 00325 return INVALID_USERID; 00326 #endif 00327 } 00328 } // end namespace UserUtils 00329 } // end namespace BLOCXX_NAMESPACE 00330 00331