1*c2c66affSColin Finck /* 2*c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory 3*c2c66affSColin Finck * PROJECT: ReactOS kernel 4*c2c66affSColin Finck * FILE: ntoskrnl/se/sd.c 5*c2c66affSColin Finck * PURPOSE: Security manager 6*c2c66affSColin Finck * 7*c2c66affSColin Finck * PROGRAMMERS: David Welch <welch@cwcom.net> 8*c2c66affSColin Finck */ 9*c2c66affSColin Finck 10*c2c66affSColin Finck /* INCLUDES *******************************************************************/ 11*c2c66affSColin Finck 12*c2c66affSColin Finck #include <ntoskrnl.h> 13*c2c66affSColin Finck #define NDEBUG 14*c2c66affSColin Finck #include <debug.h> 15*c2c66affSColin Finck 16*c2c66affSColin Finck #if defined (ALLOC_PRAGMA) 17*c2c66affSColin Finck #pragma alloc_text(INIT, SepInitSDs) 18*c2c66affSColin Finck #endif 19*c2c66affSColin Finck 20*c2c66affSColin Finck /* GLOBALS ********************************************************************/ 21*c2c66affSColin Finck 22*c2c66affSColin Finck PSECURITY_DESCRIPTOR SePublicDefaultSd = NULL; 23*c2c66affSColin Finck PSECURITY_DESCRIPTOR SePublicDefaultUnrestrictedSd = NULL; 24*c2c66affSColin Finck PSECURITY_DESCRIPTOR SePublicOpenSd = NULL; 25*c2c66affSColin Finck PSECURITY_DESCRIPTOR SePublicOpenUnrestrictedSd = NULL; 26*c2c66affSColin Finck PSECURITY_DESCRIPTOR SeSystemDefaultSd = NULL; 27*c2c66affSColin Finck PSECURITY_DESCRIPTOR SeUnrestrictedSd = NULL; 28*c2c66affSColin Finck 29*c2c66affSColin Finck /* PRIVATE FUNCTIONS **********************************************************/ 30*c2c66affSColin Finck 31*c2c66affSColin Finck BOOLEAN 32*c2c66affSColin Finck INIT_FUNCTION 33*c2c66affSColin Finck NTAPI 34*c2c66affSColin Finck SepInitSDs(VOID) 35*c2c66affSColin Finck { 36*c2c66affSColin Finck /* Create PublicDefaultSd */ 37*c2c66affSColin Finck SePublicDefaultSd = ExAllocatePoolWithTag(PagedPool, 38*c2c66affSColin Finck sizeof(SECURITY_DESCRIPTOR), TAG_SD); 39*c2c66affSColin Finck if (SePublicDefaultSd == NULL) 40*c2c66affSColin Finck return FALSE; 41*c2c66affSColin Finck 42*c2c66affSColin Finck RtlCreateSecurityDescriptor(SePublicDefaultSd, 43*c2c66affSColin Finck SECURITY_DESCRIPTOR_REVISION); 44*c2c66affSColin Finck RtlSetDaclSecurityDescriptor(SePublicDefaultSd, 45*c2c66affSColin Finck TRUE, 46*c2c66affSColin Finck SePublicDefaultDacl, 47*c2c66affSColin Finck FALSE); 48*c2c66affSColin Finck 49*c2c66affSColin Finck /* Create PublicDefaultUnrestrictedSd */ 50*c2c66affSColin Finck SePublicDefaultUnrestrictedSd = ExAllocatePoolWithTag(PagedPool, 51*c2c66affSColin Finck sizeof(SECURITY_DESCRIPTOR), TAG_SD); 52*c2c66affSColin Finck if (SePublicDefaultUnrestrictedSd == NULL) 53*c2c66affSColin Finck return FALSE; 54*c2c66affSColin Finck 55*c2c66affSColin Finck RtlCreateSecurityDescriptor(SePublicDefaultUnrestrictedSd, 56*c2c66affSColin Finck SECURITY_DESCRIPTOR_REVISION); 57*c2c66affSColin Finck RtlSetDaclSecurityDescriptor(SePublicDefaultUnrestrictedSd, 58*c2c66affSColin Finck TRUE, 59*c2c66affSColin Finck SePublicDefaultUnrestrictedDacl, 60*c2c66affSColin Finck FALSE); 61*c2c66affSColin Finck 62*c2c66affSColin Finck /* Create PublicOpenSd */ 63*c2c66affSColin Finck SePublicOpenSd = ExAllocatePoolWithTag(PagedPool, 64*c2c66affSColin Finck sizeof(SECURITY_DESCRIPTOR), TAG_SD); 65*c2c66affSColin Finck if (SePublicOpenSd == NULL) 66*c2c66affSColin Finck return FALSE; 67*c2c66affSColin Finck 68*c2c66affSColin Finck RtlCreateSecurityDescriptor(SePublicOpenSd, 69*c2c66affSColin Finck SECURITY_DESCRIPTOR_REVISION); 70*c2c66affSColin Finck RtlSetDaclSecurityDescriptor(SePublicOpenSd, 71*c2c66affSColin Finck TRUE, 72*c2c66affSColin Finck SePublicOpenDacl, 73*c2c66affSColin Finck FALSE); 74*c2c66affSColin Finck 75*c2c66affSColin Finck /* Create PublicOpenUnrestrictedSd */ 76*c2c66affSColin Finck SePublicOpenUnrestrictedSd = ExAllocatePoolWithTag(PagedPool, 77*c2c66affSColin Finck sizeof(SECURITY_DESCRIPTOR), TAG_SD); 78*c2c66affSColin Finck if (SePublicOpenUnrestrictedSd == NULL) 79*c2c66affSColin Finck return FALSE; 80*c2c66affSColin Finck 81*c2c66affSColin Finck RtlCreateSecurityDescriptor(SePublicOpenUnrestrictedSd, 82*c2c66affSColin Finck SECURITY_DESCRIPTOR_REVISION); 83*c2c66affSColin Finck RtlSetDaclSecurityDescriptor(SePublicOpenUnrestrictedSd, 84*c2c66affSColin Finck TRUE, 85*c2c66affSColin Finck SePublicOpenUnrestrictedDacl, 86*c2c66affSColin Finck FALSE); 87*c2c66affSColin Finck 88*c2c66affSColin Finck /* Create SystemDefaultSd */ 89*c2c66affSColin Finck SeSystemDefaultSd = ExAllocatePoolWithTag(PagedPool, 90*c2c66affSColin Finck sizeof(SECURITY_DESCRIPTOR), TAG_SD); 91*c2c66affSColin Finck if (SeSystemDefaultSd == NULL) 92*c2c66affSColin Finck return FALSE; 93*c2c66affSColin Finck 94*c2c66affSColin Finck RtlCreateSecurityDescriptor(SeSystemDefaultSd, 95*c2c66affSColin Finck SECURITY_DESCRIPTOR_REVISION); 96*c2c66affSColin Finck RtlSetDaclSecurityDescriptor(SeSystemDefaultSd, 97*c2c66affSColin Finck TRUE, 98*c2c66affSColin Finck SeSystemDefaultDacl, 99*c2c66affSColin Finck FALSE); 100*c2c66affSColin Finck 101*c2c66affSColin Finck /* Create UnrestrictedSd */ 102*c2c66affSColin Finck SeUnrestrictedSd = ExAllocatePoolWithTag(PagedPool, 103*c2c66affSColin Finck sizeof(SECURITY_DESCRIPTOR), TAG_SD); 104*c2c66affSColin Finck if (SeUnrestrictedSd == NULL) 105*c2c66affSColin Finck return FALSE; 106*c2c66affSColin Finck 107*c2c66affSColin Finck RtlCreateSecurityDescriptor(SeUnrestrictedSd, 108*c2c66affSColin Finck SECURITY_DESCRIPTOR_REVISION); 109*c2c66affSColin Finck RtlSetDaclSecurityDescriptor(SeUnrestrictedSd, 110*c2c66affSColin Finck TRUE, 111*c2c66affSColin Finck SeUnrestrictedDacl, 112*c2c66affSColin Finck FALSE); 113*c2c66affSColin Finck 114*c2c66affSColin Finck return TRUE; 115*c2c66affSColin Finck } 116*c2c66affSColin Finck 117*c2c66affSColin Finck NTSTATUS 118*c2c66affSColin Finck NTAPI 119*c2c66affSColin Finck SeSetWorldSecurityDescriptor(SECURITY_INFORMATION SecurityInformation, 120*c2c66affSColin Finck PISECURITY_DESCRIPTOR SecurityDescriptor, 121*c2c66affSColin Finck PULONG BufferLength) 122*c2c66affSColin Finck { 123*c2c66affSColin Finck ULONG Current; 124*c2c66affSColin Finck ULONG SidSize; 125*c2c66affSColin Finck ULONG SdSize; 126*c2c66affSColin Finck NTSTATUS Status; 127*c2c66affSColin Finck PISECURITY_DESCRIPTOR_RELATIVE SdRel = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor; 128*c2c66affSColin Finck 129*c2c66affSColin Finck DPRINT("SeSetWorldSecurityDescriptor() called\n"); 130*c2c66affSColin Finck 131*c2c66affSColin Finck if (SecurityInformation == 0) 132*c2c66affSColin Finck { 133*c2c66affSColin Finck return STATUS_ACCESS_DENIED; 134*c2c66affSColin Finck } 135*c2c66affSColin Finck 136*c2c66affSColin Finck /* calculate the minimum size of the buffer */ 137*c2c66affSColin Finck SidSize = RtlLengthSid(SeWorldSid); 138*c2c66affSColin Finck SdSize = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 139*c2c66affSColin Finck if (SecurityInformation & OWNER_SECURITY_INFORMATION) 140*c2c66affSColin Finck SdSize += SidSize; 141*c2c66affSColin Finck if (SecurityInformation & GROUP_SECURITY_INFORMATION) 142*c2c66affSColin Finck SdSize += SidSize; 143*c2c66affSColin Finck if (SecurityInformation & DACL_SECURITY_INFORMATION) 144*c2c66affSColin Finck { 145*c2c66affSColin Finck SdSize += sizeof(ACL) + sizeof(ACE) + SidSize; 146*c2c66affSColin Finck } 147*c2c66affSColin Finck 148*c2c66affSColin Finck if (*BufferLength < SdSize) 149*c2c66affSColin Finck { 150*c2c66affSColin Finck *BufferLength = SdSize; 151*c2c66affSColin Finck return STATUS_BUFFER_TOO_SMALL; 152*c2c66affSColin Finck } 153*c2c66affSColin Finck 154*c2c66affSColin Finck *BufferLength = SdSize; 155*c2c66affSColin Finck 156*c2c66affSColin Finck Status = RtlCreateSecurityDescriptorRelative(SdRel, 157*c2c66affSColin Finck SECURITY_DESCRIPTOR_REVISION); 158*c2c66affSColin Finck if (!NT_SUCCESS(Status)) 159*c2c66affSColin Finck { 160*c2c66affSColin Finck return Status; 161*c2c66affSColin Finck } 162*c2c66affSColin Finck 163*c2c66affSColin Finck Current = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 164*c2c66affSColin Finck 165*c2c66affSColin Finck if (SecurityInformation & OWNER_SECURITY_INFORMATION) 166*c2c66affSColin Finck { 167*c2c66affSColin Finck RtlCopyMemory((PUCHAR)SdRel + Current, SeWorldSid, SidSize); 168*c2c66affSColin Finck SdRel->Owner = Current; 169*c2c66affSColin Finck Current += SidSize; 170*c2c66affSColin Finck } 171*c2c66affSColin Finck 172*c2c66affSColin Finck if (SecurityInformation & GROUP_SECURITY_INFORMATION) 173*c2c66affSColin Finck { 174*c2c66affSColin Finck RtlCopyMemory((PUCHAR)SdRel + Current, SeWorldSid, SidSize); 175*c2c66affSColin Finck SdRel->Group = Current; 176*c2c66affSColin Finck Current += SidSize; 177*c2c66affSColin Finck } 178*c2c66affSColin Finck 179*c2c66affSColin Finck if (SecurityInformation & DACL_SECURITY_INFORMATION) 180*c2c66affSColin Finck { 181*c2c66affSColin Finck PACL Dacl = (PACL)((PUCHAR)SdRel + Current); 182*c2c66affSColin Finck SdRel->Control |= SE_DACL_PRESENT; 183*c2c66affSColin Finck 184*c2c66affSColin Finck Status = RtlCreateAcl(Dacl, 185*c2c66affSColin Finck sizeof(ACL) + sizeof(ACE) + SidSize, 186*c2c66affSColin Finck ACL_REVISION); 187*c2c66affSColin Finck if (!NT_SUCCESS(Status)) 188*c2c66affSColin Finck return Status; 189*c2c66affSColin Finck 190*c2c66affSColin Finck Status = RtlAddAccessAllowedAce(Dacl, 191*c2c66affSColin Finck ACL_REVISION, 192*c2c66affSColin Finck GENERIC_ALL, 193*c2c66affSColin Finck SeWorldSid); 194*c2c66affSColin Finck if (!NT_SUCCESS(Status)) 195*c2c66affSColin Finck return Status; 196*c2c66affSColin Finck 197*c2c66affSColin Finck SdRel->Dacl = Current; 198*c2c66affSColin Finck } 199*c2c66affSColin Finck 200*c2c66affSColin Finck if (SecurityInformation & SACL_SECURITY_INFORMATION) 201*c2c66affSColin Finck { 202*c2c66affSColin Finck /* FIXME - SdRel->Control |= SE_SACL_PRESENT; */ 203*c2c66affSColin Finck } 204*c2c66affSColin Finck 205*c2c66affSColin Finck return STATUS_SUCCESS; 206*c2c66affSColin Finck } 207*c2c66affSColin Finck 208*c2c66affSColin Finck 209*c2c66affSColin Finck NTSTATUS 210*c2c66affSColin Finck NTAPI 211*c2c66affSColin Finck SepCaptureSecurityQualityOfService(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, 212*c2c66affSColin Finck IN KPROCESSOR_MODE AccessMode, 213*c2c66affSColin Finck IN POOL_TYPE PoolType, 214*c2c66affSColin Finck IN BOOLEAN CaptureIfKernel, 215*c2c66affSColin Finck OUT PSECURITY_QUALITY_OF_SERVICE *CapturedSecurityQualityOfService, 216*c2c66affSColin Finck OUT PBOOLEAN Present) 217*c2c66affSColin Finck { 218*c2c66affSColin Finck PSECURITY_QUALITY_OF_SERVICE CapturedQos; 219*c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS; 220*c2c66affSColin Finck 221*c2c66affSColin Finck PAGED_CODE(); 222*c2c66affSColin Finck 223*c2c66affSColin Finck ASSERT(CapturedSecurityQualityOfService); 224*c2c66affSColin Finck ASSERT(Present); 225*c2c66affSColin Finck 226*c2c66affSColin Finck if (ObjectAttributes != NULL) 227*c2c66affSColin Finck { 228*c2c66affSColin Finck if (AccessMode != KernelMode) 229*c2c66affSColin Finck { 230*c2c66affSColin Finck SECURITY_QUALITY_OF_SERVICE SafeQos; 231*c2c66affSColin Finck 232*c2c66affSColin Finck _SEH2_TRY 233*c2c66affSColin Finck { 234*c2c66affSColin Finck ProbeForRead(ObjectAttributes, 235*c2c66affSColin Finck sizeof(OBJECT_ATTRIBUTES), 236*c2c66affSColin Finck sizeof(ULONG)); 237*c2c66affSColin Finck if (ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES)) 238*c2c66affSColin Finck { 239*c2c66affSColin Finck if (ObjectAttributes->SecurityQualityOfService != NULL) 240*c2c66affSColin Finck { 241*c2c66affSColin Finck ProbeForRead(ObjectAttributes->SecurityQualityOfService, 242*c2c66affSColin Finck sizeof(SECURITY_QUALITY_OF_SERVICE), 243*c2c66affSColin Finck sizeof(ULONG)); 244*c2c66affSColin Finck 245*c2c66affSColin Finck if (((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length == 246*c2c66affSColin Finck sizeof(SECURITY_QUALITY_OF_SERVICE)) 247*c2c66affSColin Finck { 248*c2c66affSColin Finck /* 249*c2c66affSColin Finck * Don't allocate memory here because ExAllocate should bugcheck 250*c2c66affSColin Finck * the system if it's buggy, SEH would catch that! So make a local 251*c2c66affSColin Finck * copy of the qos structure. 252*c2c66affSColin Finck */ 253*c2c66affSColin Finck RtlCopyMemory(&SafeQos, 254*c2c66affSColin Finck ObjectAttributes->SecurityQualityOfService, 255*c2c66affSColin Finck sizeof(SECURITY_QUALITY_OF_SERVICE)); 256*c2c66affSColin Finck *Present = TRUE; 257*c2c66affSColin Finck } 258*c2c66affSColin Finck else 259*c2c66affSColin Finck { 260*c2c66affSColin Finck Status = STATUS_INVALID_PARAMETER; 261*c2c66affSColin Finck } 262*c2c66affSColin Finck } 263*c2c66affSColin Finck else 264*c2c66affSColin Finck { 265*c2c66affSColin Finck *CapturedSecurityQualityOfService = NULL; 266*c2c66affSColin Finck *Present = FALSE; 267*c2c66affSColin Finck } 268*c2c66affSColin Finck } 269*c2c66affSColin Finck else 270*c2c66affSColin Finck { 271*c2c66affSColin Finck Status = STATUS_INVALID_PARAMETER; 272*c2c66affSColin Finck } 273*c2c66affSColin Finck } 274*c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 275*c2c66affSColin Finck { 276*c2c66affSColin Finck Status = _SEH2_GetExceptionCode(); 277*c2c66affSColin Finck } 278*c2c66affSColin Finck _SEH2_END; 279*c2c66affSColin Finck 280*c2c66affSColin Finck if (NT_SUCCESS(Status)) 281*c2c66affSColin Finck { 282*c2c66affSColin Finck if (*Present) 283*c2c66affSColin Finck { 284*c2c66affSColin Finck CapturedQos = ExAllocatePoolWithTag(PoolType, 285*c2c66affSColin Finck sizeof(SECURITY_QUALITY_OF_SERVICE), 286*c2c66affSColin Finck TAG_QOS); 287*c2c66affSColin Finck if (CapturedQos != NULL) 288*c2c66affSColin Finck { 289*c2c66affSColin Finck RtlCopyMemory(CapturedQos, 290*c2c66affSColin Finck &SafeQos, 291*c2c66affSColin Finck sizeof(SECURITY_QUALITY_OF_SERVICE)); 292*c2c66affSColin Finck *CapturedSecurityQualityOfService = CapturedQos; 293*c2c66affSColin Finck } 294*c2c66affSColin Finck else 295*c2c66affSColin Finck { 296*c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES; 297*c2c66affSColin Finck } 298*c2c66affSColin Finck } 299*c2c66affSColin Finck else 300*c2c66affSColin Finck { 301*c2c66affSColin Finck *CapturedSecurityQualityOfService = NULL; 302*c2c66affSColin Finck } 303*c2c66affSColin Finck } 304*c2c66affSColin Finck } 305*c2c66affSColin Finck else 306*c2c66affSColin Finck { 307*c2c66affSColin Finck if (ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES)) 308*c2c66affSColin Finck { 309*c2c66affSColin Finck if (CaptureIfKernel) 310*c2c66affSColin Finck { 311*c2c66affSColin Finck if (ObjectAttributes->SecurityQualityOfService != NULL) 312*c2c66affSColin Finck { 313*c2c66affSColin Finck if (((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length == 314*c2c66affSColin Finck sizeof(SECURITY_QUALITY_OF_SERVICE)) 315*c2c66affSColin Finck { 316*c2c66affSColin Finck CapturedQos = ExAllocatePoolWithTag(PoolType, 317*c2c66affSColin Finck sizeof(SECURITY_QUALITY_OF_SERVICE), 318*c2c66affSColin Finck TAG_QOS); 319*c2c66affSColin Finck if (CapturedQos != NULL) 320*c2c66affSColin Finck { 321*c2c66affSColin Finck RtlCopyMemory(CapturedQos, 322*c2c66affSColin Finck ObjectAttributes->SecurityQualityOfService, 323*c2c66affSColin Finck sizeof(SECURITY_QUALITY_OF_SERVICE)); 324*c2c66affSColin Finck *CapturedSecurityQualityOfService = CapturedQos; 325*c2c66affSColin Finck *Present = TRUE; 326*c2c66affSColin Finck } 327*c2c66affSColin Finck else 328*c2c66affSColin Finck { 329*c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES; 330*c2c66affSColin Finck } 331*c2c66affSColin Finck } 332*c2c66affSColin Finck else 333*c2c66affSColin Finck { 334*c2c66affSColin Finck Status = STATUS_INVALID_PARAMETER; 335*c2c66affSColin Finck } 336*c2c66affSColin Finck } 337*c2c66affSColin Finck else 338*c2c66affSColin Finck { 339*c2c66affSColin Finck *CapturedSecurityQualityOfService = NULL; 340*c2c66affSColin Finck *Present = FALSE; 341*c2c66affSColin Finck } 342*c2c66affSColin Finck } 343*c2c66affSColin Finck else 344*c2c66affSColin Finck { 345*c2c66affSColin Finck *CapturedSecurityQualityOfService = (PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService; 346*c2c66affSColin Finck *Present = (ObjectAttributes->SecurityQualityOfService != NULL); 347*c2c66affSColin Finck } 348*c2c66affSColin Finck } 349*c2c66affSColin Finck else 350*c2c66affSColin Finck { 351*c2c66affSColin Finck Status = STATUS_INVALID_PARAMETER; 352*c2c66affSColin Finck } 353*c2c66affSColin Finck } 354*c2c66affSColin Finck } 355*c2c66affSColin Finck else 356*c2c66affSColin Finck { 357*c2c66affSColin Finck *CapturedSecurityQualityOfService = NULL; 358*c2c66affSColin Finck *Present = FALSE; 359*c2c66affSColin Finck } 360*c2c66affSColin Finck 361*c2c66affSColin Finck return Status; 362*c2c66affSColin Finck } 363*c2c66affSColin Finck 364*c2c66affSColin Finck 365*c2c66affSColin Finck VOID 366*c2c66affSColin Finck NTAPI 367*c2c66affSColin Finck SepReleaseSecurityQualityOfService(IN PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService OPTIONAL, 368*c2c66affSColin Finck IN KPROCESSOR_MODE AccessMode, 369*c2c66affSColin Finck IN BOOLEAN CaptureIfKernel) 370*c2c66affSColin Finck { 371*c2c66affSColin Finck PAGED_CODE(); 372*c2c66affSColin Finck 373*c2c66affSColin Finck if (CapturedSecurityQualityOfService != NULL && 374*c2c66affSColin Finck (AccessMode != KernelMode || CaptureIfKernel)) 375*c2c66affSColin Finck { 376*c2c66affSColin Finck ExFreePoolWithTag(CapturedSecurityQualityOfService, TAG_QOS); 377*c2c66affSColin Finck } 378*c2c66affSColin Finck } 379*c2c66affSColin Finck 380*c2c66affSColin Finck /* PUBLIC FUNCTIONS ***********************************************************/ 381*c2c66affSColin Finck 382*c2c66affSColin Finck static 383*c2c66affSColin Finck ULONG 384*c2c66affSColin Finck DetermineSIDSize( 385*c2c66affSColin Finck PISID Sid, 386*c2c66affSColin Finck PULONG OutSAC, 387*c2c66affSColin Finck KPROCESSOR_MODE ProcessorMode) 388*c2c66affSColin Finck { 389*c2c66affSColin Finck ULONG Size; 390*c2c66affSColin Finck 391*c2c66affSColin Finck if (!Sid) 392*c2c66affSColin Finck { 393*c2c66affSColin Finck *OutSAC = 0; 394*c2c66affSColin Finck return 0; 395*c2c66affSColin Finck } 396*c2c66affSColin Finck 397*c2c66affSColin Finck if (ProcessorMode != KernelMode) 398*c2c66affSColin Finck { 399*c2c66affSColin Finck /* Securely access the buffers! */ 400*c2c66affSColin Finck *OutSAC = ProbeForReadUchar(&Sid->SubAuthorityCount); 401*c2c66affSColin Finck Size = RtlLengthRequiredSid(*OutSAC); 402*c2c66affSColin Finck ProbeForRead(Sid, Size, sizeof(ULONG)); 403*c2c66affSColin Finck } 404*c2c66affSColin Finck else 405*c2c66affSColin Finck { 406*c2c66affSColin Finck *OutSAC = Sid->SubAuthorityCount; 407*c2c66affSColin Finck Size = RtlLengthRequiredSid(*OutSAC); 408*c2c66affSColin Finck } 409*c2c66affSColin Finck 410*c2c66affSColin Finck return Size; 411*c2c66affSColin Finck } 412*c2c66affSColin Finck 413*c2c66affSColin Finck static 414*c2c66affSColin Finck ULONG 415*c2c66affSColin Finck DetermineACLSize( 416*c2c66affSColin Finck PACL Acl, 417*c2c66affSColin Finck KPROCESSOR_MODE ProcessorMode) 418*c2c66affSColin Finck { 419*c2c66affSColin Finck ULONG Size; 420*c2c66affSColin Finck 421*c2c66affSColin Finck if (!Acl) return 0; 422*c2c66affSColin Finck 423*c2c66affSColin Finck if (ProcessorMode == KernelMode) return Acl->AclSize; 424*c2c66affSColin Finck 425*c2c66affSColin Finck /* Probe the buffers! */ 426*c2c66affSColin Finck Size = ProbeForReadUshort(&Acl->AclSize); 427*c2c66affSColin Finck ProbeForRead(Acl, Size, sizeof(ULONG)); 428*c2c66affSColin Finck 429*c2c66affSColin Finck return Size; 430*c2c66affSColin Finck } 431*c2c66affSColin Finck 432*c2c66affSColin Finck NTSTATUS 433*c2c66affSColin Finck NTAPI 434*c2c66affSColin Finck SeCaptureSecurityDescriptor( 435*c2c66affSColin Finck IN PSECURITY_DESCRIPTOR _OriginalSecurityDescriptor, 436*c2c66affSColin Finck IN KPROCESSOR_MODE CurrentMode, 437*c2c66affSColin Finck IN POOL_TYPE PoolType, 438*c2c66affSColin Finck IN BOOLEAN CaptureIfKernel, 439*c2c66affSColin Finck OUT PSECURITY_DESCRIPTOR *CapturedSecurityDescriptor) 440*c2c66affSColin Finck { 441*c2c66affSColin Finck PISECURITY_DESCRIPTOR OriginalDescriptor = _OriginalSecurityDescriptor; 442*c2c66affSColin Finck SECURITY_DESCRIPTOR DescriptorCopy; 443*c2c66affSColin Finck PISECURITY_DESCRIPTOR_RELATIVE NewDescriptor; 444*c2c66affSColin Finck ULONG OwnerSAC = 0, GroupSAC = 0; 445*c2c66affSColin Finck ULONG OwnerSize = 0, GroupSize = 0; 446*c2c66affSColin Finck ULONG SaclSize = 0, DaclSize = 0; 447*c2c66affSColin Finck ULONG DescriptorSize = 0; 448*c2c66affSColin Finck ULONG Offset; 449*c2c66affSColin Finck 450*c2c66affSColin Finck if (!OriginalDescriptor) 451*c2c66affSColin Finck { 452*c2c66affSColin Finck /* Nothing to do... */ 453*c2c66affSColin Finck *CapturedSecurityDescriptor = NULL; 454*c2c66affSColin Finck return STATUS_SUCCESS; 455*c2c66affSColin Finck } 456*c2c66affSColin Finck 457*c2c66affSColin Finck /* Quick path */ 458*c2c66affSColin Finck if (CurrentMode == KernelMode && !CaptureIfKernel) 459*c2c66affSColin Finck { 460*c2c66affSColin Finck /* Check descriptor version */ 461*c2c66affSColin Finck if (OriginalDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1) 462*c2c66affSColin Finck { 463*c2c66affSColin Finck return STATUS_UNKNOWN_REVISION; 464*c2c66affSColin Finck } 465*c2c66affSColin Finck 466*c2c66affSColin Finck *CapturedSecurityDescriptor = _OriginalSecurityDescriptor; 467*c2c66affSColin Finck return STATUS_SUCCESS; 468*c2c66affSColin Finck } 469*c2c66affSColin Finck 470*c2c66affSColin Finck _SEH2_TRY 471*c2c66affSColin Finck { 472*c2c66affSColin Finck if (CurrentMode != KernelMode) 473*c2c66affSColin Finck { 474*c2c66affSColin Finck ProbeForRead(OriginalDescriptor, 475*c2c66affSColin Finck sizeof(SECURITY_DESCRIPTOR_RELATIVE), 476*c2c66affSColin Finck sizeof(ULONG)); 477*c2c66affSColin Finck } 478*c2c66affSColin Finck 479*c2c66affSColin Finck /* Check the descriptor version */ 480*c2c66affSColin Finck if (OriginalDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1) 481*c2c66affSColin Finck { 482*c2c66affSColin Finck _SEH2_YIELD(return STATUS_UNKNOWN_REVISION); 483*c2c66affSColin Finck } 484*c2c66affSColin Finck 485*c2c66affSColin Finck if (CurrentMode != KernelMode) 486*c2c66affSColin Finck { 487*c2c66affSColin Finck /* Get the size of the descriptor */ 488*c2c66affSColin Finck DescriptorSize = (OriginalDescriptor->Control & SE_SELF_RELATIVE) ? 489*c2c66affSColin Finck sizeof(SECURITY_DESCRIPTOR_RELATIVE) : sizeof(SECURITY_DESCRIPTOR); 490*c2c66affSColin Finck 491*c2c66affSColin Finck /* Probe the entire security descriptor structure. The SIDs 492*c2c66affSColin Finck * and ACLs will be probed and copied later though */ 493*c2c66affSColin Finck ProbeForRead(OriginalDescriptor, DescriptorSize, sizeof(ULONG)); 494*c2c66affSColin Finck } 495*c2c66affSColin Finck 496*c2c66affSColin Finck /* Now capture all fields and convert to an absolute descriptor */ 497*c2c66affSColin Finck DescriptorCopy.Revision = OriginalDescriptor->Revision; 498*c2c66affSColin Finck DescriptorCopy.Sbz1 = OriginalDescriptor->Sbz1; 499*c2c66affSColin Finck DescriptorCopy.Control = OriginalDescriptor->Control & ~SE_SELF_RELATIVE; 500*c2c66affSColin Finck DescriptorCopy.Owner = SepGetOwnerFromDescriptor(OriginalDescriptor); 501*c2c66affSColin Finck DescriptorCopy.Group = SepGetGroupFromDescriptor(OriginalDescriptor); 502*c2c66affSColin Finck DescriptorCopy.Sacl = SepGetSaclFromDescriptor(OriginalDescriptor); 503*c2c66affSColin Finck DescriptorCopy.Dacl = SepGetDaclFromDescriptor(OriginalDescriptor); 504*c2c66affSColin Finck DescriptorSize = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 505*c2c66affSColin Finck 506*c2c66affSColin Finck /* Determine owner and group sizes */ 507*c2c66affSColin Finck OwnerSize = DetermineSIDSize(DescriptorCopy.Owner, &OwnerSAC, CurrentMode); 508*c2c66affSColin Finck DescriptorSize += ROUND_UP(OwnerSize, sizeof(ULONG)); 509*c2c66affSColin Finck GroupSize = DetermineSIDSize(DescriptorCopy.Group, &GroupSAC, CurrentMode); 510*c2c66affSColin Finck DescriptorSize += ROUND_UP(GroupSize, sizeof(ULONG)); 511*c2c66affSColin Finck 512*c2c66affSColin Finck /* Determine the size of the ACLs */ 513*c2c66affSColin Finck if (DescriptorCopy.Control & SE_SACL_PRESENT) 514*c2c66affSColin Finck { 515*c2c66affSColin Finck /* Get the size and probe if user mode */ 516*c2c66affSColin Finck SaclSize = DetermineACLSize(DescriptorCopy.Sacl, CurrentMode); 517*c2c66affSColin Finck DescriptorSize += ROUND_UP(SaclSize, sizeof(ULONG)); 518*c2c66affSColin Finck } 519*c2c66affSColin Finck 520*c2c66affSColin Finck if (DescriptorCopy.Control & SE_DACL_PRESENT) 521*c2c66affSColin Finck { 522*c2c66affSColin Finck /* Get the size and probe if user mode */ 523*c2c66affSColin Finck DaclSize = DetermineACLSize(DescriptorCopy.Dacl, CurrentMode); 524*c2c66affSColin Finck DescriptorSize += ROUND_UP(DaclSize, sizeof(ULONG)); 525*c2c66affSColin Finck } 526*c2c66affSColin Finck } 527*c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 528*c2c66affSColin Finck { 529*c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode()); 530*c2c66affSColin Finck } 531*c2c66affSColin Finck _SEH2_END; 532*c2c66affSColin Finck 533*c2c66affSColin Finck /* 534*c2c66affSColin Finck * Allocate enough memory to store a complete copy of a self-relative 535*c2c66affSColin Finck * security descriptor 536*c2c66affSColin Finck */ 537*c2c66affSColin Finck NewDescriptor = ExAllocatePoolWithTag(PoolType, 538*c2c66affSColin Finck DescriptorSize, 539*c2c66affSColin Finck TAG_SD); 540*c2c66affSColin Finck if (!NewDescriptor) return STATUS_INSUFFICIENT_RESOURCES; 541*c2c66affSColin Finck 542*c2c66affSColin Finck RtlZeroMemory(NewDescriptor, DescriptorSize); 543*c2c66affSColin Finck NewDescriptor->Revision = DescriptorCopy.Revision; 544*c2c66affSColin Finck NewDescriptor->Sbz1 = DescriptorCopy.Sbz1; 545*c2c66affSColin Finck NewDescriptor->Control = DescriptorCopy.Control | SE_SELF_RELATIVE; 546*c2c66affSColin Finck 547*c2c66affSColin Finck _SEH2_TRY 548*c2c66affSColin Finck { 549*c2c66affSColin Finck /* 550*c2c66affSColin Finck * Setup the offsets and copy the SIDs and ACLs to the new 551*c2c66affSColin Finck * self-relative security descriptor. Probing the pointers is not 552*c2c66affSColin Finck * neccessary anymore as we did that when collecting the sizes! 553*c2c66affSColin Finck * Make sure to validate the SIDs and ACLs *again* as they could have 554*c2c66affSColin Finck * been modified in the meanwhile! 555*c2c66affSColin Finck */ 556*c2c66affSColin Finck Offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 557*c2c66affSColin Finck 558*c2c66affSColin Finck if (DescriptorCopy.Owner) 559*c2c66affSColin Finck { 560*c2c66affSColin Finck if (!RtlValidSid(DescriptorCopy.Owner)) RtlRaiseStatus(STATUS_INVALID_SID); 561*c2c66affSColin Finck NewDescriptor->Owner = Offset; 562*c2c66affSColin Finck RtlCopyMemory((PUCHAR)NewDescriptor + Offset, 563*c2c66affSColin Finck DescriptorCopy.Owner, 564*c2c66affSColin Finck OwnerSize); 565*c2c66affSColin Finck Offset += ROUND_UP(OwnerSize, sizeof(ULONG)); 566*c2c66affSColin Finck } 567*c2c66affSColin Finck 568*c2c66affSColin Finck if (DescriptorCopy.Group) 569*c2c66affSColin Finck { 570*c2c66affSColin Finck if (!RtlValidSid(DescriptorCopy.Group)) RtlRaiseStatus(STATUS_INVALID_SID); 571*c2c66affSColin Finck NewDescriptor->Group = Offset; 572*c2c66affSColin Finck RtlCopyMemory((PUCHAR)NewDescriptor + Offset, 573*c2c66affSColin Finck DescriptorCopy.Group, 574*c2c66affSColin Finck GroupSize); 575*c2c66affSColin Finck Offset += ROUND_UP(GroupSize, sizeof(ULONG)); 576*c2c66affSColin Finck } 577*c2c66affSColin Finck 578*c2c66affSColin Finck if (DescriptorCopy.Sacl) 579*c2c66affSColin Finck { 580*c2c66affSColin Finck if (!RtlValidAcl(DescriptorCopy.Sacl)) RtlRaiseStatus(STATUS_INVALID_ACL); 581*c2c66affSColin Finck NewDescriptor->Sacl = Offset; 582*c2c66affSColin Finck RtlCopyMemory((PUCHAR)NewDescriptor + Offset, 583*c2c66affSColin Finck DescriptorCopy.Sacl, 584*c2c66affSColin Finck SaclSize); 585*c2c66affSColin Finck Offset += ROUND_UP(SaclSize, sizeof(ULONG)); 586*c2c66affSColin Finck } 587*c2c66affSColin Finck 588*c2c66affSColin Finck if (DescriptorCopy.Dacl) 589*c2c66affSColin Finck { 590*c2c66affSColin Finck if (!RtlValidAcl(DescriptorCopy.Dacl)) RtlRaiseStatus(STATUS_INVALID_ACL); 591*c2c66affSColin Finck NewDescriptor->Dacl = Offset; 592*c2c66affSColin Finck RtlCopyMemory((PUCHAR)NewDescriptor + Offset, 593*c2c66affSColin Finck DescriptorCopy.Dacl, 594*c2c66affSColin Finck DaclSize); 595*c2c66affSColin Finck Offset += ROUND_UP(DaclSize, sizeof(ULONG)); 596*c2c66affSColin Finck } 597*c2c66affSColin Finck 598*c2c66affSColin Finck /* Make sure the size was correct */ 599*c2c66affSColin Finck ASSERT(Offset == DescriptorSize); 600*c2c66affSColin Finck } 601*c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 602*c2c66affSColin Finck { 603*c2c66affSColin Finck /* We failed to copy the data to the new descriptor */ 604*c2c66affSColin Finck ExFreePoolWithTag(NewDescriptor, TAG_SD); 605*c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode()); 606*c2c66affSColin Finck } 607*c2c66affSColin Finck _SEH2_END; 608*c2c66affSColin Finck 609*c2c66affSColin Finck /* 610*c2c66affSColin Finck * We're finally done! 611*c2c66affSColin Finck * Copy the pointer to the captured descriptor to to the caller. 612*c2c66affSColin Finck */ 613*c2c66affSColin Finck *CapturedSecurityDescriptor = NewDescriptor; 614*c2c66affSColin Finck return STATUS_SUCCESS; 615*c2c66affSColin Finck } 616*c2c66affSColin Finck 617*c2c66affSColin Finck /* 618*c2c66affSColin Finck * @implemented 619*c2c66affSColin Finck */ 620*c2c66affSColin Finck _IRQL_requires_max_(PASSIVE_LEVEL) 621*c2c66affSColin Finck NTSTATUS 622*c2c66affSColin Finck NTAPI 623*c2c66affSColin Finck SeQuerySecurityDescriptorInfo( 624*c2c66affSColin Finck _In_ PSECURITY_INFORMATION SecurityInformation, 625*c2c66affSColin Finck _Out_writes_bytes_(*Length) PSECURITY_DESCRIPTOR SecurityDescriptor, 626*c2c66affSColin Finck _Inout_ PULONG Length, 627*c2c66affSColin Finck _Inout_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor) 628*c2c66affSColin Finck { 629*c2c66affSColin Finck PISECURITY_DESCRIPTOR ObjectSd; 630*c2c66affSColin Finck PISECURITY_DESCRIPTOR_RELATIVE RelSD; 631*c2c66affSColin Finck PSID Owner = NULL; 632*c2c66affSColin Finck PSID Group = NULL; 633*c2c66affSColin Finck PACL Dacl = NULL; 634*c2c66affSColin Finck PACL Sacl = NULL; 635*c2c66affSColin Finck ULONG OwnerLength = 0; 636*c2c66affSColin Finck ULONG GroupLength = 0; 637*c2c66affSColin Finck ULONG DaclLength = 0; 638*c2c66affSColin Finck ULONG SaclLength = 0; 639*c2c66affSColin Finck SECURITY_DESCRIPTOR_CONTROL Control = 0; 640*c2c66affSColin Finck ULONG_PTR Current; 641*c2c66affSColin Finck ULONG SdLength; 642*c2c66affSColin Finck 643*c2c66affSColin Finck PAGED_CODE(); 644*c2c66affSColin Finck 645*c2c66affSColin Finck RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor; 646*c2c66affSColin Finck 647*c2c66affSColin Finck if (*ObjectsSecurityDescriptor == NULL) 648*c2c66affSColin Finck { 649*c2c66affSColin Finck if (*Length < sizeof(SECURITY_DESCRIPTOR_RELATIVE)) 650*c2c66affSColin Finck { 651*c2c66affSColin Finck *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 652*c2c66affSColin Finck return STATUS_BUFFER_TOO_SMALL; 653*c2c66affSColin Finck } 654*c2c66affSColin Finck 655*c2c66affSColin Finck *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 656*c2c66affSColin Finck RtlCreateSecurityDescriptorRelative(RelSD, 657*c2c66affSColin Finck SECURITY_DESCRIPTOR_REVISION); 658*c2c66affSColin Finck return STATUS_SUCCESS; 659*c2c66affSColin Finck } 660*c2c66affSColin Finck 661*c2c66affSColin Finck ObjectSd = *ObjectsSecurityDescriptor; 662*c2c66affSColin Finck 663*c2c66affSColin Finck /* Calculate the required security descriptor length */ 664*c2c66affSColin Finck Control = SE_SELF_RELATIVE; 665*c2c66affSColin Finck if ((*SecurityInformation & OWNER_SECURITY_INFORMATION) && 666*c2c66affSColin Finck (ObjectSd->Owner != NULL)) 667*c2c66affSColin Finck { 668*c2c66affSColin Finck Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd); 669*c2c66affSColin Finck OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4); 670*c2c66affSColin Finck Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED); 671*c2c66affSColin Finck } 672*c2c66affSColin Finck 673*c2c66affSColin Finck if ((*SecurityInformation & GROUP_SECURITY_INFORMATION) && 674*c2c66affSColin Finck (ObjectSd->Group != NULL)) 675*c2c66affSColin Finck { 676*c2c66affSColin Finck Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd); 677*c2c66affSColin Finck GroupLength = ROUND_UP(RtlLengthSid(Group), 4); 678*c2c66affSColin Finck Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED); 679*c2c66affSColin Finck } 680*c2c66affSColin Finck 681*c2c66affSColin Finck if ((*SecurityInformation & DACL_SECURITY_INFORMATION) && 682*c2c66affSColin Finck (ObjectSd->Control & SE_DACL_PRESENT)) 683*c2c66affSColin Finck { 684*c2c66affSColin Finck if (ObjectSd->Dacl != NULL) 685*c2c66affSColin Finck { 686*c2c66affSColin Finck Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd); 687*c2c66affSColin Finck DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4); 688*c2c66affSColin Finck } 689*c2c66affSColin Finck 690*c2c66affSColin Finck Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT)); 691*c2c66affSColin Finck } 692*c2c66affSColin Finck 693*c2c66affSColin Finck if ((*SecurityInformation & SACL_SECURITY_INFORMATION) && 694*c2c66affSColin Finck (ObjectSd->Control & SE_SACL_PRESENT)) 695*c2c66affSColin Finck { 696*c2c66affSColin Finck if (ObjectSd->Sacl != NULL) 697*c2c66affSColin Finck { 698*c2c66affSColin Finck Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd); 699*c2c66affSColin Finck SaclLength = ROUND_UP(Sacl->AclSize, 4); 700*c2c66affSColin Finck } 701*c2c66affSColin Finck 702*c2c66affSColin Finck Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT)); 703*c2c66affSColin Finck } 704*c2c66affSColin Finck 705*c2c66affSColin Finck SdLength = OwnerLength + GroupLength + DaclLength + 706*c2c66affSColin Finck SaclLength + sizeof(SECURITY_DESCRIPTOR_RELATIVE); 707*c2c66affSColin Finck if (*Length < SdLength) 708*c2c66affSColin Finck { 709*c2c66affSColin Finck *Length = SdLength; 710*c2c66affSColin Finck return STATUS_BUFFER_TOO_SMALL; 711*c2c66affSColin Finck } 712*c2c66affSColin Finck 713*c2c66affSColin Finck /* Build the new security descrtiptor */ 714*c2c66affSColin Finck RtlCreateSecurityDescriptorRelative(RelSD, 715*c2c66affSColin Finck SECURITY_DESCRIPTOR_REVISION); 716*c2c66affSColin Finck RelSD->Control = Control; 717*c2c66affSColin Finck 718*c2c66affSColin Finck Current = (ULONG_PTR)(RelSD + 1); 719*c2c66affSColin Finck 720*c2c66affSColin Finck if (OwnerLength != 0) 721*c2c66affSColin Finck { 722*c2c66affSColin Finck RtlCopyMemory((PVOID)Current, 723*c2c66affSColin Finck Owner, 724*c2c66affSColin Finck OwnerLength); 725*c2c66affSColin Finck RelSD->Owner = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor); 726*c2c66affSColin Finck Current += OwnerLength; 727*c2c66affSColin Finck } 728*c2c66affSColin Finck 729*c2c66affSColin Finck if (GroupLength != 0) 730*c2c66affSColin Finck { 731*c2c66affSColin Finck RtlCopyMemory((PVOID)Current, 732*c2c66affSColin Finck Group, 733*c2c66affSColin Finck GroupLength); 734*c2c66affSColin Finck RelSD->Group = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor); 735*c2c66affSColin Finck Current += GroupLength; 736*c2c66affSColin Finck } 737*c2c66affSColin Finck 738*c2c66affSColin Finck if (DaclLength != 0) 739*c2c66affSColin Finck { 740*c2c66affSColin Finck RtlCopyMemory((PVOID)Current, 741*c2c66affSColin Finck Dacl, 742*c2c66affSColin Finck DaclLength); 743*c2c66affSColin Finck RelSD->Dacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor); 744*c2c66affSColin Finck Current += DaclLength; 745*c2c66affSColin Finck } 746*c2c66affSColin Finck 747*c2c66affSColin Finck if (SaclLength != 0) 748*c2c66affSColin Finck { 749*c2c66affSColin Finck RtlCopyMemory((PVOID)Current, 750*c2c66affSColin Finck Sacl, 751*c2c66affSColin Finck SaclLength); 752*c2c66affSColin Finck RelSD->Sacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor); 753*c2c66affSColin Finck Current += SaclLength; 754*c2c66affSColin Finck } 755*c2c66affSColin Finck 756*c2c66affSColin Finck *Length = SdLength; 757*c2c66affSColin Finck 758*c2c66affSColin Finck return STATUS_SUCCESS; 759*c2c66affSColin Finck } 760*c2c66affSColin Finck 761*c2c66affSColin Finck /* 762*c2c66affSColin Finck * @implemented 763*c2c66affSColin Finck */ 764*c2c66affSColin Finck NTSTATUS 765*c2c66affSColin Finck NTAPI 766*c2c66affSColin Finck SeReleaseSecurityDescriptor(IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor, 767*c2c66affSColin Finck IN KPROCESSOR_MODE CurrentMode, 768*c2c66affSColin Finck IN BOOLEAN CaptureIfKernelMode) 769*c2c66affSColin Finck { 770*c2c66affSColin Finck PAGED_CODE(); 771*c2c66affSColin Finck 772*c2c66affSColin Finck /* 773*c2c66affSColin Finck * WARNING! You need to call this function with the same value for CurrentMode 774*c2c66affSColin Finck * and CaptureIfKernelMode that you previously passed to 775*c2c66affSColin Finck * SeCaptureSecurityDescriptor() in order to avoid memory leaks! 776*c2c66affSColin Finck */ 777*c2c66affSColin Finck if (CapturedSecurityDescriptor != NULL && 778*c2c66affSColin Finck (CurrentMode != KernelMode || 779*c2c66affSColin Finck (CurrentMode == KernelMode && CaptureIfKernelMode))) 780*c2c66affSColin Finck { 781*c2c66affSColin Finck /* Only delete the descriptor when SeCaptureSecurityDescriptor() allocated one! */ 782*c2c66affSColin Finck ExFreePoolWithTag(CapturedSecurityDescriptor, TAG_SD); 783*c2c66affSColin Finck } 784*c2c66affSColin Finck 785*c2c66affSColin Finck return STATUS_SUCCESS; 786*c2c66affSColin Finck } 787*c2c66affSColin Finck 788*c2c66affSColin Finck /* 789*c2c66affSColin Finck * @implemented 790*c2c66affSColin Finck */ 791*c2c66affSColin Finck _IRQL_requires_max_(PASSIVE_LEVEL) 792*c2c66affSColin Finck NTSTATUS 793*c2c66affSColin Finck NTAPI 794*c2c66affSColin Finck SeSetSecurityDescriptorInfo( 795*c2c66affSColin Finck _In_opt_ PVOID Object, 796*c2c66affSColin Finck _In_ PSECURITY_INFORMATION SecurityInformation, 797*c2c66affSColin Finck _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, 798*c2c66affSColin Finck _Inout_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, 799*c2c66affSColin Finck _In_ POOL_TYPE PoolType, 800*c2c66affSColin Finck _In_ PGENERIC_MAPPING GenericMapping) 801*c2c66affSColin Finck { 802*c2c66affSColin Finck PAGED_CODE(); 803*c2c66affSColin Finck 804*c2c66affSColin Finck return SeSetSecurityDescriptorInfoEx(Object, 805*c2c66affSColin Finck SecurityInformation, 806*c2c66affSColin Finck SecurityDescriptor, 807*c2c66affSColin Finck ObjectsSecurityDescriptor, 808*c2c66affSColin Finck 0, 809*c2c66affSColin Finck PoolType, 810*c2c66affSColin Finck GenericMapping); 811*c2c66affSColin Finck } 812*c2c66affSColin Finck 813*c2c66affSColin Finck /* 814*c2c66affSColin Finck * @implemented 815*c2c66affSColin Finck */ 816*c2c66affSColin Finck _IRQL_requires_max_(PASSIVE_LEVEL) 817*c2c66affSColin Finck NTSTATUS 818*c2c66affSColin Finck NTAPI 819*c2c66affSColin Finck SeSetSecurityDescriptorInfoEx( 820*c2c66affSColin Finck _In_opt_ PVOID Object, 821*c2c66affSColin Finck _In_ PSECURITY_INFORMATION _SecurityInformation, 822*c2c66affSColin Finck _In_ PSECURITY_DESCRIPTOR _SecurityDescriptor, 823*c2c66affSColin Finck _Inout_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, 824*c2c66affSColin Finck _In_ ULONG AutoInheritFlags, 825*c2c66affSColin Finck _In_ POOL_TYPE PoolType, 826*c2c66affSColin Finck _In_ PGENERIC_MAPPING GenericMapping) 827*c2c66affSColin Finck { 828*c2c66affSColin Finck PISECURITY_DESCRIPTOR_RELATIVE ObjectSd; 829*c2c66affSColin Finck PISECURITY_DESCRIPTOR_RELATIVE NewSd; 830*c2c66affSColin Finck PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor; 831*c2c66affSColin Finck PSID Owner; 832*c2c66affSColin Finck PSID Group; 833*c2c66affSColin Finck PACL Dacl; 834*c2c66affSColin Finck PACL Sacl; 835*c2c66affSColin Finck ULONG OwnerLength; 836*c2c66affSColin Finck ULONG GroupLength; 837*c2c66affSColin Finck ULONG DaclLength; 838*c2c66affSColin Finck ULONG SaclLength; 839*c2c66affSColin Finck SECURITY_DESCRIPTOR_CONTROL Control = 0; 840*c2c66affSColin Finck ULONG Current; 841*c2c66affSColin Finck SECURITY_INFORMATION SecurityInformation; 842*c2c66affSColin Finck 843*c2c66affSColin Finck PAGED_CODE(); 844*c2c66affSColin Finck 845*c2c66affSColin Finck ObjectSd = *ObjectsSecurityDescriptor; 846*c2c66affSColin Finck 847*c2c66affSColin Finck /* The object does not have a security descriptor. */ 848*c2c66affSColin Finck if (!ObjectSd) 849*c2c66affSColin Finck return STATUS_NO_SECURITY_ON_OBJECT; 850*c2c66affSColin Finck 851*c2c66affSColin Finck ASSERT(ObjectSd->Control & SE_SELF_RELATIVE); 852*c2c66affSColin Finck 853*c2c66affSColin Finck SecurityInformation = *_SecurityInformation; 854*c2c66affSColin Finck 855*c2c66affSColin Finck /* Get owner and owner size */ 856*c2c66affSColin Finck if (SecurityInformation & OWNER_SECURITY_INFORMATION) 857*c2c66affSColin Finck { 858*c2c66affSColin Finck Owner = SepGetOwnerFromDescriptor(SecurityDescriptor); 859*c2c66affSColin Finck Control |= (SecurityDescriptor->Control & SE_OWNER_DEFAULTED); 860*c2c66affSColin Finck } 861*c2c66affSColin Finck else 862*c2c66affSColin Finck { 863*c2c66affSColin Finck Owner = SepGetOwnerFromDescriptor(ObjectSd); 864*c2c66affSColin Finck Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED); 865*c2c66affSColin Finck } 866*c2c66affSColin Finck OwnerLength = Owner ? RtlLengthSid(Owner) : 0; 867*c2c66affSColin Finck ASSERT(OwnerLength % sizeof(ULONG) == 0); 868*c2c66affSColin Finck 869*c2c66affSColin Finck /* Get group and group size */ 870*c2c66affSColin Finck if (SecurityInformation & GROUP_SECURITY_INFORMATION) 871*c2c66affSColin Finck { 872*c2c66affSColin Finck Group = SepGetGroupFromDescriptor(SecurityDescriptor); 873*c2c66affSColin Finck Control |= (SecurityDescriptor->Control & SE_GROUP_DEFAULTED); 874*c2c66affSColin Finck } 875*c2c66affSColin Finck else 876*c2c66affSColin Finck { 877*c2c66affSColin Finck Group = SepGetGroupFromDescriptor(ObjectSd); 878*c2c66affSColin Finck Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED); 879*c2c66affSColin Finck } 880*c2c66affSColin Finck GroupLength = Group ? RtlLengthSid(Group) : 0; 881*c2c66affSColin Finck ASSERT(GroupLength % sizeof(ULONG) == 0); 882*c2c66affSColin Finck 883*c2c66affSColin Finck /* Get DACL and DACL size */ 884*c2c66affSColin Finck if (SecurityInformation & DACL_SECURITY_INFORMATION) 885*c2c66affSColin Finck { 886*c2c66affSColin Finck Dacl = SepGetDaclFromDescriptor(SecurityDescriptor); 887*c2c66affSColin Finck Control |= (SecurityDescriptor->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT)); 888*c2c66affSColin Finck } 889*c2c66affSColin Finck else 890*c2c66affSColin Finck { 891*c2c66affSColin Finck Dacl = SepGetDaclFromDescriptor(ObjectSd); 892*c2c66affSColin Finck Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT)); 893*c2c66affSColin Finck } 894*c2c66affSColin Finck DaclLength = Dacl ? ROUND_UP((ULONG)Dacl->AclSize, 4) : 0; 895*c2c66affSColin Finck 896*c2c66affSColin Finck /* Get SACL and SACL size */ 897*c2c66affSColin Finck if (SecurityInformation & SACL_SECURITY_INFORMATION) 898*c2c66affSColin Finck { 899*c2c66affSColin Finck Sacl = SepGetSaclFromDescriptor(SecurityDescriptor); 900*c2c66affSColin Finck Control |= (SecurityDescriptor->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT)); 901*c2c66affSColin Finck } 902*c2c66affSColin Finck else 903*c2c66affSColin Finck { 904*c2c66affSColin Finck Sacl = SepGetSaclFromDescriptor(ObjectSd); 905*c2c66affSColin Finck Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT)); 906*c2c66affSColin Finck } 907*c2c66affSColin Finck SaclLength = Sacl ? ROUND_UP((ULONG)Sacl->AclSize, 4) : 0; 908*c2c66affSColin Finck 909*c2c66affSColin Finck NewSd = ExAllocatePoolWithTag(NonPagedPool, 910*c2c66affSColin Finck sizeof(SECURITY_DESCRIPTOR_RELATIVE) + 911*c2c66affSColin Finck OwnerLength + GroupLength + 912*c2c66affSColin Finck DaclLength + SaclLength, 913*c2c66affSColin Finck TAG_SD); 914*c2c66affSColin Finck if (NewSd == NULL) 915*c2c66affSColin Finck { 916*c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 917*c2c66affSColin Finck } 918*c2c66affSColin Finck 919*c2c66affSColin Finck RtlCreateSecurityDescriptor(NewSd, 920*c2c66affSColin Finck SECURITY_DESCRIPTOR_REVISION1); 921*c2c66affSColin Finck 922*c2c66affSColin Finck /* We always build a self-relative descriptor */ 923*c2c66affSColin Finck NewSd->Control = Control | SE_SELF_RELATIVE; 924*c2c66affSColin Finck 925*c2c66affSColin Finck Current = sizeof(SECURITY_DESCRIPTOR); 926*c2c66affSColin Finck 927*c2c66affSColin Finck if (OwnerLength != 0) 928*c2c66affSColin Finck { 929*c2c66affSColin Finck RtlCopyMemory((PUCHAR)NewSd + Current, Owner, OwnerLength); 930*c2c66affSColin Finck NewSd->Owner = Current; 931*c2c66affSColin Finck Current += OwnerLength; 932*c2c66affSColin Finck } 933*c2c66affSColin Finck 934*c2c66affSColin Finck if (GroupLength != 0) 935*c2c66affSColin Finck { 936*c2c66affSColin Finck RtlCopyMemory((PUCHAR)NewSd + Current, Group, GroupLength); 937*c2c66affSColin Finck NewSd->Group = Current; 938*c2c66affSColin Finck Current += GroupLength; 939*c2c66affSColin Finck } 940*c2c66affSColin Finck 941*c2c66affSColin Finck if (DaclLength != 0) 942*c2c66affSColin Finck { 943*c2c66affSColin Finck RtlCopyMemory((PUCHAR)NewSd + Current, Dacl, DaclLength); 944*c2c66affSColin Finck NewSd->Dacl = Current; 945*c2c66affSColin Finck Current += DaclLength; 946*c2c66affSColin Finck } 947*c2c66affSColin Finck 948*c2c66affSColin Finck if (SaclLength != 0) 949*c2c66affSColin Finck { 950*c2c66affSColin Finck RtlCopyMemory((PUCHAR)NewSd + Current, Sacl, SaclLength); 951*c2c66affSColin Finck NewSd->Sacl = Current; 952*c2c66affSColin Finck Current += SaclLength; 953*c2c66affSColin Finck } 954*c2c66affSColin Finck 955*c2c66affSColin Finck *ObjectsSecurityDescriptor = NewSd; 956*c2c66affSColin Finck return STATUS_SUCCESS; 957*c2c66affSColin Finck } 958*c2c66affSColin Finck 959*c2c66affSColin Finck 960*c2c66affSColin Finck /* 961*c2c66affSColin Finck * @implemented 962*c2c66affSColin Finck */ 963*c2c66affSColin Finck BOOLEAN NTAPI 964*c2c66affSColin Finck SeValidSecurityDescriptor(IN ULONG Length, 965*c2c66affSColin Finck IN PSECURITY_DESCRIPTOR _SecurityDescriptor) 966*c2c66affSColin Finck { 967*c2c66affSColin Finck ULONG SdLength; 968*c2c66affSColin Finck PISID Sid; 969*c2c66affSColin Finck PACL Acl; 970*c2c66affSColin Finck PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor = _SecurityDescriptor; 971*c2c66affSColin Finck 972*c2c66affSColin Finck if (Length < SECURITY_DESCRIPTOR_MIN_LENGTH) 973*c2c66affSColin Finck { 974*c2c66affSColin Finck DPRINT1("Invalid Security Descriptor revision\n"); 975*c2c66affSColin Finck return FALSE; 976*c2c66affSColin Finck } 977*c2c66affSColin Finck 978*c2c66affSColin Finck if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1) 979*c2c66affSColin Finck { 980*c2c66affSColin Finck DPRINT1("Invalid Security Descriptor revision\n"); 981*c2c66affSColin Finck return FALSE; 982*c2c66affSColin Finck } 983*c2c66affSColin Finck 984*c2c66affSColin Finck if (!(SecurityDescriptor->Control & SE_SELF_RELATIVE)) 985*c2c66affSColin Finck { 986*c2c66affSColin Finck DPRINT1("No self-relative Security Descriptor\n"); 987*c2c66affSColin Finck return FALSE; 988*c2c66affSColin Finck } 989*c2c66affSColin Finck 990*c2c66affSColin Finck SdLength = sizeof(SECURITY_DESCRIPTOR); 991*c2c66affSColin Finck 992*c2c66affSColin Finck /* Check Owner SID */ 993*c2c66affSColin Finck if (!SecurityDescriptor->Owner) 994*c2c66affSColin Finck { 995*c2c66affSColin Finck DPRINT1("No Owner SID\n"); 996*c2c66affSColin Finck return FALSE; 997*c2c66affSColin Finck } 998*c2c66affSColin Finck 999*c2c66affSColin Finck if (SecurityDescriptor->Owner % sizeof(ULONG)) 1000*c2c66affSColin Finck { 1001*c2c66affSColin Finck DPRINT1("Invalid Owner SID alignment\n"); 1002*c2c66affSColin Finck return FALSE; 1003*c2c66affSColin Finck } 1004*c2c66affSColin Finck 1005*c2c66affSColin Finck Sid = (PISID)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Owner); 1006*c2c66affSColin Finck if (Sid->Revision != SID_REVISION) 1007*c2c66affSColin Finck { 1008*c2c66affSColin Finck DPRINT1("Invalid Owner SID revision\n"); 1009*c2c66affSColin Finck return FALSE; 1010*c2c66affSColin Finck } 1011*c2c66affSColin Finck 1012*c2c66affSColin Finck SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG)); 1013*c2c66affSColin Finck if (Length < SdLength) 1014*c2c66affSColin Finck { 1015*c2c66affSColin Finck DPRINT1("Invalid Owner SID size\n"); 1016*c2c66affSColin Finck return FALSE; 1017*c2c66affSColin Finck } 1018*c2c66affSColin Finck 1019*c2c66affSColin Finck /* Check Group SID */ 1020*c2c66affSColin Finck if (SecurityDescriptor->Group) 1021*c2c66affSColin Finck { 1022*c2c66affSColin Finck if (SecurityDescriptor->Group % sizeof(ULONG)) 1023*c2c66affSColin Finck { 1024*c2c66affSColin Finck DPRINT1("Invalid Group SID alignment\n"); 1025*c2c66affSColin Finck return FALSE; 1026*c2c66affSColin Finck } 1027*c2c66affSColin Finck 1028*c2c66affSColin Finck Sid = (PSID)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Group); 1029*c2c66affSColin Finck if (Sid->Revision != SID_REVISION) 1030*c2c66affSColin Finck { 1031*c2c66affSColin Finck DPRINT1("Invalid Group SID revision\n"); 1032*c2c66affSColin Finck return FALSE; 1033*c2c66affSColin Finck } 1034*c2c66affSColin Finck 1035*c2c66affSColin Finck SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG)); 1036*c2c66affSColin Finck if (Length < SdLength) 1037*c2c66affSColin Finck { 1038*c2c66affSColin Finck DPRINT1("Invalid Group SID size\n"); 1039*c2c66affSColin Finck return FALSE; 1040*c2c66affSColin Finck } 1041*c2c66affSColin Finck } 1042*c2c66affSColin Finck 1043*c2c66affSColin Finck /* Check DACL */ 1044*c2c66affSColin Finck if (SecurityDescriptor->Dacl) 1045*c2c66affSColin Finck { 1046*c2c66affSColin Finck if (SecurityDescriptor->Dacl % sizeof(ULONG)) 1047*c2c66affSColin Finck { 1048*c2c66affSColin Finck DPRINT1("Invalid DACL alignment\n"); 1049*c2c66affSColin Finck return FALSE; 1050*c2c66affSColin Finck } 1051*c2c66affSColin Finck 1052*c2c66affSColin Finck Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Dacl); 1053*c2c66affSColin Finck if ((Acl->AclRevision < MIN_ACL_REVISION) || 1054*c2c66affSColin Finck (Acl->AclRevision > MAX_ACL_REVISION)) 1055*c2c66affSColin Finck { 1056*c2c66affSColin Finck DPRINT1("Invalid DACL revision\n"); 1057*c2c66affSColin Finck return FALSE; 1058*c2c66affSColin Finck } 1059*c2c66affSColin Finck 1060*c2c66affSColin Finck SdLength += Acl->AclSize; 1061*c2c66affSColin Finck if (Length < SdLength) 1062*c2c66affSColin Finck { 1063*c2c66affSColin Finck DPRINT1("Invalid DACL size\n"); 1064*c2c66affSColin Finck return FALSE; 1065*c2c66affSColin Finck } 1066*c2c66affSColin Finck } 1067*c2c66affSColin Finck 1068*c2c66affSColin Finck /* Check SACL */ 1069*c2c66affSColin Finck if (SecurityDescriptor->Sacl) 1070*c2c66affSColin Finck { 1071*c2c66affSColin Finck if (SecurityDescriptor->Sacl % sizeof(ULONG)) 1072*c2c66affSColin Finck { 1073*c2c66affSColin Finck DPRINT1("Invalid SACL alignment\n"); 1074*c2c66affSColin Finck return FALSE; 1075*c2c66affSColin Finck } 1076*c2c66affSColin Finck 1077*c2c66affSColin Finck Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Sacl); 1078*c2c66affSColin Finck if ((Acl->AclRevision < MIN_ACL_REVISION) || 1079*c2c66affSColin Finck (Acl->AclRevision > MAX_ACL_REVISION)) 1080*c2c66affSColin Finck { 1081*c2c66affSColin Finck DPRINT1("Invalid SACL revision\n"); 1082*c2c66affSColin Finck return FALSE; 1083*c2c66affSColin Finck } 1084*c2c66affSColin Finck 1085*c2c66affSColin Finck SdLength += Acl->AclSize; 1086*c2c66affSColin Finck if (Length < SdLength) 1087*c2c66affSColin Finck { 1088*c2c66affSColin Finck DPRINT1("Invalid SACL size\n"); 1089*c2c66affSColin Finck return FALSE; 1090*c2c66affSColin Finck } 1091*c2c66affSColin Finck } 1092*c2c66affSColin Finck 1093*c2c66affSColin Finck return TRUE; 1094*c2c66affSColin Finck } 1095*c2c66affSColin Finck 1096*c2c66affSColin Finck /* 1097*c2c66affSColin Finck * @implemented 1098*c2c66affSColin Finck */ 1099*c2c66affSColin Finck _IRQL_requires_max_(PASSIVE_LEVEL) 1100*c2c66affSColin Finck NTSTATUS 1101*c2c66affSColin Finck NTAPI 1102*c2c66affSColin Finck SeDeassignSecurity( 1103*c2c66affSColin Finck _Inout_ PSECURITY_DESCRIPTOR *SecurityDescriptor) 1104*c2c66affSColin Finck { 1105*c2c66affSColin Finck PAGED_CODE(); 1106*c2c66affSColin Finck 1107*c2c66affSColin Finck if (*SecurityDescriptor != NULL) 1108*c2c66affSColin Finck { 1109*c2c66affSColin Finck ExFreePoolWithTag(*SecurityDescriptor, TAG_SD); 1110*c2c66affSColin Finck *SecurityDescriptor = NULL; 1111*c2c66affSColin Finck } 1112*c2c66affSColin Finck 1113*c2c66affSColin Finck return STATUS_SUCCESS; 1114*c2c66affSColin Finck } 1115*c2c66affSColin Finck 1116*c2c66affSColin Finck /* 1117*c2c66affSColin Finck * @implemented 1118*c2c66affSColin Finck */ 1119*c2c66affSColin Finck _IRQL_requires_max_(PASSIVE_LEVEL) 1120*c2c66affSColin Finck NTSTATUS 1121*c2c66affSColin Finck NTAPI 1122*c2c66affSColin Finck SeAssignSecurityEx( 1123*c2c66affSColin Finck _In_opt_ PSECURITY_DESCRIPTOR _ParentDescriptor, 1124*c2c66affSColin Finck _In_opt_ PSECURITY_DESCRIPTOR _ExplicitDescriptor, 1125*c2c66affSColin Finck _Out_ PSECURITY_DESCRIPTOR *NewDescriptor, 1126*c2c66affSColin Finck _In_opt_ GUID *ObjectType, 1127*c2c66affSColin Finck _In_ BOOLEAN IsDirectoryObject, 1128*c2c66affSColin Finck _In_ ULONG AutoInheritFlags, 1129*c2c66affSColin Finck _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, 1130*c2c66affSColin Finck _In_ PGENERIC_MAPPING GenericMapping, 1131*c2c66affSColin Finck _In_ POOL_TYPE PoolType) 1132*c2c66affSColin Finck { 1133*c2c66affSColin Finck PISECURITY_DESCRIPTOR ParentDescriptor = _ParentDescriptor; 1134*c2c66affSColin Finck PISECURITY_DESCRIPTOR ExplicitDescriptor = _ExplicitDescriptor; 1135*c2c66affSColin Finck PISECURITY_DESCRIPTOR_RELATIVE Descriptor; 1136*c2c66affSColin Finck PTOKEN Token; 1137*c2c66affSColin Finck ULONG OwnerLength; 1138*c2c66affSColin Finck ULONG GroupLength; 1139*c2c66affSColin Finck ULONG DaclLength; 1140*c2c66affSColin Finck ULONG SaclLength; 1141*c2c66affSColin Finck ULONG Length; 1142*c2c66affSColin Finck SECURITY_DESCRIPTOR_CONTROL Control = 0; 1143*c2c66affSColin Finck ULONG Current; 1144*c2c66affSColin Finck PSID Owner = NULL; 1145*c2c66affSColin Finck PSID Group = NULL; 1146*c2c66affSColin Finck PACL ExplicitAcl; 1147*c2c66affSColin Finck BOOLEAN ExplicitPresent; 1148*c2c66affSColin Finck BOOLEAN ExplicitDefaulted; 1149*c2c66affSColin Finck PACL ParentAcl; 1150*c2c66affSColin Finck PACL Dacl = NULL; 1151*c2c66affSColin Finck PACL Sacl = NULL; 1152*c2c66affSColin Finck BOOLEAN DaclIsInherited; 1153*c2c66affSColin Finck BOOLEAN SaclIsInherited; 1154*c2c66affSColin Finck BOOLEAN DaclPresent; 1155*c2c66affSColin Finck BOOLEAN SaclPresent; 1156*c2c66affSColin Finck NTSTATUS Status; 1157*c2c66affSColin Finck 1158*c2c66affSColin Finck DBG_UNREFERENCED_PARAMETER(ObjectType); 1159*c2c66affSColin Finck DBG_UNREFERENCED_PARAMETER(AutoInheritFlags); 1160*c2c66affSColin Finck UNREFERENCED_PARAMETER(PoolType); 1161*c2c66affSColin Finck 1162*c2c66affSColin Finck PAGED_CODE(); 1163*c2c66affSColin Finck 1164*c2c66affSColin Finck *NewDescriptor = NULL; 1165*c2c66affSColin Finck 1166*c2c66affSColin Finck if (!ARGUMENT_PRESENT(SubjectContext)) 1167*c2c66affSColin Finck { 1168*c2c66affSColin Finck return STATUS_NO_TOKEN; 1169*c2c66affSColin Finck } 1170*c2c66affSColin Finck 1171*c2c66affSColin Finck /* Lock subject context */ 1172*c2c66affSColin Finck SeLockSubjectContext(SubjectContext); 1173*c2c66affSColin Finck 1174*c2c66affSColin Finck if (SubjectContext->ClientToken != NULL) 1175*c2c66affSColin Finck { 1176*c2c66affSColin Finck Token = SubjectContext->ClientToken; 1177*c2c66affSColin Finck } 1178*c2c66affSColin Finck else 1179*c2c66affSColin Finck { 1180*c2c66affSColin Finck Token = SubjectContext->PrimaryToken; 1181*c2c66affSColin Finck } 1182*c2c66affSColin Finck 1183*c2c66affSColin Finck /* Inherit the Owner SID */ 1184*c2c66affSColin Finck if (ExplicitDescriptor != NULL) 1185*c2c66affSColin Finck { 1186*c2c66affSColin Finck DPRINT("Use explicit owner sid!\n"); 1187*c2c66affSColin Finck Owner = SepGetOwnerFromDescriptor(ExplicitDescriptor); 1188*c2c66affSColin Finck } 1189*c2c66affSColin Finck if (!Owner) 1190*c2c66affSColin Finck { 1191*c2c66affSColin Finck if (AutoInheritFlags & 0x20 /* FIXME: SEF_DEFAULT_OWNER_FROM_PARENT */) 1192*c2c66affSColin Finck { 1193*c2c66affSColin Finck DPRINT("Use parent owner sid!\n"); 1194*c2c66affSColin Finck if (!ARGUMENT_PRESENT(ParentDescriptor)) 1195*c2c66affSColin Finck { 1196*c2c66affSColin Finck SeUnlockSubjectContext(SubjectContext); 1197*c2c66affSColin Finck return STATUS_INVALID_OWNER; 1198*c2c66affSColin Finck } 1199*c2c66affSColin Finck 1200*c2c66affSColin Finck Owner = SepGetOwnerFromDescriptor(ParentDescriptor); 1201*c2c66affSColin Finck if (!Owner) 1202*c2c66affSColin Finck { 1203*c2c66affSColin Finck SeUnlockSubjectContext(SubjectContext); 1204*c2c66affSColin Finck return STATUS_INVALID_OWNER; 1205*c2c66affSColin Finck } 1206*c2c66affSColin Finck } 1207*c2c66affSColin Finck else 1208*c2c66affSColin Finck { 1209*c2c66affSColin Finck DPRINT("Use token owner sid!\n"); 1210*c2c66affSColin Finck Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid; 1211*c2c66affSColin Finck } 1212*c2c66affSColin Finck } 1213*c2c66affSColin Finck OwnerLength = RtlLengthSid(Owner); 1214*c2c66affSColin Finck ASSERT(OwnerLength % sizeof(ULONG) == 0); 1215*c2c66affSColin Finck 1216*c2c66affSColin Finck /* Inherit the Group SID */ 1217*c2c66affSColin Finck if (ExplicitDescriptor != NULL) 1218*c2c66affSColin Finck { 1219*c2c66affSColin Finck Group = SepGetGroupFromDescriptor(ExplicitDescriptor); 1220*c2c66affSColin Finck } 1221*c2c66affSColin Finck if (!Group) 1222*c2c66affSColin Finck { 1223*c2c66affSColin Finck if (AutoInheritFlags & 0x40 /* FIXME: SEF_DEFAULT_GROUP_FROM_PARENT */) 1224*c2c66affSColin Finck { 1225*c2c66affSColin Finck DPRINT("Use parent group sid!\n"); 1226*c2c66affSColin Finck if (!ARGUMENT_PRESENT(ParentDescriptor)) 1227*c2c66affSColin Finck { 1228*c2c66affSColin Finck SeUnlockSubjectContext(SubjectContext); 1229*c2c66affSColin Finck return STATUS_INVALID_PRIMARY_GROUP; 1230*c2c66affSColin Finck } 1231*c2c66affSColin Finck 1232*c2c66affSColin Finck Group = SepGetGroupFromDescriptor(ParentDescriptor); 1233*c2c66affSColin Finck if (!Group) 1234*c2c66affSColin Finck { 1235*c2c66affSColin Finck SeUnlockSubjectContext(SubjectContext); 1236*c2c66affSColin Finck return STATUS_INVALID_PRIMARY_GROUP; 1237*c2c66affSColin Finck } 1238*c2c66affSColin Finck } 1239*c2c66affSColin Finck else 1240*c2c66affSColin Finck { 1241*c2c66affSColin Finck DPRINT("Use token group sid!\n"); 1242*c2c66affSColin Finck Group = Token->PrimaryGroup; 1243*c2c66affSColin Finck } 1244*c2c66affSColin Finck } 1245*c2c66affSColin Finck if (!Group) 1246*c2c66affSColin Finck { 1247*c2c66affSColin Finck SeUnlockSubjectContext(SubjectContext); 1248*c2c66affSColin Finck return STATUS_INVALID_PRIMARY_GROUP; 1249*c2c66affSColin Finck } 1250*c2c66affSColin Finck GroupLength = RtlLengthSid(Group); 1251*c2c66affSColin Finck ASSERT(GroupLength % sizeof(ULONG) == 0); 1252*c2c66affSColin Finck 1253*c2c66affSColin Finck /* Inherit the DACL */ 1254*c2c66affSColin Finck DaclLength = 0; 1255*c2c66affSColin Finck ExplicitAcl = NULL; 1256*c2c66affSColin Finck ExplicitPresent = FALSE; 1257*c2c66affSColin Finck ExplicitDefaulted = FALSE; 1258*c2c66affSColin Finck if (ExplicitDescriptor != NULL && 1259*c2c66affSColin Finck (ExplicitDescriptor->Control & SE_DACL_PRESENT)) 1260*c2c66affSColin Finck { 1261*c2c66affSColin Finck ExplicitAcl = SepGetDaclFromDescriptor(ExplicitDescriptor); 1262*c2c66affSColin Finck ExplicitPresent = TRUE; 1263*c2c66affSColin Finck if (ExplicitDescriptor->Control & SE_DACL_DEFAULTED) 1264*c2c66affSColin Finck ExplicitDefaulted = TRUE; 1265*c2c66affSColin Finck } 1266*c2c66affSColin Finck ParentAcl = NULL; 1267*c2c66affSColin Finck if (ParentDescriptor != NULL && 1268*c2c66affSColin Finck (ParentDescriptor->Control & SE_DACL_PRESENT)) 1269*c2c66affSColin Finck { 1270*c2c66affSColin Finck ParentAcl = SepGetDaclFromDescriptor(ParentDescriptor); 1271*c2c66affSColin Finck } 1272*c2c66affSColin Finck Dacl = SepSelectAcl(ExplicitAcl, 1273*c2c66affSColin Finck ExplicitPresent, 1274*c2c66affSColin Finck ExplicitDefaulted, 1275*c2c66affSColin Finck ParentAcl, 1276*c2c66affSColin Finck Token->DefaultDacl, 1277*c2c66affSColin Finck &DaclLength, 1278*c2c66affSColin Finck Owner, 1279*c2c66affSColin Finck Group, 1280*c2c66affSColin Finck &DaclPresent, 1281*c2c66affSColin Finck &DaclIsInherited, 1282*c2c66affSColin Finck IsDirectoryObject, 1283*c2c66affSColin Finck GenericMapping); 1284*c2c66affSColin Finck if (DaclPresent) 1285*c2c66affSColin Finck Control |= SE_DACL_PRESENT; 1286*c2c66affSColin Finck ASSERT(DaclLength % sizeof(ULONG) == 0); 1287*c2c66affSColin Finck 1288*c2c66affSColin Finck /* Inherit the SACL */ 1289*c2c66affSColin Finck SaclLength = 0; 1290*c2c66affSColin Finck ExplicitAcl = NULL; 1291*c2c66affSColin Finck ExplicitPresent = FALSE; 1292*c2c66affSColin Finck ExplicitDefaulted = FALSE; 1293*c2c66affSColin Finck if (ExplicitDescriptor != NULL && 1294*c2c66affSColin Finck (ExplicitDescriptor->Control & SE_SACL_PRESENT)) 1295*c2c66affSColin Finck { 1296*c2c66affSColin Finck ExplicitAcl = SepGetSaclFromDescriptor(ExplicitDescriptor); 1297*c2c66affSColin Finck ExplicitPresent = TRUE; 1298*c2c66affSColin Finck if (ExplicitDescriptor->Control & SE_SACL_DEFAULTED) 1299*c2c66affSColin Finck ExplicitDefaulted = TRUE; 1300*c2c66affSColin Finck } 1301*c2c66affSColin Finck ParentAcl = NULL; 1302*c2c66affSColin Finck if (ParentDescriptor != NULL && 1303*c2c66affSColin Finck (ParentDescriptor->Control & SE_SACL_PRESENT)) 1304*c2c66affSColin Finck { 1305*c2c66affSColin Finck ParentAcl = SepGetSaclFromDescriptor(ParentDescriptor); 1306*c2c66affSColin Finck } 1307*c2c66affSColin Finck Sacl = SepSelectAcl(ExplicitAcl, 1308*c2c66affSColin Finck ExplicitPresent, 1309*c2c66affSColin Finck ExplicitDefaulted, 1310*c2c66affSColin Finck ParentAcl, 1311*c2c66affSColin Finck NULL, 1312*c2c66affSColin Finck &SaclLength, 1313*c2c66affSColin Finck Owner, 1314*c2c66affSColin Finck Group, 1315*c2c66affSColin Finck &SaclPresent, 1316*c2c66affSColin Finck &SaclIsInherited, 1317*c2c66affSColin Finck IsDirectoryObject, 1318*c2c66affSColin Finck GenericMapping); 1319*c2c66affSColin Finck if (SaclPresent) 1320*c2c66affSColin Finck Control |= SE_SACL_PRESENT; 1321*c2c66affSColin Finck ASSERT(SaclLength % sizeof(ULONG) == 0); 1322*c2c66affSColin Finck 1323*c2c66affSColin Finck /* Allocate and initialize the new security descriptor */ 1324*c2c66affSColin Finck Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE) + 1325*c2c66affSColin Finck OwnerLength + GroupLength + DaclLength + SaclLength; 1326*c2c66affSColin Finck 1327*c2c66affSColin Finck DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %u OwnerLength %lu GroupLength %lu DaclLength %lu SaclLength %lu\n", 1328*c2c66affSColin Finck sizeof(SECURITY_DESCRIPTOR), 1329*c2c66affSColin Finck OwnerLength, 1330*c2c66affSColin Finck GroupLength, 1331*c2c66affSColin Finck DaclLength, 1332*c2c66affSColin Finck SaclLength); 1333*c2c66affSColin Finck 1334*c2c66affSColin Finck Descriptor = ExAllocatePoolWithTag(PagedPool, Length, TAG_SD); 1335*c2c66affSColin Finck if (Descriptor == NULL) 1336*c2c66affSColin Finck { 1337*c2c66affSColin Finck DPRINT1("ExAlloctePool() failed\n"); 1338*c2c66affSColin Finck SeUnlockSubjectContext(SubjectContext); 1339*c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 1340*c2c66affSColin Finck } 1341*c2c66affSColin Finck 1342*c2c66affSColin Finck RtlZeroMemory(Descriptor, Length); 1343*c2c66affSColin Finck RtlCreateSecurityDescriptor(Descriptor, SECURITY_DESCRIPTOR_REVISION); 1344*c2c66affSColin Finck 1345*c2c66affSColin Finck Descriptor->Control = Control | SE_SELF_RELATIVE; 1346*c2c66affSColin Finck 1347*c2c66affSColin Finck Current = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 1348*c2c66affSColin Finck 1349*c2c66affSColin Finck if (SaclLength != 0) 1350*c2c66affSColin Finck { 1351*c2c66affSColin Finck Status = SepPropagateAcl((PACL)((PUCHAR)Descriptor + Current), 1352*c2c66affSColin Finck &SaclLength, 1353*c2c66affSColin Finck Sacl, 1354*c2c66affSColin Finck Owner, 1355*c2c66affSColin Finck Group, 1356*c2c66affSColin Finck SaclIsInherited, 1357*c2c66affSColin Finck IsDirectoryObject, 1358*c2c66affSColin Finck GenericMapping); 1359*c2c66affSColin Finck ASSERT(Status == STATUS_SUCCESS); 1360*c2c66affSColin Finck Descriptor->Sacl = Current; 1361*c2c66affSColin Finck Current += SaclLength; 1362*c2c66affSColin Finck } 1363*c2c66affSColin Finck 1364*c2c66affSColin Finck if (DaclLength != 0) 1365*c2c66affSColin Finck { 1366*c2c66affSColin Finck Status = SepPropagateAcl((PACL)((PUCHAR)Descriptor + Current), 1367*c2c66affSColin Finck &DaclLength, 1368*c2c66affSColin Finck Dacl, 1369*c2c66affSColin Finck Owner, 1370*c2c66affSColin Finck Group, 1371*c2c66affSColin Finck DaclIsInherited, 1372*c2c66affSColin Finck IsDirectoryObject, 1373*c2c66affSColin Finck GenericMapping); 1374*c2c66affSColin Finck ASSERT(Status == STATUS_SUCCESS); 1375*c2c66affSColin Finck Descriptor->Dacl = Current; 1376*c2c66affSColin Finck Current += DaclLength; 1377*c2c66affSColin Finck } 1378*c2c66affSColin Finck 1379*c2c66affSColin Finck if (OwnerLength != 0) 1380*c2c66affSColin Finck { 1381*c2c66affSColin Finck RtlCopyMemory((PUCHAR)Descriptor + Current, Owner, OwnerLength); 1382*c2c66affSColin Finck Descriptor->Owner = Current; 1383*c2c66affSColin Finck Current += OwnerLength; 1384*c2c66affSColin Finck DPRINT("Owner of %p at %x\n", Descriptor, Descriptor->Owner); 1385*c2c66affSColin Finck } 1386*c2c66affSColin Finck else 1387*c2c66affSColin Finck { 1388*c2c66affSColin Finck DPRINT("Owner of %p is zero length\n", Descriptor); 1389*c2c66affSColin Finck } 1390*c2c66affSColin Finck 1391*c2c66affSColin Finck if (GroupLength != 0) 1392*c2c66affSColin Finck { 1393*c2c66affSColin Finck RtlCopyMemory((PUCHAR)Descriptor + Current, Group, GroupLength); 1394*c2c66affSColin Finck Descriptor->Group = Current; 1395*c2c66affSColin Finck } 1396*c2c66affSColin Finck 1397*c2c66affSColin Finck /* Unlock subject context */ 1398*c2c66affSColin Finck SeUnlockSubjectContext(SubjectContext); 1399*c2c66affSColin Finck 1400*c2c66affSColin Finck *NewDescriptor = Descriptor; 1401*c2c66affSColin Finck 1402*c2c66affSColin Finck DPRINT("Descriptor %p\n", Descriptor); 1403*c2c66affSColin Finck ASSERT(RtlLengthSecurityDescriptor(Descriptor)); 1404*c2c66affSColin Finck 1405*c2c66affSColin Finck return STATUS_SUCCESS; 1406*c2c66affSColin Finck } 1407*c2c66affSColin Finck 1408*c2c66affSColin Finck /* 1409*c2c66affSColin Finck * @implemented 1410*c2c66affSColin Finck */ 1411*c2c66affSColin Finck _IRQL_requires_max_(PASSIVE_LEVEL) 1412*c2c66affSColin Finck NTSTATUS 1413*c2c66affSColin Finck NTAPI 1414*c2c66affSColin Finck SeAssignSecurity( 1415*c2c66affSColin Finck _In_opt_ PSECURITY_DESCRIPTOR ParentDescriptor, 1416*c2c66affSColin Finck _In_opt_ PSECURITY_DESCRIPTOR ExplicitDescriptor, 1417*c2c66affSColin Finck _Out_ PSECURITY_DESCRIPTOR *NewDescriptor, 1418*c2c66affSColin Finck _In_ BOOLEAN IsDirectoryObject, 1419*c2c66affSColin Finck _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, 1420*c2c66affSColin Finck _In_ PGENERIC_MAPPING GenericMapping, 1421*c2c66affSColin Finck _In_ POOL_TYPE PoolType) 1422*c2c66affSColin Finck { 1423*c2c66affSColin Finck PAGED_CODE(); 1424*c2c66affSColin Finck 1425*c2c66affSColin Finck return SeAssignSecurityEx(ParentDescriptor, 1426*c2c66affSColin Finck ExplicitDescriptor, 1427*c2c66affSColin Finck NewDescriptor, 1428*c2c66affSColin Finck NULL, 1429*c2c66affSColin Finck IsDirectoryObject, 1430*c2c66affSColin Finck 0, 1431*c2c66affSColin Finck SubjectContext, 1432*c2c66affSColin Finck GenericMapping, 1433*c2c66affSColin Finck PoolType); 1434*c2c66affSColin Finck } 1435*c2c66affSColin Finck 1436*c2c66affSColin Finck /* EOF */ 1437