00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "obp.h"
00022
00023
00024
#if DBG
00025
#define OB_DIAGNOSTICS_ENABLED 1
00026
#endif // DBG
00027
00028
00029
00030
00031
00032
#if OB_DIAGNOSTICS_ENABLED
00033
00034 ULONG ObsDebugFlags = 0;
00035
00036
00037
00038
00039
00040
#define IF_OB_GLOBAL( FlagName ) if (ObsDebugFlags & (OBS_DEBUG_##FlagName))
00041
00042
00043
00044
00045
00046
#define ObPrint( FlagName, _Text_ ) IF_OB_GLOBAL( FlagName ) DbgPrint _Text_
00047
00048
#else
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 #define IF_OB_GLOBAL( FlagName ) if (FALSE)
00059
00060
00061
00062
00063
00064 #define ObPrint( FlagName, _Text_ ) ;
00065
00066
#endif // OB_DIAGNOSTICS_ENABLED
00067
00068
00069
#if OB_DIAGNOSTICS_ENABLED
00070
00071 ULONG ObsTotalCacheEntries = 0;
00072
00073
#endif
00074
00075
00076
00077
00078
00079
00080
00081
00082 #define OBS_DEBUG_ALLOC_TRACKING ((ULONG) 0x00000001L)
00083 #define OBS_DEBUG_CACHE_FREES ((ULONG) 0x00000002L)
00084 #define OBS_DEBUG_BREAK_ON_INIT ((ULONG) 0x00000004L)
00085 #define OBS_DEBUG_SHOW_COLLISIONS ((ULONG) 0x00000008L)
00086 #define OBS_DEBUG_SHOW_STATISTICS ((ULONG) 0x00000010L)
00087 #define OBS_DEBUG_SHOW_REFERENCES ((ULONG) 0x00000020L)
00088 #define OBS_DEBUG_SHOW_DEASSIGN ((ULONG) 0x00000040L)
00089 #define OBS_DEBUG_STOP_INVALID_DESCRIPTOR ((ULONG) 0x00000080L)
00090 #define OBS_DEBUG_SHOW_HEADER_FREE ((ULONG) 0x00000100L)
00091
00092
00093
00094
00095
00096 PLIST_ENTRY *
ObsSecurityDescriptorCache =
NULL;
00097
00098
00099
00100
00101
00102
00103 ERESOURCE ObsSecurityDescriptorCacheLock;
00104
00105
#if defined (ALLOC_PRAGMA)
00106
#pragma alloc_text(PAGE,ObpDereferenceSecurityDescriptor)
00107
#pragma alloc_text(PAGE,ObpDestroySecurityDescriptorHeader)
00108
#pragma alloc_text(PAGE,ObpHashBuffer)
00109
#pragma alloc_text(PAGE,ObpHashSecurityDescriptor)
00110
#pragma alloc_text(PAGE,ObpInitSecurityDescriptorCache)
00111
#pragma alloc_text(PAGE,ObpLogSecurityDescriptor)
00112
#pragma alloc_text(PAGE,ObpReferenceSecurityDescriptor)
00113
#pragma alloc_text(PAGE,ObpCreateCacheEntry)
00114
#endif
00115
00116
00117
NTSTATUS
00118 ObpInitSecurityDescriptorCache (
00119 VOID
00120 )
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 {
00139 ULONG
Size;
00140
NTSTATUS Status;
00141
00142
IF_OB_GLOBAL( BREAK_ON_INIT ) {
00143
00144 DbgBreakPoint();
00145 }
00146
00147
00148
00149
00150
00151
Size =
SECURITY_DESCRIPTOR_CACHE_ENTRIES *
sizeof(PLIST_ENTRY);
00152
ObsSecurityDescriptorCache =
ExAllocatePoolWithTag(
PagedPool,
Size, 'cCdS' );
00153
00154
if (
ObsSecurityDescriptorCache ==
NULL ) {
00155
00156
return( STATUS_INSUFFICIENT_RESOURCES );
00157 }
00158
00159 RtlZeroMemory(
ObsSecurityDescriptorCache,
Size );
00160
00161
00162
00163
00164
00165
Status =
ExInitializeResource ( &
ObsSecurityDescriptorCacheLock );
00166
00167
if ( !
NT_SUCCESS(
Status) ) {
00168
00169
ExFreePool(
ObsSecurityDescriptorCache );
00170
return(
Status );
00171 }
00172
00173
00174
00175
00176
00177
return( STATUS_SUCCESS );
00178 }
00179
00180
00181 ULONG
00182 ObpHashSecurityDescriptor (
00183 PSECURITY_DESCRIPTOR SecurityDescriptor
00184 )
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 {
00203 PSID
Owner =
NULL;
00204 PSID
Group =
NULL;
00205
00206 PACL
Dacl;
00207 PACL Sacl;
00208
00209 ULONG Hash = 0;
00210 BOOLEAN Junk;
00211
NTSTATUS Status;
00212 BOOLEAN DaclPresent =
FALSE;
00213 BOOLEAN SaclPresent =
FALSE;
00214 PISECURITY_DESCRIPTOR sd;
00215
00216
00217
00218
00219
00220
00221 sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
00222
00223
Status =
RtlGetOwnerSecurityDescriptor( sd, &
Owner, &Junk );
00224
Status =
RtlGetGroupSecurityDescriptor( sd, &
Group, &Junk );
00225
Status =
RtlGetDaclSecurityDescriptor( sd, &DaclPresent, &
Dacl, &Junk );
00226
Status =
RtlGetSaclSecurityDescriptor( sd, &SaclPresent, &Sacl, &Junk );
00227
00228
if (
Owner !=
NULL ) {
00229
00230 Hash =
ObpHashBuffer(
Owner,
RtlLengthSid(
Owner ));
00231 }
00232
00233
if (
Group !=
NULL ) {
00234
00235 Hash +=
ObpHashBuffer(
Group,
RtlLengthSid(
Group));
00236 }
00237
00238
if ( DaclPresent && (
Dacl !=
NULL)) {
00239
00240 Hash +=
ObpHashBuffer(
Dacl,
Dacl->AclSize);
00241 }
00242
00243
if ( SaclPresent && (Sacl !=
NULL)) {
00244
00245 Hash +=
ObpHashBuffer( Sacl, Sacl->AclSize);
00246 }
00247
00248
return( Hash );
00249 }
00250
00251
00252 ULONG
00253 ObpHashBuffer (
00254 PVOID Data,
00255 ULONG Length
00256 )
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 {
00278 PCHAR
Buffer;
00279 ULONG Result = 0;
00280 LONG i;
00281
00282
Buffer = (PCHAR)Data;
00283
00284
for (i = 0; i <= (LONG)((Length-3)-
sizeof(ULONG)); i++) {
00285
00286 ULONG Tmp;
00287
00288 Tmp = *((ULONG UNALIGNED *)(
Buffer + i));
00289 Result += Tmp;
00290 }
00291
00292
return( Result );
00293 }
00294
00295
00296
NTSTATUS
00297 ObpLogSecurityDescriptor (
00298 IN PSECURITY_DESCRIPTOR InputSecurityDescriptor,
00299 OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor
00300 )
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 {
00325 ULONG FullHash;
00326 UCHAR SmallHash;
00327
PSECURITY_DESCRIPTOR_HEADER NewDescriptor;
00328 PLIST_ENTRY Front;
00329 PLIST_ENTRY Back;
00330
PSECURITY_DESCRIPTOR_HEADER Header;
00331 BOOLEAN Match;
00332
00333 FullHash =
ObpHashSecurityDescriptor( InputSecurityDescriptor );
00334 SmallHash = (UCHAR)FullHash;
00335
00336
00337
00338
00339
00340
00341
ObpAcquireDescriptorCacheWriteLock();
00342
00343 Front =
ObsSecurityDescriptorCache[SmallHash];
00344 Back =
NULL;
00345 Match =
FALSE;
00346
00347
00348
00349
00350
00351
while ( Front !=
NULL ) {
00352
00353
Header =
LINK_TO_SD_HEADER( Front );
00354
00355
00356
00357
00358
00359
00360
if (
Header->FullHash > FullHash ) {
00361
00362
break;
00363 }
00364
00365
if (
Header->FullHash == FullHash ) {
00366
00367 Match =
ObpCompareSecurityDescriptors( InputSecurityDescriptor,
00368 &
Header->SecurityDescriptor );
00369
00370
if ( Match ) {
00371
00372
break;
00373 }
00374
00375
ObPrint( SHOW_COLLISIONS,(
"Got a collision on %d, no match\n",SmallHash));
00376 }
00377
00378 Back = Front;
00379 Front = Front->Flink;
00380 }
00381
00382
00383
00384
00385
00386
00387
00388
if ( Match ) {
00389
00390
Header->RefCount++;
00391
00392
ObPrint( SHOW_REFERENCES, (
"Reference Hash = 0x%lX, New RefCount = %d\n",
Header->FullHash,
Header->RefCount));
00393
00394 *OutputSecurityDescriptor = &
Header->SecurityDescriptor;
00395
00396
ExFreePool( InputSecurityDescriptor );
00397
00398
ObpReleaseDescriptorCacheLock();
00399
00400
return( STATUS_SUCCESS );
00401 }
00402
00403
00404
00405
00406
00407
00408 NewDescriptor =
ObpCreateCacheEntry( InputSecurityDescriptor,
00409 FullHash );
00410
00411
if ( NewDescriptor ==
NULL ) {
00412
00413
ObpReleaseDescriptorCacheLock();
00414
00415
return( STATUS_INSUFFICIENT_RESOURCES );
00416 }
00417
00418
#if OB_DIAGNOSTICS_ENABLED
00419
00420 ObsTotalCacheEntries++;
00421
00422
#endif
00423
00424
ObPrint( SHOW_STATISTICS, (
"ObsTotalCacheEntries = %d \n",ObsTotalCacheEntries));
00425
ObPrint( SHOW_COLLISIONS, (
"Adding new entry for index #%d \n",SmallHash));
00426
00427
00428
00429
00430
00431
ExFreePool( InputSecurityDescriptor );
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
if ( Back ==
NULL ) {
00447
00448
00449
00450
00451
00452
00453 NewDescriptor->
Link.Flink =
ObsSecurityDescriptorCache[SmallHash];
00454
ObsSecurityDescriptorCache[SmallHash] = &NewDescriptor->
Link;
00455
00456
if ( NewDescriptor->
Link.Flink !=
NULL ) {
00457
00458 NewDescriptor->
Link.Flink->Blink = &NewDescriptor->
Link;
00459 }
00460
00461 }
else {
00462
00463
00464
00465
00466
00467 NewDescriptor->
Link.Flink = Front;
00468
00469 NewDescriptor->
Link.Blink = Back;
00470
00471 Back->Flink = &NewDescriptor->
Link;
00472
00473
if (Front !=
NULL) {
00474
00475 Front->Blink = &NewDescriptor->
Link;
00476 }
00477 }
00478
00479
00480
00481
00482
00483 *OutputSecurityDescriptor = &NewDescriptor->
SecurityDescriptor;
00484
ObpReleaseDescriptorCacheLock();
00485
00486
return( STATUS_SUCCESS );
00487 }
00488
00489
00490
PSECURITY_DESCRIPTOR_HEADER
00491 ObpCreateCacheEntry (
00492 PSECURITY_DESCRIPTOR InputSecurityDescriptor,
00493 ULONG FullHash
00494 )
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514 {
00515
00516 ULONG SecurityDescriptorLength;
00517 ULONG CacheEntrySize;
00518
PSECURITY_DESCRIPTOR_HEADER NewDescriptor;
00519
00520
00521
00522
00523
00524
00525
00526 SecurityDescriptorLength =
RtlLengthSecurityDescriptor ( InputSecurityDescriptor );
00527 CacheEntrySize = SecurityDescriptorLength + (
sizeof(
SECURITY_DESCRIPTOR_HEADER) -
sizeof( QUAD ));
00528
00529
00530
00531
00532
00533 NewDescriptor =
ExAllocatePoolWithTag(
PagedPool, CacheEntrySize, 'dSeS');
00534
00535
if ( NewDescriptor ==
NULL ) {
00536
00537
return(
NULL );
00538 }
00539
00540
00541
00542
00543
00544
00545 NewDescriptor->
RefCount = 1;
00546 NewDescriptor->
FullHash = FullHash;
00547 NewDescriptor->
Link.Flink =
NULL;
00548 NewDescriptor->
Link.Blink =
NULL;
00549
00550 RtlCopyMemory( &NewDescriptor->
SecurityDescriptor,
00551 InputSecurityDescriptor,
00552 SecurityDescriptorLength );
00553
00554
return( NewDescriptor );
00555 }
00556
00557
00558 PSECURITY_DESCRIPTOR
00559 ObpReferenceSecurityDescriptor (
00560 PVOID Object
00561 )
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579 {
00580
PSECURITY_DESCRIPTOR_HEADER SecurityDescriptorHeader;
00581
POBJECT_HEADER ObjectHeader;
00582
POBJECT_TYPE ObjectType;
00583 PSECURITY_DESCRIPTOR SecurityDescriptor;
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594 ObjectHeader =
OBJECT_TO_OBJECT_HEADER( Object );
00595 ObjectType = ObjectHeader->
Type;
00596
ASSERT(
ObpCentralizedSecurity(ObjectType) );
00597
00598
00599
00600
00601
00602
00603
ObpAcquireDescriptorCacheWriteLock();
00604
00605 SecurityDescriptor =
OBJECT_TO_OBJECT_HEADER( Object )->SecurityDescriptor;
00606
00607
IF_OB_GLOBAL( STOP_INVALID_DESCRIPTOR ) {
00608
00609
if((SecurityDescriptor !=
NULL) &&
00610 (!
RtlValidSecurityDescriptor ( SecurityDescriptor ))) {
00611
00612 DbgBreakPoint();
00613 }
00614 }
00615
00616
00617
00618
00619
00620
00621
00622
00623
if ( SecurityDescriptor !=
NULL ) {
00624
00625 SecurityDescriptorHeader =
SD_TO_SD_HEADER( SecurityDescriptor );
00626
ObPrint( SHOW_REFERENCES, (
"Referencing Hash %lX, Refcount = %d \n",SecurityDescriptorHeader->
FullHash,SecurityDescriptorHeader->
RefCount));
00627 SecurityDescriptorHeader->
RefCount++;
00628 }
00629
00630
ObpReleaseDescriptorCacheLock();
00631
00632
return( SecurityDescriptor );
00633 }
00634
00635
00636
NTSTATUS
00637 ObDeassignSecurity (
00638 IN OUT PSECURITY_DESCRIPTOR *SecurityDescriptor
00639 )
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658 {
00659
PSECURITY_DESCRIPTOR_HEADER Header;
00660
00661
00662
00663
00664
00665
00666
ObpAcquireDescriptorCacheWriteLock();
00667
00668
00669
00670
00671
00672
00673
Header =
SD_TO_SD_HEADER( *SecurityDescriptor );
00674
ObPrint( SHOW_DEASSIGN,(
"Deassigning security descriptor %x, hash = %lX\n",*SecurityDescriptor,
Header->FullHash));
00675
00676
00677
00678
00679
00680
ObpDereferenceSecurityDescriptor( *SecurityDescriptor );
00681
00682
00683
00684
00685
00686
00687 *SecurityDescriptor =
NULL;
00688
00689
00690
00691
00692
00693
ObpReleaseDescriptorCacheLock();
00694
00695
return( STATUS_SUCCESS );
00696 }
00697
00698
00699
VOID
00700 ObpDereferenceSecurityDescriptor (
00701 PSECURITY_DESCRIPTOR SecurityDescriptor
00702 )
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720 {
00721
PSECURITY_DESCRIPTOR_HEADER SecurityDescriptorHeader;
00722
00723
00724
00725
00726
00727
00728
ObpAcquireDescriptorCacheWriteLock();
00729
00730 SecurityDescriptorHeader =
SD_TO_SD_HEADER( SecurityDescriptor );
00731
00732
00733
00734
00735
00736
ObPrint( SHOW_REFERENCES, (
"Dereferencing SecurityDescriptor %x, hash %lx, refcount = %d \n", SecurityDescriptor, SecurityDescriptorHeader->
FullHash,SecurityDescriptorHeader->
RefCount));
00737
00738
ASSERT(SecurityDescriptorHeader->
RefCount != 0);
00739
00740
00741
00742
00743
00744
00745
if (--SecurityDescriptorHeader->
RefCount == 0) {
00746
00747
ObpDestroySecurityDescriptorHeader( SecurityDescriptorHeader );
00748 }
00749
00750
00751
00752
00753
00754
ObpReleaseDescriptorCacheLock();
00755 }
00756
00757
00758
VOID
00759 ObpDestroySecurityDescriptorHeader (
00760 IN
PSECURITY_DESCRIPTOR_HEADER Header
00761 )
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780 {
00781 PLIST_ENTRY Forward;
00782 PLIST_ENTRY Rear;
00783 UCHAR SmallHash;
00784
00785
ASSERT (
Header->RefCount == 0 );
00786
00787
#if OB_DIAGNOSTICS_ENABLED
00788
00789 ObsTotalCacheEntries--;
00790
00791
#endif
00792
00793
ObPrint( SHOW_STATISTICS, (
"ObsTotalCacheEntries = %d \n",ObsTotalCacheEntries));
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803 SmallHash = (UCHAR)
Header->FullHash;
00804
00805 Forward =
Header->Link.Flink;
00806 Rear =
Header->Link.Blink;
00807
00808
if ( Forward !=
NULL ) {
00809
00810 Forward->Blink = Rear;
00811 }
00812
00813
if ( Rear !=
NULL ) {
00814
00815 Rear->Flink = Forward;
00816
00817 }
else {
00818
00819
00820
00821
00822
00823
ObsSecurityDescriptorCache[SmallHash] = Forward;
00824 }
00825
00826
ObPrint( SHOW_HEADER_FREE, (
"Freeing memory at %x \n",
Header));
00827
00828
00829
00830
00831
00832
ExFreePool(
Header );
00833
00834
return;
00835 }
00836
00837
00838 BOOLEAN
00839 ObpCompareSecurityDescriptors (
00840 IN PSECURITY_DESCRIPTOR SD1,
00841 IN PSECURITY_DESCRIPTOR SD2
00842 )
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863 {
00864 ULONG Length1;
00865 ULONG Length2;
00866 ULONG
Compare;
00867
00868
00869
00870
00871
00872
00873 Length1 =
RtlLengthSecurityDescriptor ( SD1 );
00874 Length2 =
RtlLengthSecurityDescriptor ( SD2 );
00875
00876
if (Length1 != Length2) {
00877
00878
return(
FALSE );
00879 }
00880
00881
return (BOOLEAN)RtlEqualMemory ( SD1, SD2, Length1 );
00882 }
00883
00884
00885
VOID
00886 ObpAcquireDescriptorCacheWriteLock (
00887 VOID
00888 )
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906 {
00907
KeEnterCriticalRegion();
00908 (
VOID)
ExAcquireResourceExclusive( &
ObsSecurityDescriptorCacheLock,
TRUE );
00909
00910
return;
00911 }
00912
00913
VOID
00914 ObpAcquireDescriptorCacheReadLock (
00915 VOID
00916 )
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934 {
00935
KeEnterCriticalRegion();
00936 (
VOID)
ExAcquireResourceShared( &
ObsSecurityDescriptorCacheLock,
TRUE );
00937
00938
return;
00939 }
00940
00941
VOID
00942 ObpReleaseDescriptorCacheLock (
00943 VOID
00944 )
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962 {
00963 (
VOID)
ExReleaseResource( &
ObsSecurityDescriptorCacheLock );
00964
KeLeaveCriticalRegion ();
00965
00966
return;
00967 }
00968