00001
00002
00003
00004 #include "stdafx.h"
00005 #define FKSEC_NO_AUTO_INCLUDES 1
00006 #include "fksec.h"
00007 #include "ex.h"
00008 #include "priv.h"
00009
00010 using namespace fksec;
00011
00014
00015
00016
00017
00018 priv::priv()
00019 {
00020 Init();
00021 }
00022
00023
00024 priv::priv( const priv &s )
00025 {
00026 privNum = s.privNum;
00027 privName = s.privName;
00028 dispName = s.dispName;
00029 ht = 0;
00030 try { SetHandle( s.ht ); }
00031 RETHROWEX( "priv::priv(const priv&): invalid token handle" )
00032 }
00033
00034
00035 priv::priv( const LUID s )
00036 {
00037 privNum = s;
00038 try { LookupNames(); }
00039 RETHROWEX( "priv::priv(const LUID): LookupNames() failed; invalid privilege LUID?" )
00040
00041 ht = 0;
00042 }
00043
00044
00045 priv::priv( unsigned __int64 s )
00046 {
00047 privNum.LowPart = (DWORD) ( s & 0xffffffffUI64 );
00048 privNum.HighPart = (DWORD) ( s >> 32 );
00049
00050 try { LookupNames(); }
00051 RETHROWEX( "priv::priv(unsigned __int64): LookupNames() failed; invalid privilege LUID?" )
00052
00053 ht = 0;
00054 }
00055
00056
00057 priv::priv( const TCHAR *name )
00058 {
00059 try { LookupValue( name ); }
00060 RETHROWEX( "priv::priv(const TCHAR *): LookupValue() failed; invalid privilege name?" )
00061
00062 ht = 0;
00063 }
00064
00065
00066 priv::~priv()
00067 {
00068 try { closeToken(); }
00069 catch ( ex *e ) { delete e; }
00070 }
00071
00072
00073
00074
00075
00076 const priv &priv::operator=( const priv &s )
00077 {
00078 if ( this != &s )
00079 {
00080 privNum = s.privNum;
00081 privName = s.privName;
00082 dispName = s.dispName;
00083 try { closeToken(); }
00084 RETHROWEX( "priv::operator=(): closeToken() failed" )
00085 try { SetHandle( s.ht ); }
00086 RETHROWEX( "priv::operator=(const priv&): invalid token handle" )
00087 }
00088
00089 return *this;
00090 }
00091
00092
00093 const priv &priv::operator=( const LUID s )
00094 {
00095 privNum = s;
00096 try { LookupNames(); }
00097 RETHROWEX( "priv::operator=(const LUID): LookupNames() failed; invalid privilege LUID?" )
00098 return *this;
00099 }
00100
00101
00102 const priv &priv::operator=( unsigned __int64 s )
00103 {
00104 privNum.LowPart = (DWORD) ( s & 0xffffffffUI64 );
00105 privNum.HighPart = (DWORD) ( s >> 32 );
00106
00107 try { LookupNames(); }
00108 RETHROWEX( "priv::operator=(unsigned __int64): LookupNames() failed; invalid privilege LUID?" )
00109 return *this;
00110 }
00111
00112
00113 const priv &priv::operator=( const TCHAR *name )
00114 {
00115 try { LookupValue( name ); }
00116 RETHROWEX( "priv::operator=(const TCHAR *): LookupValue() failed; invalid privilege name?" )
00117
00118 return *this;
00119 }
00120
00121
00122
00123
00124
00125 bool priv::operator==( const priv &r ) const
00126 {
00127 return privNum.LowPart == r.privNum.LowPart && privNum.HighPart == r.privNum.HighPart;
00128 }
00129
00130
00131 bool priv::operator!=( const priv &r ) const
00132 {
00133 return privNum.LowPart != r.privNum.LowPart || privNum.HighPart != r.privNum.HighPart;
00134 }
00135
00136
00137
00138
00139
00140 fkostream &fksec::operator<<( fkostream &o, const priv& p )
00141 {
00142 bool state, haveState;
00143
00144 try { state = p.GetState(); haveState = true; }
00145 catch ( ex & ) { haveState = false; }
00146
00147 o << _T( "Privilege: " ) << p.privNum.LowPart << _T( ", " ) <<
00148 p.privName << _T( " (" ) << p.dispName << _T( ")" );
00149 if ( haveState )
00150 o << _T( ", state: " ) << ( state? _T( "enabled" ): _T( "disabled" ) );
00151 return o;
00152 }
00153
00154
00155
00156
00157
00158 const TCHAR *priv::GetPrivilegeName() const
00159 {
00160 return privName.c_str();
00161 }
00162
00163
00164 const TCHAR *priv::GetDisplayName() const
00165 {
00166 return dispName.c_str();
00167 }
00168
00169
00170 bool priv::Enable()
00171 {
00172 try { return SetState( true ); }
00173 RETHROWEX( "priv::Enable(): SetState() failed" )
00174 }
00175
00176
00177 bool priv::Disable()
00178 {
00179 try { return SetState( false ); }
00180 RETHROWEX( "priv::Disable(): SetState() failed" )
00181 }
00182
00183
00184 bool priv::Toggle()
00185 {
00186 bool oldState;
00187
00188 try { oldState = GetState(); }
00189 RETHROWEX( "priv::Toggle(): GetState() failed" )
00190
00191 try { return SetState( ! oldState ); }
00192 RETHROWEX( "priv::Toggle(): SetState() failed" )
00193 }
00194
00195
00196 bool priv::SetState( bool newState )
00197 {
00198 TOKEN_PRIVILEGES tp, otp;
00199 DWORD returnLength = sizeof otp;
00200
00201 try { openToken(); }
00202 RETHROWEX( "priv::SetState(): openToken() failed" )
00203
00204 tp.PrivilegeCount = 1;
00205 tp.Privileges[0].Luid = privNum;
00206 tp.Privileges[0].Attributes = newState? SE_PRIVILEGE_ENABLED: 0;
00207
00208 if ( ::AdjustTokenPrivileges( ht, FALSE, &tp, sizeof tp, &otp, &returnLength ) )
00209 {
00210 if ( GetLastError() == ERROR_SUCCESS )
00211
00212 return !! ( ( SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT ) &
00213 otp.Privileges[0].Attributes );
00214 throw NEWEX32( errStubbornPriv, "priv::SetState(): AdjustTokenPrivileges() succeeded but did not set the privilege state, see ex::GetErrWin32()", GetLastError() );
00215 }
00216
00217 throw NEWEX32( errStubbornPriv, "priv::SetState(): AdjustTokenPrivileges() failed, see ex::GetErrWin32()", GetLastError() );
00218
00219
00220 return false;
00221 }
00222
00223
00224 bool priv::GetState() const
00225 {
00226
00227 byte buf[sizeof TOKEN_PRIVILEGES + 50 * sizeof LUID_AND_ATTRIBUTES];
00228 TOKEN_PRIVILEGES &tp = *( (TOKEN_PRIVILEGES *) buf );
00229 DWORD returnLength, i;
00230
00231 try { openToken(); }
00232 RETHROWEX( "priv::GetState(): openToken() failed" )
00233
00234 if ( ::GetTokenInformation( ht, TokenPrivileges, &buf[0], sizeof buf, &returnLength ) )
00235 {
00236 for ( i = 0; i < tp.PrivilegeCount; ++ i )
00237 {
00238 if ( privNum.LowPart == tp.Privileges[i].Luid.LowPart &&
00239 privNum.HighPart == tp.Privileges[i].Luid.HighPart )
00240 return !! ( ( SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT ) & tp.Privileges[i].Attributes );
00241 }
00242 return false;
00243 }
00244
00245 throw NEWEX32( errQueryToken, "priv::GetState(): GetTokenInformation() failed, see ex::GetErrWin32()", GetLastError() );
00246
00247
00248 return false;
00249 }
00250
00251
00252 void priv::SetHandle( HANDLE h )
00253 {
00254 try { closeToken(); }
00255 RETHROWEX( "priv::SetHandle(): closeToken() failed" )
00256
00257 if ( h != 0 )
00258 {
00259 if ( ! ::DuplicateHandle( GetCurrentProcess(), h, GetCurrentProcess(),
00260 &ht, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, FALSE, 0 ) )
00261 throw NEWEX32( errDupTokenHandle, "priv::SetHandle(): DuplicateHandle() failed, see ex::GetErrWin32()", GetLastError() );
00262 }
00263 else
00264 ht = h;
00265 }
00266
00267
00268 void priv::Init()
00269 {
00270 ht = 0;
00271 privNum.LowPart = privNum.HighPart = 0;
00272 privName.erase();
00273 dispName.erase();
00274 }
00275
00276
00277 void priv::openToken() const
00278 {
00279 DWORD rc;
00280 const TCHAR *func = _T( "what?" );
00281
00282 if ( ht != 0 )
00283 return;
00284
00285 rc = 0;
00286 func = _T( "OpenThreadToken()" );
00287 if ( ! ::OpenThreadToken( GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, FALSE, &ht ) )
00288 rc = GetLastError();
00289
00290
00291 if ( rc == ERROR_ACCESS_DENIED || rc == ERROR_NO_TOKEN || rc == ERROR_NO_IMPERSONATION_TOKEN )
00292 {
00293 rc = 0;
00294 func = _T( "OpenThreadToken() as self" );
00295 if ( ! ::OpenThreadToken( GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, TRUE, &ht ) )
00296 rc = GetLastError();
00297
00298
00299 if ( rc == ERROR_ACCESS_DENIED || rc == ERROR_NO_TOKEN || rc == ERROR_NO_IMPERSONATION_TOKEN )
00300 {
00301 rc = 0;
00302 func = _T( "OpenProcessToken()" );
00303 if ( ! ::OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &ht ) )
00304 rc = GetLastError();
00305 }
00306 }
00307
00308 if ( rc != 0 )
00309 {
00310 ht = 0;
00311 fkstr errstr = _T( "priv::openToken(): " ) + fkstr( func ) + _T( " failed, see ex::GetErrWin32()" );
00312 throw new ex( _T( __FILE__ ), __LINE__, errOpenToken, errstr.c_str(), rc );
00313 }
00314 }
00315
00316
00317 void priv::closeToken() const
00318 {
00319 if ( ht != 0 )
00320 {
00321 if ( ! CloseHandle( ht ) )
00322 {
00323 ht = 0;
00324 throw NEWEX32( errCloseToken, "priv::closeToken(): CloseHandle() failed, see ex::GetErrWin32()", GetLastError() );
00325 }
00326 ht = 0;
00327 }
00328 }
00329
00330
00331 void priv::LookupNames() const
00332 {
00333 const static DWORD initialBufLen = 128;
00334 DWORD namelen, buflen, langID, rc;
00335 BOOL result;
00336 TCHAR *name;
00337
00338 buflen = initialBufLen;
00339 name = 0;
00340 do
00341 {
00342 buflen *= 2;
00343 delete [] name;
00344 name = new TCHAR[buflen];
00345 if ( name == 0 )
00346 throw NEWEX( errNoMemory, "priv::LookupNames(): no memory for priv name buffer" );
00347 namelen = buflen;
00348 result = ::LookupPrivilegeName( 0,
00349 const_cast<LUID *>( &privNum ), name, &namelen );
00350 rc = result? 0: GetLastError();
00351 } while ( ! result && rc == ERROR_INSUFFICIENT_BUFFER );
00352
00353 if ( rc == 0 )
00354 privName = name;
00355
00356 delete [] name;
00357
00358 if ( rc != 0 )
00359 throw NEWEX32( errInvalidPriv, "priv::LookupNames(): privilege name not found", rc );
00360
00361 buflen = initialBufLen;
00362 name = 0;
00363 do
00364 {
00365 buflen *= 2;
00366 delete [] name;
00367 name = new TCHAR[buflen];
00368 if ( name == 0 )
00369 throw NEWEX( errNoMemory, "priv::LookupNames(): no memory for priv display-name buffer" );
00370 namelen = buflen;
00371 result = ::LookupPrivilegeDisplayName( 0,
00372 privName.c_str(), name, &namelen, &langID );
00373 rc = result? 0: GetLastError();
00374 } while ( ! result && rc == ERROR_INSUFFICIENT_BUFFER );
00375
00376 if ( rc == 0 )
00377 dispName = name;
00378
00379 delete [] name;
00380
00381 if ( rc != 0 )
00382 throw NEWEX32( errInvalidPriv, "priv::LookupNames(): privilege display-name not found", rc );
00383 }
00384
00385
00386 void priv::LookupValue( const TCHAR *name )
00387 {
00388 if ( ! ::LookupPrivilegeValue( 0, name, &privNum ) )
00389 throw NEWEX32( errInvalidPriv, "priv::LookupValue(): privilege not found", GetLastError() );
00390
00391 try { LookupNames(); }
00392 RETHROWEX( "priv::LookupValue(): cannot get names for privilege" )
00393 }