Main Page   Namespace List   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

priv.cpp

Go to the documentation of this file.
00001 // recommended includes in stdafx.h (or in the precompiled header, to be precise):
00002 // windows.h, tchar.h, string, vector, algorithm, exception, sstream, iomanip
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 // --- ctors/dtor ---
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; } // eat exceptions
00070 }
00071 
00072 
00073 
00074 // --- assignment ---
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 // --- comparisons ---
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 // --- inserters ---
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 // --- utilities ---
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             // all is well, return previous state
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     // unreachable code -- but VC 5.0 complains if this is absent
00220     return false;
00221 }
00222 
00223 
00224 bool priv::GetState() const
00225 {
00226     // this limits us to 50 privs; currently defined (NT5 RC3) are 27, plus 4 logon rights.
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; // a missing priv is considered disabled
00243     }
00244 
00245     throw NEWEX32( errQueryToken, "priv::GetState(): GetTokenInformation() failed, see ex::GetErrWin32()", GetLastError() );
00246 
00247     // unreachable code -- but VC 5.0 complains if this is absent
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; // == 0
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     // OTT() failed with something recoverable?
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         // OTT() failed again? try OPT()
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 }

Generated at Mon Oct 16 06:14:07 2000 for fksec by doxygen1.2.2 written by Dimitri van Heesch, © 1997-2000