public void AclInheritance() { NtfsFileSystem ntfs = FileSystemSource.NtfsFileSystem(); RawSecurityDescriptor sd = new RawSecurityDescriptor("O:BAG:BAD:(A;OICINP;GA;;;BA)"); ntfs.CreateDirectory("dir"); ntfs.SetSecurity("dir", sd); ntfs.CreateDirectory(@"dir\subdir"); RawSecurityDescriptor inheritedSd = ntfs.GetSecurity(@"dir\subdir"); Assert.NotNull(inheritedSd); Assert.Equal("O:BAG:BAD:(A;ID;GA;;;BA)", inheritedSd.GetSddlForm(AccessControlSections.All)); using (ntfs.OpenFile(@"dir\subdir\file", FileMode.Create, FileAccess.ReadWrite)) { } inheritedSd = ntfs.GetSecurity(@"dir\subdir\file"); Assert.NotNull(inheritedSd); Assert.Equal("O:BAG:BAD:", inheritedSd.GetSddlForm(AccessControlSections.All)); }
private void CopyFile(NtfsFileSystem sourceNtfs, NtfsFileSystem destNtfs, string path) { if (IsExcluded(path)) { return; } using (Stream s = sourceNtfs.OpenFile(path, FileMode.Open, FileAccess.Read)) using (Stream d = destNtfs.OpenFile(path, FileMode.Create, FileAccess.ReadWrite)) { d.SetLength(s.Length); int numRead = s.Read(_copyBuffer, 0, _copyBuffer.Length); while (numRead > 0) { d.Write(_copyBuffer, 0, numRead); numRead = s.Read(_copyBuffer, 0, _copyBuffer.Length); } } destNtfs.SetSecurity(path, sourceNtfs.GetSecurity(path)); destNtfs.SetFileStandardInformation(path, sourceNtfs.GetFileStandardInformation(path)); }
private static void DoNtfsSecurityComparison(int partition, NtfsFileSystem leftFileSystem, DiscFileInfo left, NtfsFileSystem rightFileSystem, DiscFileInfo right) { var leftEntry = leftFileSystem.GetDirectoryEntry(left.FullName); var leftRef = leftFileSystem.GetFile(leftEntry.Reference); var rightEntry = rightFileSystem.GetDirectoryEntry(right.FullName); var rightRef = rightFileSystem.GetFile(rightEntry.Reference); Info("Partition{0}:{1}: Comparing NTFS meta data", partition, left.FullName); // Disable these checks there are problems with the short names DiscUtils assigns /* // hard links * DoingCheck(); * var leftRefHardLinkCount = leftRef.HardLinkCount; * if (leftRef.HasWin32OrDosName) * leftRefHardLinkCount--; // remove the legacy short name * * var rightRefHardLinkCount = rightRef.HardLinkCount; * if (rightRef.HasWin32OrDosName) * rightRefHardLinkCount--; // remove the legacy short name * * if (leftRefHardLinkCount != rightRefHardLinkCount) * { * Error("Partition{0}:{1}: Non-matching hard link count" + * "(Left: {2}, Right: {3})", * partition, left.FullName, leftRefHardLinkCount, rightRefHardLinkCount); * } * * // file names * DoingCheck(); * var leftRefNamesCount = leftRef.Names.Count; * if (leftRef.HasWin32OrDosName) * leftRefNamesCount--; // remove the legacy short name * * var rightRefNamesCount = rightRef.Names.Count; * if (rightRef.HasWin32OrDosName) * rightRefNamesCount--; // remove the legacy short name * * if (leftRefNamesCount != rightRefNamesCount) * { * Error("Partition{0}:{1}: Non-matching file names count" + * "(Left: {2}, Right: {3})", * partition, left.FullName, leftRefNamesCount, rightRefNamesCount); * } */ // security var leftSecurity = leftFileSystem.GetSecurity(left.FullName); var rightSecurity = rightFileSystem.GetSecurity(right.FullName); DoingCheck(); if (leftSecurity.BinaryLength != rightSecurity.BinaryLength) { Error("Partition{0}:{1}: Non-matching security binary length" + "(Left: 0x{2:X}, Right: 0x{3:X})", partition, left.FullName, leftSecurity.BinaryLength, rightSecurity.BinaryLength); } DoingCheck(); if (leftSecurity.ControlFlags != rightSecurity.ControlFlags) { Error("Partition{0}:{1}: Non-matching security control flags" + "(Left: 0x{2:X}, Right: 0x{3:X})", partition, left.FullName, leftSecurity.ControlFlags, rightSecurity.ControlFlags); } DoingCheck(); if (leftSecurity.Group != null && rightSecurity.Group != null) { if (leftSecurity.Group.Value != rightSecurity.Group.Value) { Error("Partition{0}:{1}: Non-matching security group name" + "(Left: {2}, Right: {3})", partition, left.FullName, leftSecurity.Group.Value, rightSecurity.Group.Value); } } else if ((leftSecurity.Group == null && rightSecurity.Group != null) || (leftSecurity.Group != null && rightSecurity.Owner == null)) { Warning("Partition{0}:{1}: No valid NTFS security group found", partition, left.FullName); } DoingCheck(); if (leftSecurity.Owner != null && rightSecurity.Owner != null) { if (leftSecurity.Owner.Value != rightSecurity.Owner.Value) { Error("Partition{0}:{1}: Non-matching security owner name" + "(Left: {2}, Right: {3})", partition, left.FullName, leftSecurity.Group.Value, rightSecurity.Group.Value); } } else if ((leftSecurity.Owner == null && rightSecurity.Owner != null) || (leftSecurity.Owner != null && rightSecurity.Owner == null)) { Warning("Partition{0}:{1}: No valid NTFS security owner found", partition, left.FullName); } DoingCheck(); if (leftSecurity.DiscretionaryAcl != null && rightSecurity.DiscretionaryAcl != null) { if (leftSecurity.DiscretionaryAcl.Count != rightSecurity.DiscretionaryAcl.Count) { Error("Partition{0}:{1}: Non-matching count of Discretionary ACL entries" + "(Left: {2}, Right: {3})", partition, left.FullName, leftSecurity.DiscretionaryAcl.Count, rightSecurity.DiscretionaryAcl.Count); } } else if ((leftSecurity.DiscretionaryAcl == null && rightSecurity.DiscretionaryAcl != null) || (leftSecurity.DiscretionaryAcl != null && rightSecurity.DiscretionaryAcl == null)) { Warning("Partition{0}:{1}: No valid NTFS security Discretionary ACL found", partition, left.FullName); } DoingCheck(); if (leftSecurity.SystemAcl != null && rightSecurity.SystemAcl != null) { if (leftSecurity.SystemAcl.Count != rightSecurity.SystemAcl.Count) { Error("Partition{0}:{1}: Non-matching count of System ACL entries" + "(Left: {2}, Right: {3})", partition, left.FullName, leftSecurity.DiscretionaryAcl.Count, rightSecurity.DiscretionaryAcl.Count); } } else if ((leftSecurity.SystemAcl == null && rightSecurity.SystemAcl != null) || (leftSecurity.SystemAcl != null && rightSecurity.SystemAcl == null)) { Warning("Partition{0}:{1}: No valid NTFS security System ACL found", partition, left.FullName); } }
protected override void DoRun() { if (DiskSize <= 0) { DisplayHelp(); return; } using (VirtualDisk sourceDisk = VirtualDisk.OpenDisk(_sourceFile.Value, FileAccess.Read, UserName, Password)) using (VirtualDisk destDisk = VirtualDisk.CreateDisk(OutputDiskType, OutputDiskVariant, _destFile.Value, DiskParameters, UserName, Password)) { if (destDisk is DiscUtils.Vhd.Disk) { ((DiscUtils.Vhd.Disk)destDisk).AutoCommitFooter = false; } // Copy the MBR from the source disk, and invent a new signature for this new disk destDisk.SetMasterBootRecord(sourceDisk.GetMasterBootRecord()); destDisk.Signature = new Random().Next(); SparseStream sourcePartStream = SparseStream.FromStream(sourceDisk.Partitions[0].Open(), Ownership.None); NtfsFileSystem sourceNtfs = new NtfsFileSystem(sourcePartStream); // Copy the OS boot code into memory, so we can apply it when formatting the new disk byte[] bootCode; using (Stream bootStream = sourceNtfs.OpenFile("$Boot", FileMode.Open, FileAccess.Read)) { bootCode = new byte[bootStream.Length]; int totalRead = 0; while (totalRead < bootCode.Length) { totalRead += bootStream.Read(bootCode, totalRead, bootCode.Length - totalRead); } } // Partition the new disk with a single NTFS partition BiosPartitionTable.Initialize(destDisk, WellKnownPartitionType.WindowsNtfs); VolumeManager volMgr = new VolumeManager(destDisk); string label = _labelSwitch.IsPresent ? _labelSwitch.Value : sourceNtfs.VolumeLabel; using (NtfsFileSystem destNtfs = NtfsFileSystem.Format(volMgr.GetLogicalVolumes()[0], label, bootCode)) { destNtfs.SetSecurity(@"\", sourceNtfs.GetSecurity(@"\")); destNtfs.NtfsOptions.ShortNameCreation = ShortFileNameOption.Disabled; sourceNtfs.NtfsOptions.HideHiddenFiles = false; sourceNtfs.NtfsOptions.HideSystemFiles = false; CopyFiles(sourceNtfs, destNtfs, @"\", true); if (destNtfs.FileExists(@"\boot\BCD")) { // Force all boot entries in the BCD to point to the newly created NTFS partition - does _not_ cope with // complex multi-volume / multi-boot scenarios at all. using (Stream bcdStream = destNtfs.OpenFile(@"\boot\BCD", FileMode.Open, FileAccess.ReadWrite)) { using (RegistryHive hive = new RegistryHive(bcdStream)) { Store store = new Store(hive.Root); foreach (var obj in store.Objects) { foreach (var elem in obj.Elements) { if (elem.Format == DiscUtils.BootConfig.ElementFormat.Device) { elem.Value = DiscUtils.BootConfig.ElementValue.ForDevice(elem.Value.ParentObject, volMgr.GetPhysicalVolumes()[0]); } } } } } } } } }
private void CopyFiles(NtfsFileSystem sourceNtfs, NtfsFileSystem destNtfs, string path, bool subs) { if (subs) { foreach (var dir in sourceNtfs.GetDirectories(path)) { if (!IsExcluded(dir)) { int hardLinksRemaining = sourceNtfs.GetHardLinkCount(dir) - 1; bool newDir = false; long sourceFileId = sourceNtfs.GetFileId(dir); string refPath; if (_uniqueFiles.TryGetValue(sourceFileId, out refPath)) { // If this is another name for a known dir, recreate the hard link destNtfs.CreateHardLink(refPath, dir); } else { destNtfs.CreateDirectory(dir); newDir = true; FileAttributes fileAttrs = sourceNtfs.GetAttributes(dir); if ((fileAttrs & FileAttributes.ReparsePoint) != 0) { destNtfs.SetReparsePoint(dir, sourceNtfs.GetReparsePoint(dir)); } destNtfs.SetAttributes(dir, fileAttrs); destNtfs.SetSecurity(dir, sourceNtfs.GetSecurity(dir)); } // File may have a short name string shortName = sourceNtfs.GetShortName(dir); if (!string.IsNullOrEmpty(shortName) && shortName != dir) { destNtfs.SetShortName(dir, shortName); --hardLinksRemaining; } if (newDir) { if (hardLinksRemaining > 0) { _uniqueFiles[sourceFileId] = dir; } CopyFiles(sourceNtfs, destNtfs, dir, subs); } // Set standard information last (includes modification timestamps) destNtfs.SetFileStandardInformation(dir, sourceNtfs.GetFileStandardInformation(dir)); } } } foreach (var file in sourceNtfs.GetFiles(path)) { Console.WriteLine(file); int hardLinksRemaining = sourceNtfs.GetHardLinkCount(file) - 1; long sourceFileId = sourceNtfs.GetFileId(file); string refPath; if (_uniqueFiles.TryGetValue(sourceFileId, out refPath)) { // If this is another name for a known file, recreate the hard link destNtfs.CreateHardLink(refPath, file); } else { CopyFile(sourceNtfs, destNtfs, file); if (hardLinksRemaining > 0) { _uniqueFiles[sourceFileId] = file; } } // File may have a short name string shortName = sourceNtfs.GetShortName(file); if (!string.IsNullOrEmpty(shortName) && shortName != file) { destNtfs.SetShortName(file, shortName); } } }