00001
00002
00003
00004 #include "stdafx.h"
00005 #define FKSEC_NO_AUTO_INCLUDES 1
00006 #include "fksec.h"
00007 #include "ex.h"
00008 #include "sid.h"
00009 #include "ace.h"
00010 #include "acl.h"
00011
00012 using namespace fksec;
00013
00014
00017
00018
00019
00020
00021
00024 acl::acl()
00025 {
00026 Init();
00027 }
00028
00029
00030
00034 acl::acl( const acl &a )
00035 {
00036 Init();
00037 if ( a.IsValid() )
00038 {
00039 aces = a.aces;
00040 additionalBytes = a.additionalBytes;
00041 }
00042 else
00043 throw NEWEX( errInvalidAcl, "acl::acl(const acl&): invalid ACL" );
00044
00045 }
00046
00047
00048
00056 acl::acl( ACL *a )
00057 {
00058 ACL_SIZE_INFORMATION asi;
00059 DWORD i, n;
00060 void *pace;
00061
00062 Init();
00063 if ( IsValidAcl( a ) && ( a->AclRevision == ACL_REVISION ||
00064 a->AclRevision == ACL_REVISION_DS ) )
00065 {
00066 GetAclInformation( a, &asi, sizeof asi, AclSizeInformation );
00067 additionalBytes = asi.AclBytesFree;
00068 n = asi.AceCount;
00069 for ( i = 0; i < n; ++ i )
00070 {
00071 if ( ::GetAce( a, i, &pace ) )
00072 {
00073 try { AddAce( (DWORD) -1, pace ); }
00074 catch ( ex *e )
00075 {
00076 e->FKSECADDHOP( "acl::ace(ACL *): failed to add an ACE" );
00077 aces.clear();
00078 throw;
00079 }
00080 }
00081 }
00082 }
00083 else
00084 throw NEWEX( errInvalidAcl, "acl::acl(ACL *): invalid ACL, or bad revision" );
00085 }
00086
00087
00088
00091 acl::~acl()
00092 {
00093 ReleasePACL();
00094 aces.clear();
00095 }
00096
00097
00098
00099
00100
00101
00107 const acl &acl::operator=( const acl &s )
00108 {
00109 if ( this != &s )
00110 {
00111 ReleasePACL();
00112 if ( s.IsValid() )
00113 {
00114 aces = s.aces;
00115 additionalBytes = s.additionalBytes;
00116 }
00117 else
00118 throw NEWEX( errInvalidAcl, "acl::operator=(const acl&): invalid ACL" );
00119 }
00120
00121 return *this;
00122 }
00123
00124
00125
00134 const acl &acl::operator=( ACL *s )
00135 {
00136 ACL_SIZE_INFORMATION asi;
00137 DWORD i, n;
00138 void *pace;
00139
00140 if ( havePACL && pacl == s )
00141 return *this;
00142
00143 ReleasePACL();
00144 Init();
00145 if ( IsValidAcl( s ) )
00146 {
00147 GetAclInformation( s, &asi, sizeof asi, AclSizeInformation );
00148 additionalBytes = asi.AclBytesFree;
00149 n = asi.AceCount;
00150 for ( i = 0; i < n; ++ i )
00151 {
00152 if ( ::GetAce( s, i, &pace ) )
00153 {
00154 try { AddAce( (DWORD) -1, pace ); }
00155 catch ( ex *e )
00156 {
00157 e->FKSECADDHOP( "acl::operator=(ACL *): failed to add an ACE" );
00158 aces.clear();
00159 throw;
00160 }
00161 }
00162 }
00163 }
00164 else
00165 throw NEWEX( errInvalidAcl, "acl::operator=(ACL *): invalid ACL" );
00166
00167 return *this;
00168 }
00169
00170
00171
00172
00173
00174
00190 acl::operator ACL *() const
00191 {
00192 ACL *p;
00193
00194 try { p = MakePACL(); }
00195 RETHROWEX( "acl::operator const ACL *(): MakePACL() failed" )
00196
00197 return p;
00198 }
00199
00200
00201
00202
00203
00204
00211 const ace &acl::GetAce( DWORD index ) const
00212 {
00213 if ( index >= GetCount() )
00214 throw NEWEX( errInvalidAceIndex, "acl::GetAce(): ACE index out of range" );
00215
00216 return aces[index];
00217 }
00218
00219
00226 ace &acl::GetAce( DWORD index )
00227 {
00228 if ( index >= GetCount() )
00229 throw NEWEX( errInvalidAceIndex, "acl::GetAce(): ACE index out of range" );
00230
00231 return aces[index];
00232 }
00233
00234
00235
00242 DWORD acl::GetSize() const
00243 {
00244 return GetLength() + additionalBytes;
00245 }
00246
00247
00248
00252 DWORD acl::GetCount() const
00253 {
00254 return aces.size();
00255 }
00256
00257
00258
00264 void acl::SetFreeBytes( DWORD newAdditionalBytes )
00265 {
00266 additionalBytes = newAdditionalBytes;
00267 }
00268
00269
00270
00275 DWORD acl::GetFreeBytes() const
00276 {
00277 return additionalBytes;
00278 }
00279
00280
00281
00282
00283
00284
00285
00286
00287
00296 void acl::AddAce( DWORD index, const ace &a )
00297 {
00298 AceListIter i;
00299
00300 if ( index >= aces.size() )
00301 i = aces.end();
00302 else
00303 i = &aces[index];
00304
00305 aces.insert( i, a );
00306 }
00307
00308
00341 void acl::AddAce( DWORD index, byte type, byte flags, byte inheritance,
00342 ACCESS_MASK mask, const sid &newSid, const GUID &ObjectType ,
00343 const GUID &InheritedObjectType )
00344 {
00345 AceListIter i;
00346
00347 if ( index >= aces.size() )
00348 i = aces.end();
00349 else
00350 i = &aces[index];
00351
00352 aces.insert( i, ace( type, flags, inheritance, mask,
00353 newSid, ObjectType, InheritedObjectType ) );
00354 }
00355
00356
00357
00362 void acl::DeleteAce( DWORD index )
00363 {
00364 if ( index < aces.size() )
00365 aces.erase( &aces[index] );
00366 else
00367 throw NEWEX( errInvalidAceIndex, "acl::DeleteAce(): ACE index out of range" );
00368 }
00369
00370
00371
00377 void acl::DeleteAcesForSid( const sid &delSid )
00378 {
00379 int i;
00380
00381 for ( i = aces.size() - 1; i >= 0; -- i )
00382 {
00383 if ( aces[i].GetSid() == delSid )
00384 aces.erase( &aces[i] );
00385 }
00386 }
00387
00388
00413 ACCESS_MASK acl::GetEffectiveRights( const SidList& sids )
00414 {
00415 AceListConstIter i;
00416 ACCESS_MASK denied = 0, granted = 0;
00417
00418 if ( ! IsValid() )
00419 throw NEWEX( errInvalidAcl, "acl::GetEffectiveRights(): invalid ACL" );
00420
00421 for ( i = aces.begin(); i != aces.end(); ++ i )
00422 {
00423
00424
00425
00426
00427 if ( sids.end() != std::find( sids.begin(), sids.end(), i->GetSid() ) )
00428 {
00429 switch ( i->GetType() )
00430 {
00431 case ACCESS_ALLOWED_ACE_TYPE:
00432 case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
00433 case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
00434 granted |= i->GetMask();
00435 break;
00436 case ACCESS_DENIED_ACE_TYPE:
00437 case ACCESS_DENIED_OBJECT_ACE_TYPE:
00438 denied |= i->GetMask();
00439 break;
00440 default:
00441 throw NEWEX( errInvalidAcl, "acl::GetEffectiveRights(): only allow- and deny-ACEs are supported" );
00442 }
00443 }
00444 }
00445
00446 granted &= ~denied;
00447 return granted;
00448 }
00449
00450
00451
00452
00453
00454 void acl::normalize()
00455 {
00456 int i, j;
00457
00458 for ( i = 0; i < aces.size() - 1; ++ i )
00459 {
00460 for ( j = aces.size() - 1; j > i; -- j )
00461 {
00462 if ( aces[i] == aces[j] )
00463 {
00464 aces[i].SetMask( aces[i].GetMask() | aces[j].GetMask() );
00465 aces.erase( &aces[j] );
00466 }
00467 }
00468 }
00469 }
00470
00471
00472
00473
00474 void acl::canonicalize()
00475 {
00476 std::sort( aces.begin(), aces.end() );
00477 }
00478
00479
00480
00481 DWORD acl::GetLength() const
00482 {
00483 AceListConstIter i;
00484 DWORD totsize;
00485
00486 for ( totsize = 0, i = aces.begin(); i != aces.end(); ++ i )
00487 {
00488 try { totsize += i->GetLength(); }
00489 RETHROWEX( "acl::GetLength(): failed to retrieve an ACE's size" )
00490 }
00491
00492 totsize += sizeof ACL;
00493 return totsize;
00494 }
00495
00496
00497
00508 void acl::StoreAcl( ACL *p, DWORD sz ) const
00509 {
00510 AceListConstIter i;
00511 void *a;
00512 DWORD remaining, acelen;
00513
00514 if ( ! IsValid() )
00515 throw NEWEX( errInvalidAcl, "acl::StoreAcl(): invalid ACL" );
00516
00517 remaining = GetSize();
00518 if ( sz < remaining )
00519 {
00520 ex *e = NEWEX( errBufferTooSmall,
00521 "acl::StoreAcl(): insufficient buffer, see ex::GetData() for required size" );
00522 e->SetData( remaining );
00523 throw e;
00524 }
00525
00526 if ( ! ::InitializeAcl( p, remaining, GetRequiredAclRevision() ) )
00527 throw NEWEX32( errInvalidAcl,
00528 "acl::StoreAcl(): ::InitializeAcl() failed, see ex::GetErrWin32",
00529 GetLastError() );
00530
00531 p->AceCount = aces.size();
00532 a = (void *) &p[1];
00533 remaining -= sizeof ACL;
00534
00535 for ( i = aces.begin(); i != aces.end(); ++ i )
00536 {
00537 try
00538 {
00539 acelen = i->GetLength();
00540 i->StoreAce( a, remaining );
00541 }
00542 RETHROWEX( "acl::StoreAcl(): ran into a stubborn ACE" )
00543 a = (void *) ( (byte *) a + acelen );
00544 remaining -= acelen;
00545 }
00546
00547
00548
00549 if ( remaining != additionalBytes || ! IsValidAcl( p ) )
00550 throw NEWEX( errInvalidAcl,
00551 "acl::StoreAcl(): size calculation incorrect, or invalid ACL produced" );
00552 }
00553
00554
00555
00565 bool acl::IsValid() const
00566 {
00567 bool result = true;
00568
00569 try
00570 {
00571 for ( AceListConstIter i = aces.begin(); result && i != aces.end(); ++ i )
00572 result = result && i->IsValid();
00573 }
00574 catch ( ex *e )
00575 {
00576 delete e;
00577 return false;
00578 }
00579
00580 if ( GetSize() > 65535 )
00581 return false;
00582
00583 return true;
00584 }
00585
00586
00592 bool acl::IsObjectACL() const
00593 {
00594 AceListConstIter i;
00595
00596 for ( i = aces.begin(); i != aces.end(); ++ i )
00597 {
00598 if ( i->IsObjectACE() )
00599 return true;
00600 }
00601 return false;
00602 }
00603
00604
00605
00614 DWORD acl::GetRequiredAclRevision() const
00615 {
00616 return IsObjectACL()? ACL_REVISION_DS: ACL_REVISION;
00617 }
00618
00619
00620
00621
00622
00632 fkostream &fksec::operator<<( fkostream &o, const acl &a )
00633 {
00634 o << _T( "acl, " ) << a.aces.size() << _T( " ACEs, " )
00635 << a.additionalBytes << _T( " bytes extra space" ) << std::endl;
00636
00637 for ( AceListConstIter i = a.aces.begin(); i != a.aces.end(); ++ i )
00638 o << _T( " " ) << (*i) << std::endl;
00639
00640 return o;
00641 }
00642
00643
00646 void acl::Init()
00647 {
00648 aces.clear();
00649 additionalBytes = 0;
00650 ClearPACL();
00651 }
00652
00653
00654
00657 void acl::ClearPACL() const
00658 {
00659 havePACL = false;
00660 pacl = 0;
00661 }
00662
00663
00664
00668 void acl::ReleasePACL() const
00669 {
00670 if ( havePACL )
00671 {
00672 delete [] (byte *) pacl;
00673 pacl = 0;
00674 havePACL = false;
00675 }
00676 }
00677
00678
00691 ACL *acl::MakePACL() const
00692 {
00693 DWORD sz;
00694
00695 if ( ! havePACL )
00696 {
00697 if ( ! IsValid() )
00698 throw NEWEX( errInvalidAcl, "acl::MakePACL(): invalid ACL" );
00699
00700 sz = GetSize();
00701
00702 pacl = (ACL *) new byte[sz];
00703 if ( pacl == 0 )
00704 throw NEWEX( errNoMemory, "acl::MakePACL(): no memory for ACL buffer" );
00705
00706 try { StoreAcl( pacl, sz ); }
00707 catch ( ex *e )
00708 {
00709 e->FKSECADDHOP( "acl::MakePACL(): StoreAcl() is insubordinate" );
00710 delete (byte *) pacl;
00711 throw;
00712 }
00713
00714 havePACL = true;
00715 }
00716
00717 return pacl;
00718 }