public void ProblemsWithLocation_FolderReadOnly_Fails() { using (var tempFolder = new TemporaryFolder(MethodBase.GetCurrentMethod().Name)) { if (SIL.PlatformUtilities.Platform.IsWindows) { var di = new DirectoryInfo(tempFolder.FolderPath); var directorySecurity = di.GetAccessControl(); var currentUserIdentity = WindowsIdentity.GetCurrent(); var fileSystemRule = new FileSystemAccessRule(currentUserIdentity.Name, FileSystemRights.Write, InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, PropagationFlags.None, AccessControlType.Deny); directorySecurity.AddAccessRule(fileSystemRule); di.SetAccessControl(directorySecurity); Assert.That(_api.ProblemsWithLocation(tempFolder.FolderPath), Contains.Substring("Bloom does not have permission to write to the selected folder")); directorySecurity.RemoveAccessRule(fileSystemRule); di.SetAccessControl(directorySecurity); } else { var udi = new Mono.Unix.UnixDirectoryInfo(tempFolder.FolderPath); var permissions = udi.FileAccessPermissions; udi.FileAccessPermissions = Mono.Unix.FileAccessPermissions.UserRead | Mono.Unix.FileAccessPermissions.GroupRead | Mono.Unix.FileAccessPermissions.OtherRead; Assert.That(_api.ProblemsWithLocation(tempFolder.FolderPath), Contains.Substring("Bloom does not have permission to write to the selected folder")); udi.FileAccessPermissions = permissions; } } }
/// <summary> /// Gets the sysfs partitions. /// </summary> /// <returns> /// The sysfs partitions. /// </returns> /// <param name='diskPath'> /// Disk path. (eg /sys/devices/virtual/block/loop0) /// </param> /// <param name='diskName'> /// Disk name. (eg loop0) /// </param> internal List <Partition> GetSysfsPartitions(string diskPath, string diskName) { List <Partition> parts = new List <Partition>(); Mono.Unix.UnixDirectoryInfo diskDir = new Mono.Unix.UnixDirectoryInfo(diskPath); foreach (Mono.Unix.Native.Dirent part in diskDir.GetEntries(diskName + ".*")) { Partition p = new Partition(); p.Path = "/dev/" + part.d_name; p.Offset = ulong.Parse(File.ReadAllText(diskPath + "/" + part.d_name + "/start")); p.Size = long.Parse(File.ReadAllText(diskPath + "/" + part.d_name + "/size")); parts.Add(p); } return(parts); }
/// <summary> /// returns the partition name (sdX format) from any by-xxxx value (by-path, by-uuid...) /// </summary> /// <param name='partitionName'> /// Partition name. /// </param>/ private string GetPartitionFromPathOrUuid(string partitionName) { string[] disksBy = new string[] { "by-uuid", "by-path", "by-label", "by-id" }; foreach (string byType in disksBy) { Mono.Unix.UnixDirectoryInfo byUuidParts = new Mono.Unix.UnixDirectoryInfo("/dev/disk/" + byType); foreach (Mono.Unix.Native.Dirent d in byUuidParts.GetEntries()) { //Console.WriteLine ("______GetPartitionFromPathOrUuid looking cur entry="+d.d_name+", type="+d.d_type); if (d.d_type == 10 /*Mono.Unix.FileTypes.SymbolicLink*/) { string partOnlyName = ""; if (partitionName.LastIndexOf("/") >= 0) { partOnlyName = partitionName.Substring(partitionName.LastIndexOf("/") + 1); } else if (partitionName.IndexOf("UUID=") == 0) { partOnlyName = partitionName.Replace("UUID=", ""); } else { partOnlyName = partitionName; } //Console.WriteLine ("______GetPartitionFromPathOrUuid :d_name="+d.d_name+", partonlyname="+partOnlyName); if (d.d_name == partOnlyName) { Mono.Unix.UnixSymbolicLinkInfo devLink = new Mono.Unix.UnixSymbolicLinkInfo(byUuidParts + "/" + d.d_name); //Console.WriteLine ("______GetPartitionFromPathOrUuid : "+partitionName+" --> /dev/"+devLink.ContentsPath.Substring(devLink.ContentsPath.LastIndexOf('/')+1)); return("/dev/" + devLink.ContentsPath.Substring(devLink.ContentsPath.LastIndexOf('/') + 1)); } } } } // partition was probably referenced by its devics (/dev/sdXX) path, nothing to do return(partitionName); }
public static string GetPathDetails(FileSystemInfo fs, string name) { string pathname = fs.FullName; #if !__MonoCS__ bool isDir = Directory.Exists(pathname); #else bool isDir = (fs.Attributes & System.IO.FileAttributes.Directory) != 0; #endif char d = isDir ? 'd' : '-'; string last = fs.LastWriteTime.ToString("MMM dd yyyy HH:mm"); string user = string.Empty; string group = string.Empty; string links = null; string permissions = "rwx"; long size = 0; #if __MonoCS__ Mono.Unix.UnixFileSystemInfo info; if (isDir) { info = new Mono.Unix.UnixDirectoryInfo(pathname); } else { info = new Mono.Unix.UnixFileInfo(pathname); } char ur = (info.FileAccessPermissions & Mono.Unix.FileAccessPermissions.UserRead) != 0 ? 'r' : '-'; char uw = (info.FileAccessPermissions & Mono.Unix.FileAccessPermissions.UserWrite) != 0 ? 'w' : '-'; char ux = (info.FileAccessPermissions & Mono.Unix.FileAccessPermissions.UserExecute) != 0 ? 'x' : '-'; char gr = (info.FileAccessPermissions & Mono.Unix.FileAccessPermissions.GroupRead) != 0 ? 'r' : '-'; char gw = (info.FileAccessPermissions & Mono.Unix.FileAccessPermissions.GroupWrite) != 0 ? 'w' : '-'; char gx = (info.FileAccessPermissions & Mono.Unix.FileAccessPermissions.GroupExecute) != 0 ? 'x' : '-'; char or = (info.FileAccessPermissions & Mono.Unix.FileAccessPermissions.OtherRead) != 0 ? 'r' : '-'; char ow = (info.FileAccessPermissions & Mono.Unix.FileAccessPermissions.OtherWrite) != 0 ? 'w' : '-'; char ox = (info.FileAccessPermissions & Mono.Unix.FileAccessPermissions.OtherExecute) != 0 ? 'x' : '-'; permissions = string.Format("{0}{1}{2}{3}{4}{5}{6}{7}{8}", ur, uw, ux, gr, gw, gx, or, ow, ox); user = info.OwnerUser.UserName; group = info.OwnerGroup.GroupName; links = info.LinkCount.ToString(); size = info.Length; if (info.IsSymbolicLink) { d = 's'; } #else if (isDir) { user = Directory.GetAccessControl(fs.FullName).GetOwner( typeof(System.Security.Principal.NTAccount)).ToString(); DirectoryInfo di = fs as DirectoryInfo; size = di.GetFileSystemInfos().Length; } else { user = File.GetAccessControl(fs.FullName).GetOwner( typeof(System.Security.Principal.NTAccount)).ToString(); FileInfo fi = fs as FileInfo; size = fi.Length; string[] execs = new string[] { "exe", "bat", "msi" }; char x = execs.Contains(fi.Extension.ToLower()) ? 'x' : '-'; char w = !fi.IsReadOnly ? 'w' : '-'; permissions = string.Format("r{0}{1}", w, x); } #endif string data = string.Format("{0}{1} {2,4} {3,8} {4,8} {5,9} {6,23} {7}", d, permissions, links, user, group, size, last, name); return(data); }
public static string CollectFilePermissionInformation(string filePath) { var bldr = new StringBuilder(); try { if (SIL.PlatformUtilities.Platform.IsWindows) { var currentUser = System.Security.Principal.WindowsIdentity.GetCurrent(); bldr.AppendLine($"current user is {currentUser.Name}"); var principal = new System.Security.Principal.WindowsPrincipal(currentUser); bool isInRoleWithAccess = false; bool accessDenied = false; bool accessAllowed = false; System.Security.AccessControl.FileSystemRights accessRights = System.Security.AccessControl.FileSystemRights.Write; var acl = File.GetAccessControl(filePath); var rules = acl.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)); var sid = acl.GetOwner(typeof(System.Security.Principal.SecurityIdentifier)); var acct = sid.Translate(typeof(System.Security.Principal.NTAccount)) as System.Security.Principal.NTAccount; if (acct != null) { bldr.AppendLine($"owner of \"{filePath}\" is {acct.Value}"); } var fileAttributes = RobustFile.GetAttributes(filePath); bldr.AppendLine($"{filePath} current ReadOnly attribute of {filePath} is {(fileAttributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly}"); foreach (System.Security.AccessControl.AuthorizationRule rule in rules) { var fsAccessRule = rule as System.Security.AccessControl.FileSystemAccessRule; if (fsAccessRule == null) { continue; } if ((fsAccessRule.FileSystemRights & accessRights) > 0) { var ntAccount = rule.IdentityReference as System.Security.Principal.NTAccount; if (ntAccount == null) { continue; } if (principal.IsInRole(ntAccount.Value)) { if (fsAccessRule.AccessControlType == System.Security.AccessControl.AccessControlType.Deny) { bldr.AppendLine($"current user is denied write access to {filePath} by {ntAccount.Value}{(rule.IsInherited ? " (inherited)":"")}"); accessDenied = true; } if (fsAccessRule.AccessControlType == System.Security.AccessControl.AccessControlType.Allow) { bldr.AppendLine($"current user is allowed write access to {filePath} by {ntAccount.Value}{(rule.IsInherited ? " (inherited)":"")}"); accessAllowed = true; } isInRoleWithAccess = true; } } } if (isInRoleWithAccess) { if (!accessAllowed) { bldr.AppendLine($"current user is not explicitly allowed write access to {filePath}"); } if (!accessDenied) { bldr.AppendLine($"current user is not explicitly denied write access to {filePath}"); } } else { bldr.AppendLine($"current user is not explicitly given access to {filePath}"); } } else { var folder = Path.GetDirectoryName(filePath); var fileInfo = new Mono.Unix.UnixFileInfo(filePath); var dirInfo = new Mono.Unix.UnixDirectoryInfo(folder); var userInfo = Mono.Unix.UnixUserInfo.GetRealUser(); bldr.AppendLine($"current user is {userInfo.UserName}"); bldr.AppendLine($"owner of \"{filePath}\" is {fileInfo.OwnerUser.UserName}"); bldr.AppendLine($"permissions of \"{filePath}\" = {fileInfo.FileAccessPermissions.ToString()}"); bldr.AppendLine($"owner of \"{folder}\" is {dirInfo.OwnerUser.UserName}"); bldr.AppendLine($"permissions of \"{folder}\" = {dirInfo.FileAccessPermissions.ToString()}"); } } catch (Exception e) { bldr.AppendLine($"Caught exception {e} while trying to collect information about {filePath}"); } return(bldr.ToString()); }
/// <summary> /// Snapshots the VM and gets its (maybe partial) StorageLayout /// </summary> /// <returns> /// The physical disks. /// </returns> retrieve a public StorageLayout BuildStorageLayout() { List <FileSystem> fsList = new List <FileSystem>(); if (this.loopDevices == null) // local layout { fsList = GetMountedFilesystems(); } /*else * fsList = MountLoopFilesystems();*/ Mono.Unix.UnixDirectoryInfo ud = new Mono.Unix.UnixDirectoryInfo(sysfsRoot); foreach (Mono.Unix.Native.Dirent scsiDevice in ud.GetEntries()) { if (this.IsLayoutLoop && !loopDevices.Contains(scsiDevice.d_name)) { continue; } Console.WriteLine("device subsystem name : " + scsiDevice.d_name); Disk disk = new Disk(); string path = ""; if (this.IsLayoutLoop) { path = sysfsRoot + "/" + scsiDevice; } else { path = sysfsRoot + "/" + scsiDevice + "/device/block"; } if (!Directory.Exists(path)) { disk.Enabled = false; } else { disk.Enabled = true; } string diskName = ""; if (this.IsLayoutLoop) { diskName = scsiDevice.d_name; } else { Mono.Unix.UnixDirectoryInfo scsiPath = new Mono.Unix.UnixDirectoryInfo(path); diskName = scsiPath.GetEntries()[0].d_name; path += "/" + diskName; } disk.Path = "/dev/" + diskName; disk.Size = long.Parse(File.ReadAllText(path + "/size")); //disk.Enabled = File.ReadAllText(path+"/removable").StartsWith("0"); if (!File.ReadAllText(path + "/removable").StartsWith("0")) // exclude removable devices (external drives, usb keys...) { continue; } disk.Enabled = true; disk.SectorSize = uint.Parse(File.ReadAllText(path + "/queue/hw_sector_size")); if (this.IsLayoutLoop) { disk.Type = DiskType.Loop; } try{ disk.BlockStream = new FileStream(disk.Path, System.IO.FileMode.Open); } catch (Exception e) { Console.WriteLine("ERROR : " + e.Message); } //MBR mbr = new MBR(disk.MbrBytes); // gather what MBR sees //disk.Children.AddRange(StorageLayoutManager.GetPartitionsFromMBR(disk)); // now compare with what is inside sysfs and complete information List <Partition> sysfsParts = GetSysfsPartitions(path, diskName); foreach (Partition sysfsP in sysfsParts) { //Console.WriteLine ("@@@@@@@@@@@@@@@@ GetSysfsPartitions SYS current="+sysfsP.Offset+" ("+sysfsP.Path+")"); //foreach(Partition p in disk.Children){ //Console.WriteLine ("@@@@@@@@@@@@@@@@ GetSysfsPartitions MBR current="+p.Offset); //if (p.Offset != sysfsP.Offset) continue; //Console.WriteLine ("@@@@@@@@@@@@@@@@ GetSysfsPartitions MATCHED MBR partition "+sysfsP.Path); //p.Path = sysfsP.Path; //p.Size = sysfsP.Size; foreach (FileSystem f in fsList) { string fsDevName = GetPartitionFromPathOrUuid(f.Path); //Console.WriteLine ("@@@@@@@@@@@@@@@@ GetSysfsPartitions FS current="+f.Path+", mntpt="+f.MountPoint+", mapped="+fsDevName); if (fsDevName == sysfsP.Path) { sysfsP.AddChild(f); //Console.WriteLine ("@@@@@@@@@@@@@@@@ GetSysfsPartitions FS MATCHED"+Environment.NewLine); } } //break; disk.AddChild(sysfsP); //} } layout.Entries.Add(disk); } // end foreach // if using loop devices, try to detect fses and mount only now that we have a complete view and access to disks and parts. // doing it so late allows to detect things like LVM volumes spread on multiple partitions or disks if (fsList.Count == 0) { //1- try to mount the loop partitions foreach (Partition p in layout.GetAllPartitions(null)) { // quick, hackish and dirty way to avoid mounting an 'extended' partition, // which sould result in an endless loop while burning 100% cPU in zombie state. Yup. Kernel bug? if (p.Size == 2) { continue; } FileSystem mountedFS = MountLoopFilesystem(p); if (mountedFS != null) { p.AddChild(mountedFS); } } // 2- try to access and read VM /etc/fstab, from there guess the original loop FS mountpoint Dictionary <string, string> originalMountpoints = TryGuessOriginalMountPoint(layout.GetAllFileSystems(null)); foreach (FileSystem fs in layout.GetAllFileSystems(null)) { foreach (KeyValuePair <string, string> mp in originalMountpoints) { string fsBlockDevice = GetPartitionFromPathOrUuid(mp.Key); //Console.WriteLine ("ORIGINAL LAYOUT FS: mountpoint key="+mp.Key+", value="+mp.Value+", fromuuid="+fsBlockDevice+", fs.path="+fs.Path+", fs.mountpoint="+fs.MountPoint); if (fsBlockDevice == fs.Path) { fs.OriginalMountPoint = mp.Value; if (LogEvent != null) { LogEvent(this, new LogEventArgs(0, Severity.DEBUG, "Filesystem at mountpoint '" + fs.MountPoint + "' was originally mounted as '" + fs.OriginalMountPoint + "'")); } break;; } } } } return(layout); }