internal static T GetAccessControlHandleCore <T>(bool internalCall, bool isFolder, SafeFileHandle handle, AccessControlSections includeSections, SECURITY_INFORMATION securityInfo) { if (!internalCall) { securityInfo = CreateSecurityInformation(includeSections); } // We need the SE_SECURITY_NAME privilege enabled to be able to get the SACL descriptor. // So we enable it here for the remainder of this function. PrivilegeEnabler privilege = null; if (!internalCall && (includeSections & AccessControlSections.Audit) != 0) { privilege = new PrivilegeEnabler(Privilege.Security); } using (privilege) { IntPtr pSidOwner, pSidGroup, pDacl, pSacl; SafeGlobalMemoryBufferHandle pSecurityDescriptor; var lastError = Security.NativeMethods.GetSecurityInfo(handle, SE_OBJECT_TYPE.SE_FILE_OBJECT, securityInfo, out pSidOwner, out pSidGroup, out pDacl, out pSacl, out pSecurityDescriptor); return(GetSecurityDescriptor <T>(lastError, isFolder, null, pSecurityDescriptor)); } }
internal void Grant() { if (!Utilities.PlatForm.IsUnixClient()) { priv = new Alphaleonis.Win32.Security.PrivilegeEnabler(Privilege.Backup, Privilege.Restore, Privilege.ManageVolume); //see if this proves stable and reliable on all NT platforms int sec = Node.Misc.NativeMethods.CoInitializeSecurity(IntPtr.Zero, -1, IntPtr.Zero, IntPtr.Zero, Node.Misc.RpcAuthenticationLevels.None, Node.Misc.RpcImpersonationLevels.Impersonate, IntPtr.Zero, Node.Misc.EoAuthenticationCapabilities.None, IntPtr.Zero); Logger.Append(Severity.DEBUG, "CoInitializeSecurity() returned " + sec); } }
public override void PerformStep() { logger.LogInformation("Cloning operating system."); using (IVssBackupComponents backupComponents = vss.CreateVssBackupComponents()) { this.CreateVssSnapshotOfSystemVolume(backupComponents); try { logger.LogInformation("Copying system partition data..."); using (PrivilegeEnabler privEnabler = new PrivilegeEnabler(Privilege.Backup, Privilege.Restore)) { VssSnapshotProperties snapshotInfo = backupComponents.GetSnapshotProperties(this.vssSnapshotId); using (Stream rawVolStream = this.fileSystemHelper.OpenRawDiskStream(snapshotInfo.SnapshotDeviceObject)) { string vhdFullName = $"{migrationData.VhdFileTemporaryFolder}\\{migrationData.VhdFileName}"; using (VirtualDiskDecorator disk = this.fileSystemHelper.OpenVhdx(vhdFullName)) { var partitionTable = disk.Partitions; if (partitionTable != null) { int partIndex = partitionTable.CreatePrimaryBySector(1, (rawVolStream.Length / disk.Geometry.BytesPerSector), BiosPartitionTypes.Ntfs, false); PartitionInfoDecorator partition = disk.Partitions[partIndex]; using (var vhdPartitionStream = partition.Open()) { this.fileSystemHelper.CloneNtfsFileSystem(rawVolStream, vhdPartitionStream, logger); } } else { logger.LogError("VHD disk does not contain BIOS partition table. Other partitions tables are not supported."); } } } } } finally { this.RemoveVssSnapshotOfSystemVolume(backupComponents); //always remove the VSS snapshot, either after success or failure } logger.LogInformation("Cloning operating system completed."); } return; }
internal static T GetAccessControlCore <T>(bool isFolder, string path, AccessControlSections includeSections, PathFormat pathFormat) { SecurityInformation securityInfo = CreateSecurityInformation(includeSections); // We need the SE_SECURITY_NAME privilege enabled to be able to get the SACL descriptor. // So we enable it here for the remainder of this function. PrivilegeEnabler privilege = null; if ((includeSections & AccessControlSections.Audit) != 0) { privilege = new PrivilegeEnabler(Privilege.Security); } using (privilege) { IntPtr pSidOwner, pSidGroup, pDacl, pSacl; SafeGlobalMemoryBufferHandle pSecurityDescriptor; string pathLp = Path.GetExtendedLengthPathCore(null, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck); // Get/SetNamedSecurityInfo does not work with a handle but with a path, hence does not honor the privileges. // It magically does since Windows Server 2012 / 8 but not in previous OS versions. uint lastError = Security.NativeMethods.GetNamedSecurityInfo(pathLp, ObjectType.FileObject, securityInfo, out pSidOwner, out pSidGroup, out pDacl, out pSacl, out pSecurityDescriptor); // When GetNamedSecurityInfo() fails with ACCESS_DENIED, try again using GetSecurityInfo(). if (lastError == Win32Errors.ERROR_ACCESS_DENIED) { using (SafeFileHandle handle = CreateFileCore(null, pathLp, ExtendedFileAttributes.BackupSemantics, null, FileMode.Open, FileSystemRights.Read, FileShare.Read, false, PathFormat.LongFullPath)) { return(GetAccessControlHandleCore <T>(true, isFolder, handle, includeSections, securityInfo)); } } return(GetSecurityDescriptor <T>(lastError, isFolder, pathLp, pSecurityDescriptor)); } }
public override void PerformStep() { if (this.migrationData.TemporaryVhdFileIsTheFinalOne) { return; } logger.LogInformation("Copying partition data..."); this.sourceVhdFile = $"{migrationData.VhdFileTemporaryFolder}\\{migrationData.VhdFileName}"; this.destinationVhdFile = $"{migrationData.VhdFileDestinationFolder}\\{migrationData.VhdFileName}"; using (PrivilegeEnabler privEnabler = new PrivilegeEnabler(Privilege.Backup, Privilege.Restore)) { using (VirtualDiskDecorator sourceVhd = this.fileSystemHelper.OpenVhdx(this.sourceVhdFile)) { using (Stream inpuStream = sourceVhd.Partitions[0].Open()) { using (VirtualDiskDecorator destinationVhd = this.fileSystemHelper.OpenVhdx(this.destinationVhdFile)) { var partitionTable = destinationVhd.Partitions; int partIndex = partitionTable.CreatePrimaryBySector(1, (inpuStream.Length / destinationVhd.Geometry.BytesPerSector), BiosPartitionTypes.Ntfs, false); PartitionInfoDecorator partition = destinationVhd.Partitions[partIndex]; using (var outputStream = partition.Open()) { this.fileSystemHelper.CloneNtfsFileSystem(inpuStream, outputStream, logger); } } } } } if (migrationData.DeleteTemporaryVhdFile) { this.fileSystem.File.Delete(this.sourceVhdFile); } logger.LogInformation("Cloning temporary vhd to destination vhd completed."); }
public static PrivilegeEnabler EnableAllPrivileges() { var privileges = (Privilege[])Enum.GetValues(typeof(Privilege)); var process = Process.GetCurrentProcess(); var privilegeEnabler = new PrivilegeEnabler(process); foreach (var priv in privileges) { try { var result = privilegeEnabler.EnablePrivilege(priv); /* if (process.GetPrivilegeState(Privilege.TakeOwnership) != PrivilegeState.Enabled) * Logger.Error("Failed to grant privilege {0}", priv.ToString()); */ } catch (Win32Exception /* ex */) { /* Logger.Error("Failed to grant privilege {0}: {1}", priv.ToString(), ex.Message); */ } } return(privilegeEnabler); }
internal static void SetAccessControlCore(string path, SafeFileHandle handle, ObjectSecurity objectSecurity, AccessControlSections includeSections, PathFormat pathFormat) { if (pathFormat == PathFormat.RelativePath) { Path.CheckSupportedPathFormat(path, true, true); } if (objectSecurity == null) { throw new ArgumentNullException("objectSecurity"); } var managedDescriptor = objectSecurity.GetSecurityDescriptorBinaryForm(); using (var safeBuffer = new SafeGlobalMemoryBufferHandle(managedDescriptor.Length)) { var pathLp = Path.GetExtendedLengthPathCore(null, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.CheckInvalidPathChars); safeBuffer.CopyFrom(managedDescriptor, 0, managedDescriptor.Length); SECURITY_DESCRIPTOR_CONTROL control; uint revision; var success = Security.NativeMethods.GetSecurityDescriptorControl(safeBuffer, out control, out revision); var lastError = Marshal.GetLastWin32Error(); if (!success) { NativeError.ThrowException(lastError, pathLp); } PrivilegeEnabler privilegeEnabler = null; try { var securityInfo = SECURITY_INFORMATION.None; var pDacl = IntPtr.Zero; if ((includeSections & AccessControlSections.Access) != 0) { bool daclDefaulted, daclPresent; success = Security.NativeMethods.GetSecurityDescriptorDacl(safeBuffer, out daclPresent, out pDacl, out daclDefaulted); lastError = Marshal.GetLastWin32Error(); if (!success) { NativeError.ThrowException(lastError, pathLp); } if (daclPresent) { securityInfo |= SECURITY_INFORMATION.DACL_SECURITY_INFORMATION; securityInfo |= (control & SECURITY_DESCRIPTOR_CONTROL.SE_DACL_PROTECTED) != 0 ? SECURITY_INFORMATION.PROTECTED_DACL_SECURITY_INFORMATION : SECURITY_INFORMATION.UNPROTECTED_DACL_SECURITY_INFORMATION; } } var pSacl = IntPtr.Zero; if ((includeSections & AccessControlSections.Audit) != 0) { bool saclDefaulted, saclPresent; success = Security.NativeMethods.GetSecurityDescriptorSacl(safeBuffer, out saclPresent, out pSacl, out saclDefaulted); lastError = Marshal.GetLastWin32Error(); if (!success) { NativeError.ThrowException(lastError, pathLp); } if (saclPresent) { securityInfo |= SECURITY_INFORMATION.SACL_SECURITY_INFORMATION; securityInfo |= (control & SECURITY_DESCRIPTOR_CONTROL.SE_SACL_PROTECTED) != 0 ? SECURITY_INFORMATION.PROTECTED_SACL_SECURITY_INFORMATION : SECURITY_INFORMATION.UNPROTECTED_SACL_SECURITY_INFORMATION; privilegeEnabler = new PrivilegeEnabler(Privilege.Security); } } var pOwner = IntPtr.Zero; if ((includeSections & AccessControlSections.Owner) != 0) { bool ownerDefaulted; success = Security.NativeMethods.GetSecurityDescriptorOwner(safeBuffer, out pOwner, out ownerDefaulted); lastError = Marshal.GetLastWin32Error(); if (!success) { NativeError.ThrowException(lastError, pathLp); } if (pOwner != IntPtr.Zero) { securityInfo |= SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION; } } var pGroup = IntPtr.Zero; if ((includeSections & AccessControlSections.Group) != 0) { bool groupDefaulted; success = Security.NativeMethods.GetSecurityDescriptorGroup(safeBuffer, out pGroup, out groupDefaulted); lastError = Marshal.GetLastWin32Error(); if (!success) { NativeError.ThrowException(lastError, pathLp); } if (pGroup != IntPtr.Zero) { securityInfo |= SECURITY_INFORMATION.GROUP_SECURITY_INFORMATION; } } if (!Utils.IsNullOrWhiteSpace(pathLp)) { // SetNamedSecurityInfo() // 2013-01-13: MSDN does not confirm LongPath usage but a Unicode version of this function exists. lastError = (int)Security.NativeMethods.SetNamedSecurityInfo(pathLp, SE_OBJECT_TYPE.SE_FILE_OBJECT, securityInfo, pOwner, pGroup, pDacl, pSacl); if (lastError != Win32Errors.ERROR_SUCCESS) { NativeError.ThrowException(lastError, pathLp); } } else { if (NativeMethods.IsValidHandle(handle)) { lastError = (int)Security.NativeMethods.SetSecurityInfo(handle, SE_OBJECT_TYPE.SE_FILE_OBJECT, securityInfo, pOwner, pGroup, pDacl, pSacl); if (lastError != Win32Errors.ERROR_SUCCESS) { NativeError.ThrowException(lastError); } } } } finally { if (null != privilegeEnabler) { privilegeEnabler.Dispose(); } } } }
internal static SafeFileHandle CreateFileCore(KernelTransaction transaction, string path, ExtendedFileAttributes attributes, FileSecurity fileSecurity, FileMode fileMode, FileSystemRights fileSystemRights, FileShare fileShare, bool checkPath, PathFormat pathFormat) { if (checkPath && pathFormat == PathFormat.RelativePath) { Path.CheckSupportedPathFormat(path, true, true); } // When isFile == null, we're working with a device. // When opening a VOLUME or removable media drive (for example, a floppy disk drive or flash memory thumb drive), // the path string should be the following form: "\\.\X:" // Do not use a trailing backslash (\), which indicates the root. var pathLp = Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.TrimEnd | GetFullPathOptions.RemoveTrailingDirectorySeparator); PrivilegeEnabler privilegeEnabler = null; var isAppend = fileMode == FileMode.Append; // CreateFileXxx() does not support FileMode.Append mode. if (isAppend) { fileMode = FileMode.OpenOrCreate; fileSystemRights &= FileSystemRights.AppendData; // Add right. } if (fileSecurity != null) { fileSystemRights |= (FileSystemRights)0x1000000; // Set right. } // AccessSystemSecurity = 0x1000000 AccessSystemAcl access type. // MaximumAllowed = 0x2000000 MaximumAllowed access type. if ((fileSystemRights & (FileSystemRights)0x1000000) != 0 || (fileSystemRights & (FileSystemRights)0x2000000) != 0) { privilegeEnabler = new PrivilegeEnabler(Privilege.Security); } using (privilegeEnabler) using (var securityAttributes = new Security.NativeMethods.SecurityAttributes(fileSecurity)) { var handle = transaction == null || !NativeMethods.IsAtLeastWindowsVista // CreateFile() / CreateFileTransacted() // In the ANSI version of this function, the name is limited to MAX_PATH characters. // To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path. // 2013-01-13: MSDN confirms LongPath usage. ? NativeMethods.CreateFile(pathLp, fileSystemRights, fileShare, securityAttributes, fileMode, attributes, IntPtr.Zero) : NativeMethods.CreateFileTransacted(pathLp, fileSystemRights, fileShare, securityAttributes, fileMode, attributes, IntPtr.Zero, transaction.SafeHandle, IntPtr.Zero, IntPtr.Zero); var lastError = Marshal.GetLastWin32Error(); if (handle.IsInvalid) { handle.Close(); NativeError.ThrowException(lastError, pathLp); } if (isAppend) { var stream = new FileStream(handle, FileAccess.Write, NativeMethods.DefaultFileBufferSize, (attributes & ExtendedFileAttributes.Overlapped) != 0); stream.Seek(0, SeekOrigin.End); } return(handle); } }
public AppCompatCache(string filename, int controlSet, bool noLogs) { byte[] rawBytes = null; Caches = new List <IAppCompatCache>(); var controlSetIds = new List <int>(); RegistryKey subKey = null; var isLiveRegistry = string.IsNullOrEmpty(filename); if (isLiveRegistry) { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { throw new NotSupportedException("Live Registry support is not supported on non-Windows platforms."); } var keyCurrUser = Microsoft.Win32.Registry.LocalMachine; var subKey2 = keyCurrUser.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatCache"); if (subKey2 == null) { subKey2 = keyCurrUser.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatibility"); if (subKey2 == null) { Console.WriteLine( @"'CurrentControlSet\Control\Session Manager\AppCompatCache' key not found! Exiting"); return; } } rawBytes = (byte[])subKey2.GetValue("AppCompatCache", null); subKey2 = keyCurrUser.OpenSubKey(@"SYSTEM\Select"); ControlSet = (int)subKey2.GetValue("Current"); var is32Bit = Is32Bit(filename, null); var cache = Init(rawBytes, is32Bit, ControlSet); Caches.Add(cache); return; } RegistryHive reg; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { Privilege[] privileges = { Privilege.EnableDelegation, Privilege.Impersonate, Privilege.Tcb }; using var enabler = new PrivilegeEnabler(Privilege.Backup, privileges); } ControlSet = controlSet; if (File.Exists(filename) == false && Helper.RawFileExists(filename) == false) { throw new FileNotFoundException($"File not found ({filename})!"); } var dirname = Path.GetDirectoryName(Path.GetFullPath(filename)); var hiveBase = Path.GetFileName(filename); List <RawCopyReturn> rawFiles = null; try { reg = new RegistryHive(filename) { RecoverDeleted = true }; } catch (IOException) { //file is in use if (Helper.IsAdministrator() == false) { throw new UnauthorizedAccessException("Administrator privileges not found!"); } Log.Warning("'{Filename}' is in use. Rerouting...", filename); var files = new List <string>(); files.Add(filename); var logFiles = Directory.GetFiles(dirname, $"{hiveBase}.LOG?").ToList(); var log1 = $"{dirname}\\{hiveBase}.LOG1"; var log2 = $"{dirname}\\{hiveBase}.LOG2"; if (logFiles.Count == 0) { if (Helper.RawFileExists(log1)) { logFiles.Add(log1); } if (Helper.RawFileExists(log2)) { logFiles.Add(log2); } } foreach (var logFile in logFiles) { files.Add(logFile); } rawFiles = Helper.GetRawFiles(files); var b = new byte[rawFiles.First().FileStream.Length]; rawFiles.First().FileStream.Read(b, 0, (int)rawFiles.First().FileStream.Length); reg = new RegistryHive(b, rawFiles.First().InputFilename); } if (reg.Header.PrimarySequenceNumber != reg.Header.SecondarySequenceNumber) { if (string.IsNullOrEmpty(dirname)) { dirname = "."; } var logFiles = Directory.GetFiles(dirname, $"{hiveBase}.LOG?").ToList(); var log1 = $"{dirname}\\{hiveBase}.LOG1"; var log2 = $"{dirname}\\{hiveBase}.LOG2"; if (logFiles.Count == 0) { if (File.Exists(log1)) { logFiles.Add(log1); } if (File.Exists(log2)) { logFiles.Add(log2); } } if (logFiles.Count == 0) { if (Helper.IsAdministrator()) { if (Helper.RawFileExists(log1)) { logFiles.Add(log1); } if (Helper.RawFileExists(log2)) { logFiles.Add(log2); } } else { Log.Fatal("Log files not found and no administrator access to look for them!"); } } if (logFiles.Count == 0) { if (noLogs == false) { Log.Warning( "Registry hive is dirty and no transaction logs were found in the same directory! LOGs should have same base name as the hive. Aborting!!"); throw new Exception( "Sequence numbers do not match and transaction logs were not found in the same directory as the hive. Aborting"); } Log.Warning( "Registry hive is dirty and no transaction logs were found in the same directory. Data may be missing! Continuing anyways..."); } else { if (noLogs == false) { if (rawFiles != null) { var lt = new List <TransactionLogFileInfo>(); foreach (var rawCopyReturn in rawFiles.Skip(1).ToList()) { var b = new byte[rawCopyReturn.FileStream.Length]; var tt = new TransactionLogFileInfo(rawCopyReturn.InputFilename, b); lt.Add(tt); } reg.ProcessTransactionLogs(lt, true); } else { reg.ProcessTransactionLogs(logFiles.ToList(), true); } } else { Log.Warning( "Registry hive is dirty and transaction logs were found in the same directory, but --nl was provided. Data may be missing! Continuing anyways..."); } } } reg.ParseHive(); if (controlSet == -1) { for (var i = 0; i < 10; i++) { subKey = reg.GetKey($@"ControlSet00{i}\Control\Session Manager\AppCompatCache"); if (subKey == null) { subKey = reg.GetKey($@"ControlSet00{i}\Control\Session Manager\AppCompatibility"); } if (subKey != null) { controlSetIds.Add(i); } } if (controlSetIds.Count > 1) { Log.Warning( "***The following ControlSet00x keys will be exported: {Cs}. Use -c to process keys individually", string.Join(",", controlSetIds)); } } else { //a control set was passed in subKey = reg.GetKey($@"ControlSet00{ControlSet}\Control\Session Manager\AppCompatCache"); if (subKey == null) { subKey = reg.GetKey($@"ControlSet00{ControlSet}\Control\Session Manager\AppCompatibility"); } if (subKey == null) { throw new Exception($"Could not find ControlSet00{ControlSet}. Exiting"); } controlSetIds.Add(ControlSet); } var is32 = Is32Bit(filename, reg); Log.Debug("**** Found {Count} ids to process", controlSetIds.Count); foreach (var id in controlSetIds) { Log.Debug("**** Processing id {Id}", id); // var hive2 = new RegistryHiveOnDemand(filename); subKey = reg.GetKey($@"ControlSet00{id}\Control\Session Manager\AppCompatCache"); if (subKey == null) { Log.Debug("**** Initial subkey null, getting appCompatability key"); subKey = reg.GetKey($@"ControlSet00{id}\Control\Session Manager\AppCompatibility"); } Log.Debug("**** Looking for AppCompatcache value"); var val = subKey?.Values.SingleOrDefault(c => c.ValueName == "AppCompatCache"); if (val != null) { Log.Debug("**** Found AppCompatcache value"); rawBytes = val.ValueDataRaw; } if (rawBytes == null) { Log.Error("'AppCompatCache' value not found for 'ControlSet00{Id}'! Exiting", id); } var cache = Init(rawBytes, is32, id); Caches.Add(cache); } }
internal static void SetAccessControlCore(string path, SafeFileHandle handle, ObjectSecurity objectSecurity, AccessControlSections includeSections, PathFormat pathFormat) { if (pathFormat == PathFormat.RelativePath) { Path.CheckSupportedPathFormat(path, true, true); } if (objectSecurity == null) { throw new ArgumentNullException("objectSecurity"); } byte[] managedDescriptor = objectSecurity.GetSecurityDescriptorBinaryForm(); using (var safeBuffer = new SafeGlobalMemoryBufferHandle(managedDescriptor.Length)) { string pathLp = Path.GetExtendedLengthPathCore(null, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.CheckInvalidPathChars); safeBuffer.CopyFrom(managedDescriptor, 0, managedDescriptor.Length); SecurityDescriptorControl control; uint revision; if (!Security.NativeMethods.GetSecurityDescriptorControl(safeBuffer, out control, out revision)) { NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp); } PrivilegeEnabler privilegeEnabler = null; try { var securityInfo = SecurityInformation.None; IntPtr pDacl = IntPtr.Zero; if ((includeSections & AccessControlSections.Access) != 0) { bool daclDefaulted, daclPresent; if (!Security.NativeMethods.GetSecurityDescriptorDacl(safeBuffer, out daclPresent, out pDacl, out daclDefaulted)) { NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp); } if (daclPresent) { securityInfo |= SecurityInformation.Dacl; securityInfo |= (control & SecurityDescriptorControl.DaclProtected) != 0 ? SecurityInformation.ProtectedDacl : SecurityInformation.UnprotectedDacl; } } IntPtr pSacl = IntPtr.Zero; if ((includeSections & AccessControlSections.Audit) != 0) { bool saclDefaulted, saclPresent; if (!Security.NativeMethods.GetSecurityDescriptorSacl(safeBuffer, out saclPresent, out pSacl, out saclDefaulted)) { NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp); } if (saclPresent) { securityInfo |= SecurityInformation.Sacl; securityInfo |= (control & SecurityDescriptorControl.SaclProtected) != 0 ? SecurityInformation.ProtectedSacl : SecurityInformation.UnprotectedSacl; privilegeEnabler = new PrivilegeEnabler(Privilege.Security); } } IntPtr pOwner = IntPtr.Zero; if ((includeSections & AccessControlSections.Owner) != 0) { bool ownerDefaulted; if (!Security.NativeMethods.GetSecurityDescriptorOwner(safeBuffer, out pOwner, out ownerDefaulted)) { NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp); } if (pOwner != IntPtr.Zero) { securityInfo |= SecurityInformation.Owner; } } IntPtr pGroup = IntPtr.Zero; if ((includeSections & AccessControlSections.Group) != 0) { bool groupDefaulted; if (!Security.NativeMethods.GetSecurityDescriptorGroup(safeBuffer, out pGroup, out groupDefaulted)) { NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp); } if (pGroup != IntPtr.Zero) { securityInfo |= SecurityInformation.Group; } } uint lastError; if (!Utils.IsNullOrWhiteSpace(pathLp)) { // SetNamedSecurityInfo() // In the ANSI version of this function, the name is limited to MAX_PATH characters. // To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path. // 2013-01-13: MSDN does not confirm LongPath usage but a Unicode version of this function exists. lastError = Security.NativeMethods.SetNamedSecurityInfo(pathLp, ObjectType.FileObject, securityInfo, pOwner, pGroup, pDacl, pSacl); if (lastError != Win32Errors.ERROR_SUCCESS) { NativeError.ThrowException(lastError, pathLp); } } else { if (NativeMethods.IsValidHandle(handle)) { lastError = Security.NativeMethods.SetSecurityInfo(handle, ObjectType.FileObject, securityInfo, pOwner, pGroup, pDacl, pSacl); if (lastError != Win32Errors.ERROR_SUCCESS) { NativeError.ThrowException((int)lastError); } } } } finally { if (privilegeEnabler != null) { privilegeEnabler.Dispose(); } } } }
private static List <string> GetRecycleBinFiles(string dir) { var files = new List <string>(); #if NET6_0 var enumerationOptions = new EnumerationOptions { IgnoreInaccessible = true, MatchCasing = MatchCasing.CaseSensitive, RecurseSubdirectories = true, AttributesToSkip = 0 }; var files2 = Directory.EnumerateFileSystemEntries(dir, "$I*", enumerationOptions); files.AddRange(files2); files2 = Directory.EnumerateFileSystemEntries(dir, "INFO2", enumerationOptions); files.AddRange(files2); #elif NET462 Privilege[] privs = { Privilege.EnableDelegation, Privilege.Impersonate, Privilege.Tcb }; using var enabler = new PrivilegeEnabler(Privilege.Backup, privs); var filters = new DirectoryEnumerationFilters { // Used to abort the enumeration. // CancellationToken = cancelSource.Token, // Filter to decide whether to recurse into subdirectories. RecursionFilter = entryInfo => { if (!entryInfo.IsMountPoint && !entryInfo.IsSymbolicLink) { return(true); } return(false); }, // Filter to process Exception handling. ErrorFilter = delegate(int errorCode, string errorMessage, string pathProcessed) { Log.Error("Error accessing {PathProcessed}. Error: {ErrorMessage}", pathProcessed, errorCode); // Return true to continue, false to throw the Exception. return(true); }, // Filter to in-/exclude file system entries during the enumeration. InclusionFilter = entryInfo => { if (entryInfo.FileName == "INFO2" || entryInfo.FileName.StartsWith("$I")) { Log.Debug("Found match: {FullPath}", entryInfo.FullPath); return(true); } return(false); } }; var dirEnumOptions = DirectoryEnumerationOptions.Files | DirectoryEnumerationOptions.Recursive | DirectoryEnumerationOptions.ContinueOnException | DirectoryEnumerationOptions.SkipReparsePoints; files.AddRange(Directory.EnumerateFileSystemEntryInfos <string>(dir, dirEnumOptions, filters).Where(File.Exists)); #endif return(files); }
internal static T GetAccessControlInternal<T>(bool isFolder, string path, AccessControlSections includeSections, PathFormat pathFormat) { SecurityInformation securityInfo = 0; PrivilegeEnabler privilegeEnabler = null; if ((includeSections & AccessControlSections.Access) != 0) securityInfo |= SecurityInformation.Dacl; if ((includeSections & AccessControlSections.Group) != 0) securityInfo |= SecurityInformation.Group; if ((includeSections & AccessControlSections.Owner) != 0) securityInfo |= SecurityInformation.Owner; if ((includeSections & AccessControlSections.Audit) != 0) { // We need the SE_SECURITY_NAME privilege enabled to be able to get the // SACL descriptor. So we enable it here for the remainder of this function. privilegeEnabler = new PrivilegeEnabler(Privilege.Security); securityInfo |= SecurityInformation.Sacl; } using (privilegeEnabler) { string pathLp = Path.GetExtendedLengthPathInternal(null, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck); IntPtr pSidOwner, pSidGroup, pDacl, pSacl; SafeGlobalMemoryBufferHandle pSecurityDescriptor; ObjectSecurity objectSecurity; uint lastError = Security.NativeMethods.GetNamedSecurityInfo(pathLp, ObjectType.FileObject, securityInfo, out pSidOwner, out pSidGroup, out pDacl, out pSacl, out pSecurityDescriptor); try { if (lastError == Win32Errors.ERROR_FILE_NOT_FOUND || lastError == Win32Errors.ERROR_PATH_NOT_FOUND) lastError = (isFolder ? Win32Errors.ERROR_PATH_NOT_FOUND : Win32Errors.ERROR_FILE_NOT_FOUND); // If the function fails, the return value is zero. if (lastError != Win32Errors.ERROR_SUCCESS) NativeError.ThrowException(lastError, pathLp); if (!NativeMethods.IsValidHandle(pSecurityDescriptor, false)) throw new IOException(Resources.InvalidSecurityDescriptorReturnedFromSystem); uint length = Security.NativeMethods.GetSecurityDescriptorLength(pSecurityDescriptor); // Seems not to work: Method .CopyTo: length > Capacity, so an Exception is thrown. //byte[] managedBuffer = new byte[length]; //pSecurityDescriptor.CopyTo(managedBuffer, 0, (int) length); byte[] managedBuffer = pSecurityDescriptor.ToByteArray(0, (int)length); objectSecurity = (isFolder) ? (ObjectSecurity)new DirectorySecurity() : new FileSecurity(); objectSecurity.SetSecurityDescriptorBinaryForm(managedBuffer); } finally { if (pSecurityDescriptor != null) pSecurityDescriptor.Close(); } return (T)(object)objectSecurity; } }
internal static SafeFileHandle CreateFileInternal(KernelTransaction transaction, string path, ExtendedFileAttributes attributes, FileSecurity fileSecurity, FileMode fileMode, FileSystemRights fileSystemRights, FileShare fileShare, bool checkPath, PathFormat pathFormat) { if (checkPath && pathFormat == PathFormat.RelativePath) { Path.CheckValidPath(path, true, true); } // When isFile == null, we're working with a device. // When opening a VOLUME or removable media drive (for example, a floppy disk drive or flash memory thumb drive), // the path string should be the following form: "\\.\X:" // Do not use a trailing backslash (\), which indicates the root. string pathLp = Path.GetExtendedLengthPathInternal(transaction, path, pathFormat, GetFullPathOptions.TrimEnd | GetFullPathOptions.RemoveTrailingDirectorySeparator); PrivilegeEnabler privilegeEnabler = null; try { if (fileSecurity != null) { fileSystemRights |= (FileSystemRights)0x1000000; } // AccessSystemSecurity = 0x1000000 AccessSystemAcl access type. // MaximumAllowed = 0x2000000 MaximumAllowed access type. if ((fileSystemRights & (FileSystemRights)0x1000000) != 0 || (fileSystemRights & (FileSystemRights)0x2000000) != 0) { privilegeEnabler = new PrivilegeEnabler(Privilege.Security); } using (var securityAttributes = new Security.NativeMethods.SecurityAttributes(fileSecurity)) { SafeFileHandle handle = transaction == null || !NativeMethods.IsAtLeastWindowsVista // CreateFile() / CreateFileTransacted() // In the ANSI version of this function, the name is limited to MAX_PATH characters. // To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path. // 2013-01-13: MSDN confirms LongPath usage. ? NativeMethods.CreateFile(pathLp, fileSystemRights, fileShare, securityAttributes, fileMode, attributes, IntPtr.Zero) : NativeMethods.CreateFileTransacted(pathLp, fileSystemRights, fileShare, securityAttributes, fileMode, attributes, IntPtr.Zero, transaction.SafeHandle, IntPtr.Zero, IntPtr.Zero); int lastError = Marshal.GetLastWin32Error(); if (handle.IsInvalid) { handle.Close(); NativeError.ThrowException(lastError, pathLp); } return(handle); } } finally { if (privilegeEnabler != null) { privilegeEnabler.Dispose(); } } }