/// <summary> /// Converts a FileSystemInfo into a FileSystemObject by reading in data about the file /// </summary> /// <param name="fileInfo">A reference to a file on disk.</param> /// <param name="downloadCloud"> /// If the file is hosted in the cloud, the user has the option to include cloud files or not. /// </param> /// <param name="includeContentHash">If we should generate a hash of the file.</param> /// <returns></returns> public FileSystemObject FilePathToFileSystemObject(string path) { FileSystemObject obj = new FileSystemObject(path); // Get Owner/Group if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { try { var fileSecurity = new FileSecurity(path, AccessControlSections.Owner); IdentityReference oid = fileSecurity.GetOwner(typeof(SecurityIdentifier)); obj.Owner = AsaHelpers.SidToName(oid); } catch (Exception e) { Log.Verbose("Failed to get owner for {0} ({1}:{2})", path, e.GetType(), e.Message); } try { var fileSecurity = new FileSecurity(path, AccessControlSections.Group); IdentityReference gid = fileSecurity.GetGroup(typeof(SecurityIdentifier)); obj.Group = AsaHelpers.SidToName(gid); } catch (Exception e) { Log.Verbose("Failed to get group for {0} ({1}:{2})", path, e.GetType(), e.Message); } try { var fileSecurity = new FileSecurity(path, AccessControlSections.Access); var rules = fileSecurity.GetAccessRules(true, true, typeof(SecurityIdentifier)); obj.Permissions = new Dictionary <string, string>(); foreach (FileSystemAccessRule?rule in rules) { if (rule != null) { string name = AsaHelpers.SidToName(rule.IdentityReference); foreach (var permission in rule.FileSystemRights.ToString().Split(',')) { if (obj.Permissions.ContainsKey(name)) { obj.Permissions[name] = $"{obj.Permissions[name]},{permission}"; } else { obj.Permissions.Add(name, permission); } } } } } catch (Exception e) { Log.Verbose("Failed to get FileSecurity for {0} ({1}:{2})", path, e.GetType(), e.Message); } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { try { var file = new UnixSymbolicLinkInfo(path); obj.Owner = file.OwnerUser.UserName; obj.Group = file.OwnerGroup.GroupName; obj.SetGid = file.IsSetGroup; obj.SetUid = file.IsSetUser; obj.Permissions = new Dictionary <string, string>(); if (file.FileAccessPermissions.ToString().Equals("AllPermissions", StringComparison.InvariantCulture)) { obj.Permissions.Add("User", "Read,Write,Execute"); obj.Permissions.Add("Group", "Read,Write,Execute"); obj.Permissions.Add("Other", "Read,Write,Execute"); } else { var keys = new List <string>() { "User", "Group", "Other" }; var splits = file.FileAccessPermissions.ToString().Split(',').Select(x => x.Trim()); foreach (var key in keys) { foreach (var permission in splits.Where((x) => x.StartsWith(key, StringComparison.InvariantCulture))) { if (permission.Contains("ReadWriteExecute", StringComparison.InvariantCulture)) { obj.Permissions.Add(key, "Read,Write,Execute"); } else { if (obj.Permissions.ContainsKey(key)) { obj.Permissions[key] = $"{obj.Permissions[key]},{permission.Trim().Substring(key.Length)}"; } else { obj.Permissions.Add(key, permission.Trim().Substring(key.Length)); } } } } } } catch (Exception e) when( e is ArgumentNullException || e is ArgumentException || e is InvalidOperationException) { Log.Verbose("Failed to get permissions for {0} ({1}:{2})", path, e.GetType(), e.Message); } } try { FileIOPermission fiop = new FileIOPermission(FileIOPermissionAccess.Read, path); fiop.Demand(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (Directory.Exists(path)) { var fileInfo = new DirectoryInfo(path); if (fileInfo.Attributes.HasFlag(FileAttributes.ReparsePoint)) { obj.IsLink = true; obj.Target = NativeMethods.GetFinalPathName(path); } else { obj.IsDirectory = true; } } else { var fileInfo = new FileInfo(path); obj.Size = fileInfo.Length; obj.SizeOnDisk = WindowsSizeOnDisk(fileInfo); // This check is to try to prevent reading of cloud based files (like a // dropbox folder) and subsequently causing a download, unless the user // specifically requests it with DownloadCloud. if (opts.DownloadCloud || obj.SizeOnDisk > 0 || WindowsFileSystemUtils.IsLocal(obj.Path)) { obj.LastModified = File.GetLastWriteTimeUtc(path); obj.Created = File.GetCreationTimeUtc(path); if (opts.GatherHashes == true) { obj.ContentHash = FileSystemUtils.GetFileHash(fileInfo); } var exeType = FileSystemUtils.GetExecutableType(path); if (exeType != EXECUTABLE_TYPE.NONE && exeType != EXECUTABLE_TYPE.UNKNOWN) { obj.IsExecutable = true; } if (exeType == EXECUTABLE_TYPE.WINDOWS) { obj.SignatureStatus = WindowsFileSystemUtils.GetSignatureStatus(path); obj.Characteristics = WindowsFileSystemUtils.GetDllCharacteristics(path); } else if (exeType == EXECUTABLE_TYPE.MACOS) { obj.MacSignatureStatus = FileSystemUtils.GetMacSignature(path); } } } } else { UnixSymbolicLinkInfo i = new UnixSymbolicLinkInfo(path); obj.FileType = i.FileType.ToString(); obj.Size = i.Length; obj.IsDirectory = false; switch (i.FileType) { case FileTypes.SymbolicLink: obj.IsLink = true; obj.Target = i.ContentsPath; break; case FileTypes.Fifo: case FileTypes.Socket: case FileTypes.BlockDevice: case FileTypes.CharacterDevice: case FileTypes.Directory: obj.IsDirectory = true; if (path?.EndsWith(".app", StringComparison.InvariantCultureIgnoreCase) ?? false) { obj.MacSignatureStatus = FileSystemUtils.GetMacSignature(path); } break; case FileTypes.RegularFile: var fileInfo = new FileInfo(path); obj.SizeOnDisk = i.BlocksAllocated * i.BlockSize; if (opts.DownloadCloud || obj.SizeOnDisk > 0) { obj.LastModified = File.GetLastWriteTimeUtc(path); obj.Created = File.GetCreationTimeUtc(path); if (opts.GatherHashes) { obj.ContentHash = FileSystemUtils.GetFileHash(path); } var exeType = FileSystemUtils.GetExecutableType(path); if (exeType != EXECUTABLE_TYPE.NONE && exeType != EXECUTABLE_TYPE.UNKNOWN) { obj.IsExecutable = true; } if (exeType == EXECUTABLE_TYPE.WINDOWS) { obj.SignatureStatus = WindowsFileSystemUtils.GetSignatureStatus(path); obj.Characteristics = WindowsFileSystemUtils.GetDllCharacteristics(path); } else if (exeType == EXECUTABLE_TYPE.MACOS) { obj.MacSignatureStatus = FileSystemUtils.GetMacSignature(path); } } break; } } } catch (Exception e) when( e is ArgumentNullException || e is SecurityException || e is ArgumentException || e is UnauthorizedAccessException || e is PathTooLongException || e is NotSupportedException || e is InvalidOperationException || e is FileNotFoundException || e is Win32Exception || e is IOException) { Log.Verbose("Failed to create FileInfo from File at {0} ({1}:{2})", path, e.GetType(), e.Message); } catch (Exception e) { Log.Debug("Should be caught in DirectoryWalker {0} {1}", e.GetType().ToString(), path); } try { obj.LastModified = File.GetLastWriteTimeUtc(path); obj.Created = File.GetCreationTimeUtc(path); } catch (Exception e) { Log.Verbose("Failed to get last modified for {0} ({1}:{2})", path, e.GetType(), e.Message); } return(obj); }
public override void Execute() { if (!CanRunOnPlatform()) { return; } Start(); if (roots == null || !roots.Any()) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { foreach (var driveInfo in DriveInfo.GetDrives()) { if (driveInfo.IsReady && driveInfo.DriveType == DriveType.Fixed) { roots.Add(driveInfo.Name); } } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { roots.Add("/"); // @TODO Improve this } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { roots.Add("/"); // @TODO Improve this } } foreach (var root in roots) { Log.Information("{0} root {1}", Strings.Get("Scanning"), root.ToString()); //Ensure the transaction is started to prevent collisions on the multithreaded code ahead _ = DatabaseManager.Transaction; try { var fileInfoEnumerable = DirectoryWalker.WalkDirectory(root); Parallel.ForEach(fileInfoEnumerable, (fileInfo => { try { FileSystemObject obj = null; if (fileInfo is DirectoryInfo) { obj = new FileSystemObject() { Path = fileInfo.FullName, Permissions = FileSystemUtils.GetFilePermissions(fileInfo), IsDirectory = true }; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { var file = new UnixFileInfo(fileInfo.FullName); obj.Owner = file.OwnerUser.UserName; obj.Group = file.OwnerGroup.GroupName; obj.SetGid = file.IsSetGroup; obj.SetUid = file.IsSetUser; } } else { obj = new FileSystemObject() { Path = fileInfo.FullName, Permissions = FileSystemUtils.GetFilePermissions(fileInfo), Size = (ulong)(fileInfo as FileInfo).Length, IsDirectory = false }; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { var file = new UnixFileInfo(fileInfo.FullName); obj.Owner = file.OwnerUser.UserName; obj.Group = file.OwnerGroup.GroupName; obj.SetGid = file.IsSetGroup; obj.SetUid = file.IsSetUser; } if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (WindowsFileSystemUtils.IsLocal(obj.Path) || downloadCloud) { if (WindowsFileSystemUtils.NeedsSignature(obj.Path)) { obj.SignatureStatus = WindowsFileSystemUtils.GetSignatureStatus(fileInfo.FullName); obj.Characteristics = WindowsFileSystemUtils.GetDllCharacteristics(fileInfo.FullName); } else { obj.SignatureStatus = "Cloud"; } } } if (INCLUDE_CONTENT_HASH) { obj.ContentHash = FileSystemUtils.GetFileHash(fileInfo); } if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { if (obj.Permissions.Contains("Execute")) { obj.IsExecutable = true; } } else { try { if (WindowsFileSystemUtils.IsLocal(obj.Path) || downloadCloud) { if (WindowsFileSystemUtils.NeedsSignature(obj.Path)) { obj.IsExecutable = true; } } } catch (System.UnauthorizedAccessException ex) { Log.Verbose(ex, "Couldn't access {0} to check if signature is needed.", fileInfo.FullName); } } } if (obj != null) { DatabaseManager.Write(obj, runId); if (examineCertificates && fileInfo.FullName.EndsWith(".cer", StringComparison.CurrentCulture) || fileInfo.FullName.EndsWith(".der", StringComparison.CurrentCulture) || fileInfo.FullName.EndsWith(".p7b", StringComparison.CurrentCulture)) { var certificate = X509Certificate.CreateFromCertFile(fileInfo.FullName); var certObj = new CertificateObject() { StoreLocation = fileInfo.FullName, StoreName = "Disk", CertificateHashString = certificate.GetCertHashString(), Subject = certificate.Subject, Pkcs7 = certificate.Export(X509ContentType.Cert).ToString() }; DatabaseManager.Write(certObj, runId); } } } catch (System.UnauthorizedAccessException e) { Log.Verbose(e, "Access Denied {0}", fileInfo?.FullName); } catch (System.IO.IOException e) { Log.Verbose(e, "Couldn't parse {0}", fileInfo?.FullName); } catch (Exception e) { Logger.DebugException(e); } })); } catch (Exception e) { Log.Warning(e, "Error collecting file system information: {0}", e.Message); } DatabaseManager.Commit(); } Stop(); }
/// <summary> /// Converts a FileSystemInfo into a FileSystemObject by reading in data about the file /// </summary> /// <param name="fileInfo">A reference to a file on disk.</param> /// <param name="downloadCloud">If the file is hosted in the cloud, the user has the option to include cloud files or not.</param> /// <param name="INCLUDE_CONTENT_HASH">If we should generate a hash of the file.</param> /// <returns></returns> public static FileSystemObject FileSystemInfoToFileSystemObject(FileSystemInfo fileInfo, bool downloadCloud = false, bool INCLUDE_CONTENT_HASH = false) { if (fileInfo == null) { return(null); } FileSystemObject obj = new FileSystemObject() { Path = fileInfo.FullName, PermissionsString = FileSystemUtils.GetFilePermissions(fileInfo), }; // Get Owner/Group if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { try { var fileSecurity = new FileSecurity(fileInfo.FullName, AccessControlSections.All); IdentityReference oid = fileSecurity.GetOwner(typeof(SecurityIdentifier)); IdentityReference gid = fileSecurity.GetGroup(typeof(SecurityIdentifier)); // Set the Owner and Group to the SID, in case we can't properly translate obj.Owner = oid.ToString(); obj.Group = gid.ToString(); try { // Translate owner into the string representation. obj.Owner = (oid.Translate(typeof(NTAccount)) as NTAccount).Value; } catch (IdentityNotMappedException) { Log.Verbose("Couldn't find the Owner from SID {0} for file {1}", oid.ToString(), fileInfo.FullName); } try { // Translate group into the string representation. obj.Group = (gid.Translate(typeof(NTAccount)) as NTAccount).Value; } catch (IdentityNotMappedException) { // This is fine. Some SIDs don't map to NT Accounts. Log.Verbose("Couldn't find the Group from SID {0} for file {1}", gid.ToString(), fileInfo.FullName); } var rules = fileSecurity.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier)); foreach (FileSystemAccessRule rule in rules) { string name = rule.IdentityReference.Value; try { name = rule.IdentityReference.Translate(typeof(NTAccount)).Value; } catch (IdentityNotMappedException) { // This is fine. Some SIDs don't map to NT Accounts. } foreach (var permission in rule.FileSystemRights.ToString().Split(',')) { obj.Permissions.Add(new KeyValuePair <string, string>(name, permission)); } } } catch (Exception e) when( e is ArgumentException || e is ArgumentNullException || e is DirectoryNotFoundException || e is FileNotFoundException || e is IOException || e is NotSupportedException || e is PlatformNotSupportedException || e is PathTooLongException || e is PrivilegeNotHeldException || e is SystemException || e is UnauthorizedAccessException) { Log.Verbose($"Error instantiating FileSecurity object {obj.Path} {e.GetType().ToString()}"); } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { try { var file = new UnixFileInfo(fileInfo.FullName); obj.Owner = file.OwnerUser.UserName; obj.Group = file.OwnerGroup.GroupName; obj.SetGid = file.IsSetGroup; obj.SetUid = file.IsSetUser; if (file.FileAccessPermissions.ToString().Equals("AllPermissions", StringComparison.InvariantCulture)) { obj.Permissions.Add(new KeyValuePair <string, string>("User", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("User", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("User", "Execute")); obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Execute")); obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Execute")); } else { foreach (var permission in file.FileAccessPermissions.ToString().Split(',').Where((x) => x.Trim().StartsWith("User", StringComparison.InvariantCulture))) { if (permission.Contains("ReadWriteExecute", StringComparison.InvariantCulture)) { obj.Permissions.Add(new KeyValuePair <string, string>("User", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("User", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("User", "Execute")); } else { obj.Permissions.Add(new KeyValuePair <string, string>("User", permission.Trim().Substring(4))); } } foreach (var permission in file.FileAccessPermissions.ToString().Split(',').Where((x) => x.Trim().StartsWith("Group", StringComparison.InvariantCulture))) { if (permission.Contains("ReadWriteExecute", StringComparison.InvariantCulture)) { obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Execute")); } else { obj.Permissions.Add(new KeyValuePair <string, string>("Group", permission.Trim().Substring(5))); } } foreach (var permission in file.FileAccessPermissions.ToString().Split(',').Where((x) => x.Trim().StartsWith("Other", StringComparison.InvariantCulture))) { if (permission.Contains("ReadWriteExecute", StringComparison.InvariantCulture)) { obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Execute")); } else { obj.Permissions.Add(new KeyValuePair <string, string>("Other", permission.Trim().Substring(5))); } } } } catch (Exception e) when( e is ArgumentNullException || e is ArgumentException) { Log.Verbose($"Failed to get permissions for {fileInfo.FullName} {e.GetType().ToString()}"); } } if (fileInfo is DirectoryInfo) { obj.IsDirectory = true; } else if (fileInfo is FileInfo) { obj.Size = (ulong)(fileInfo as FileInfo).Length; obj.IsDirectory = false; if (INCLUDE_CONTENT_HASH) { obj.ContentHash = FileSystemUtils.GetFileHash(fileInfo); } // Set IsExecutable and Signature Status if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (WindowsFileSystemUtils.IsLocal(obj.Path) || downloadCloud) { if (WindowsFileSystemUtils.NeedsSignature(obj.Path)) { obj.SignatureStatus = WindowsFileSystemUtils.GetSignatureStatus(fileInfo.FullName); obj.Characteristics.AddRange(WindowsFileSystemUtils.GetDllCharacteristics(fileInfo.FullName)); obj.IsExecutable = FileSystemUtils.IsExecutable(obj.Path); } } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { obj.IsExecutable = FileSystemUtils.IsExecutable(obj.Path); } } return(obj); }
/// <summary> /// Converts a FileSystemInfo into a FileSystemObject by reading in data about the file /// </summary> /// <param name="fileInfo">A reference to a file on disk.</param> /// <param name="downloadCloud">If the file is hosted in the cloud, the user has the option to include cloud files or not.</param> /// <param name="includeContentHash">If we should generate a hash of the file.</param> /// <returns></returns> public static FileSystemObject FilePathToFileSystemObject(string path, bool downloadCloud = false, bool includeContentHash = false) { if (path == null) { return(null); } FileSystemObject obj = new FileSystemObject() { Path = path, }; // Get Owner/Group if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { try { var fileSecurity = new FileSecurity(path, AccessControlSections.All); IdentityReference oid = fileSecurity.GetOwner(typeof(SecurityIdentifier)); IdentityReference gid = fileSecurity.GetGroup(typeof(SecurityIdentifier)); // Set the Owner and Group to the SID, in case we can't properly translate obj.Owner = oid.ToString(); obj.Group = gid.ToString(); try { // Translate owner into the string representation. obj.Owner = (oid.Translate(typeof(NTAccount)) as NTAccount).Value; } catch (IdentityNotMappedException) { Log.Verbose("Couldn't find the Owner from SID {0} for file {1}", oid.ToString(), path); } try { // Translate group into the string representation. obj.Group = (gid.Translate(typeof(NTAccount)) as NTAccount).Value; } catch (IdentityNotMappedException) { // This is fine. Some SIDs don't map to NT Accounts. Log.Verbose("Couldn't find the Group from SID {0} for file {1}", gid.ToString(), path); } var rules = fileSecurity.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier)); foreach (FileSystemAccessRule rule in rules) { string name = rule.IdentityReference.Value; try { name = rule.IdentityReference.Translate(typeof(NTAccount)).Value; } catch (IdentityNotMappedException) { // This is fine. Some SIDs don't map to NT Accounts. } foreach (var permission in rule.FileSystemRights.ToString().Split(',')) { if (obj.Permissions.ContainsKey(name)) { obj.Permissions[name] = $"{obj.Permissions[name]},{permission}"; } else { obj.Permissions.Add(name, permission); } } } } catch (Exception e) when( e is ArgumentException || e is ArgumentNullException || e is DirectoryNotFoundException || e is FileNotFoundException || e is IOException || e is NotSupportedException || e is PlatformNotSupportedException || e is PathTooLongException || e is PrivilegeNotHeldException || e is SystemException || e is UnauthorizedAccessException) { Log.Verbose($"Error instantiating FileSecurity object {obj.Path} {e.GetType().ToString()}"); } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { try { var file = new UnixSymbolicLinkInfo(path); obj.Owner = file.OwnerUser.UserName; obj.Group = file.OwnerGroup.GroupName; obj.SetGid = file.IsSetGroup; obj.SetUid = file.IsSetUser; if (file.FileAccessPermissions.ToString().Equals("AllPermissions", StringComparison.InvariantCulture)) { obj.Permissions.Add("User", "Read,Write,Execute"); obj.Permissions.Add("Group", "Read,Write,Execute"); obj.Permissions.Add("Other", "Read,Write,Execute"); } else { var keys = new List <string>() { "User", "Group", "Other" }; var splits = file.FileAccessPermissions.ToString().Split(',').Select(x => x.Trim()); foreach (var key in keys) { foreach (var permission in splits.Where((x) => x.StartsWith(key, StringComparison.InvariantCulture))) { if (permission.Contains("ReadWriteExecute", StringComparison.InvariantCulture)) { obj.Permissions.Add(key, "Read,Write,Execute"); } else { if (obj.Permissions.ContainsKey(key)) { obj.Permissions[key] = $"{obj.Permissions[key]},{permission.Trim().Substring(key.Length)}"; } else { obj.Permissions.Add(key, permission.Trim().Substring(key.Length)); } } } } } } catch (Exception e) when( e is ArgumentNullException || e is ArgumentException || e is InvalidOperationException) { Log.Debug($"Failed to get permissions for {path} {e.GetType().ToString()}"); } } try { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (Directory.Exists(path)) { var fileInfo = new DirectoryInfo(path); if (fileInfo.Attributes.HasFlag(FileAttributes.ReparsePoint)) { obj.IsLink = true; obj.Target = NativeMethods.GetFinalPathName(path); } else { obj.IsDirectory = true; } } else { var fileInfo = new FileInfo(path); obj.Size = (ulong)fileInfo.Length; if (WindowsFileSystemUtils.IsLocal(obj.Path) || downloadCloud) { if (includeContentHash) { obj.ContentHash = FileSystemUtils.GetFileHash(fileInfo); } obj.IsExecutable = FileSystemUtils.IsExecutable(obj.Path, obj.Size); if (obj.IsExecutable) { obj.SignatureStatus = WindowsFileSystemUtils.GetSignatureStatus(path); obj.Characteristics.AddRange(WindowsFileSystemUtils.GetDllCharacteristics(path)); } } } } else { UnixSymbolicLinkInfo i = new UnixSymbolicLinkInfo(path); obj.FileType = i.FileType.ToString(); obj.Size = (ulong)i.Length; obj.IsDirectory = false; switch (i.FileType) { case FileTypes.SymbolicLink: obj.IsLink = true; obj.Target = i.ContentsPath; break; case FileTypes.Fifo: case FileTypes.Socket: case FileTypes.BlockDevice: case FileTypes.CharacterDevice: case FileTypes.Directory: obj.IsDirectory = true; break; case FileTypes.RegularFile: if (includeContentHash) { obj.ContentHash = FileSystemUtils.GetFileHash(path); } obj.IsExecutable = FileSystemUtils.IsExecutable(obj.Path, obj.Size); break; } } } catch (Exception e) when( e is ArgumentNullException || e is SecurityException || e is ArgumentException || e is UnauthorizedAccessException || e is PathTooLongException || e is NotSupportedException || e is InvalidOperationException) { Log.Verbose("Failed to create FileInfo from File at {0} {1}", path, e.GetType().ToString()); } catch (Exception e) { Log.Debug("Should be caught in DirectoryWalker {0}", e.GetType().ToString()); } return(obj); }
public static FileSystemObject FileSystemInfoToFileSystemObject(FileSystemInfo fileInfo, bool downloadCloud = false, bool INCLUDE_CONTENT_HASH = false) { FileSystemObject obj = null; try { if (fileInfo is DirectoryInfo) { obj = new FileSystemObject() { Path = fileInfo.FullName, Permissions = FileSystemUtils.GetFilePermissions(fileInfo), IsDirectory = true }; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { var file = new UnixFileInfo(fileInfo.FullName); obj.Owner = file.OwnerUser.UserName; obj.Group = file.OwnerGroup.GroupName; obj.SetGid = file.IsSetGroup; obj.SetUid = file.IsSetUser; } } else { obj = new FileSystemObject() { Path = fileInfo.FullName, Permissions = FileSystemUtils.GetFilePermissions(fileInfo), Size = (ulong)(fileInfo as FileInfo).Length, IsDirectory = false }; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { var file = new UnixFileInfo(fileInfo.FullName); obj.Owner = file.OwnerUser.UserName; obj.Group = file.OwnerGroup.GroupName; obj.SetGid = file.IsSetGroup; obj.SetUid = file.IsSetUser; } if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (WindowsFileSystemUtils.IsLocal(obj.Path) || downloadCloud) { if (WindowsFileSystemUtils.NeedsSignature(obj.Path)) { obj.SignatureStatus = WindowsFileSystemUtils.GetSignatureStatus(fileInfo.FullName); obj.Characteristics = WindowsFileSystemUtils.GetDllCharacteristics(fileInfo.FullName); } else { obj.SignatureStatus = "Cloud"; } } } if (INCLUDE_CONTENT_HASH) { obj.ContentHash = FileSystemUtils.GetFileHash(fileInfo); } if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { if (obj.Permissions.Contains("Execute")) { obj.IsExecutable = true; } } else { try { if (WindowsFileSystemUtils.IsLocal(obj.Path) || downloadCloud) { if (WindowsFileSystemUtils.NeedsSignature(obj.Path)) { obj.IsExecutable = true; } } } catch (System.UnauthorizedAccessException ex) { Log.Verbose(ex, "Couldn't access {0} to check if signature is needed.", fileInfo.FullName); } } } } catch (System.UnauthorizedAccessException e) { Log.Verbose(e, "Access Denied {0}", fileInfo?.FullName); } catch (System.IO.IOException e) { Log.Verbose(e, "Couldn't parse {0}", fileInfo?.FullName); } catch (Exception e) { Log.Warning(e, "Error collecting file system information: {0}", e.Message); } return(obj); }
/// <summary> /// Converts a FileSystemInfo into a FileSystemObject by reading in data about the file /// </summary> /// <param name="fileInfo">A reference to a file on disk.</param> /// <param name="downloadCloud">If the file is hosted in the cloud, the user has the option to include cloud files or not.</param> /// <param name="includeContentHash">If we should generate a hash of the file.</param> /// <returns></returns> public static FileSystemObject FilePathToFileSystemObject(string path, bool downloadCloud = false, bool includeContentHash = false) { FileSystemObject obj = new FileSystemObject(path); // Get Owner/Group if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { try { var fileSecurity = new FileSecurity(path, AccessControlSections.All); IdentityReference oid = fileSecurity.GetOwner(typeof(SecurityIdentifier)); IdentityReference gid = fileSecurity.GetGroup(typeof(SecurityIdentifier)); obj.Owner = AsaHelpers.SidToName(oid); obj.Group = AsaHelpers.SidToName(gid); var rules = fileSecurity.GetAccessRules(true, true, typeof(SecurityIdentifier)); foreach (FileSystemAccessRule?rule in rules) { if (rule != null) { string name = AsaHelpers.SidToName(rule.IdentityReference); obj.Permissions = new Dictionary <string, string>(); foreach (var permission in rule.FileSystemRights.ToString().Split(',')) { if (obj.Permissions.ContainsKey(name)) { obj.Permissions[name] = $"{obj.Permissions[name]},{permission}"; } else { obj.Permissions.Add(name, permission); } } } } } catch (Exception e) when( e is ArgumentException || e is ArgumentNullException || e is DirectoryNotFoundException || e is FileNotFoundException || e is IOException || e is NotSupportedException || e is PlatformNotSupportedException || e is PathTooLongException || e is PrivilegeNotHeldException || e is SystemException || e is UnauthorizedAccessException) { Log.Verbose($"Error instantiating FileSecurity object {obj.Path} {e.GetType().ToString()}"); } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { try { var file = new UnixSymbolicLinkInfo(path); obj.Owner = file.OwnerUser.UserName; obj.Group = file.OwnerGroup.GroupName; obj.SetGid = file.IsSetGroup; obj.SetUid = file.IsSetUser; obj.Permissions = new Dictionary <string, string>(); if (file.FileAccessPermissions.ToString().Equals("AllPermissions", StringComparison.InvariantCulture)) { obj.Permissions.Add("User", "Read,Write,Execute"); obj.Permissions.Add("Group", "Read,Write,Execute"); obj.Permissions.Add("Other", "Read,Write,Execute"); } else { var keys = new List <string>() { "User", "Group", "Other" }; var splits = file.FileAccessPermissions.ToString().Split(',').Select(x => x.Trim()); foreach (var key in keys) { foreach (var permission in splits.Where((x) => x.StartsWith(key, StringComparison.InvariantCulture))) { if (permission.Contains("ReadWriteExecute", StringComparison.InvariantCulture)) { obj.Permissions.Add(key, "Read,Write,Execute"); } else { if (obj.Permissions.ContainsKey(key)) { obj.Permissions[key] = $"{obj.Permissions[key]},{permission.Trim().Substring(key.Length)}"; } else { obj.Permissions.Add(key, permission.Trim().Substring(key.Length)); } } } } } } catch (Exception e) when( e is ArgumentNullException || e is ArgumentException || e is InvalidOperationException) { Log.Debug($"Failed to get permissions for {path} {e.GetType().ToString()}"); } } try { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (Directory.Exists(path)) { var fileInfo = new DirectoryInfo(path); if (fileInfo.Attributes.HasFlag(FileAttributes.ReparsePoint)) { obj.IsLink = true; obj.Target = NativeMethods.GetFinalPathName(path); } else { obj.IsDirectory = true; } } else { var fileInfo = new FileInfo(path); var size = (ulong)fileInfo.Length; obj.Size = size; if (WindowsFileSystemUtils.IsLocal(obj.Path) || downloadCloud) { if (includeContentHash) { obj.ContentHash = FileSystemUtils.GetFileHash(fileInfo); } obj.IsExecutable = FileSystemUtils.IsExecutable(obj.Path, size); if (obj.IsExecutable != null && (bool)obj.IsExecutable) { // TODO: This can be optimized into fewer touches, GetSignatureStatus also runs IsExecutable checks against the first 4 bytes obj.SignatureStatus = WindowsFileSystemUtils.GetSignatureStatus(path); obj.Characteristics = WindowsFileSystemUtils.GetDllCharacteristics(path); } } } } else { UnixSymbolicLinkInfo i = new UnixSymbolicLinkInfo(path); obj.FileType = i.FileType.ToString(); obj.Size = (ulong)i.Length; obj.IsDirectory = false; switch (i.FileType) { case FileTypes.SymbolicLink: obj.IsLink = true; obj.Target = i.ContentsPath; break; case FileTypes.Fifo: case FileTypes.Socket: case FileTypes.BlockDevice: case FileTypes.CharacterDevice: case FileTypes.Directory: obj.IsDirectory = true; break; case FileTypes.RegularFile: if (i.HasContents) { if (includeContentHash) { obj.ContentHash = FileSystemUtils.GetFileHash(path); } obj.IsExecutable = FileSystemUtils.IsExecutable(obj.Path, obj.Size); } break; } } } catch (Exception e) when( e is ArgumentNullException || e is SecurityException || e is ArgumentException || e is UnauthorizedAccessException || e is PathTooLongException || e is NotSupportedException || e is InvalidOperationException) { Log.Verbose("Failed to create FileInfo from File at {0} {1}", path, e.GetType().ToString()); } catch (Exception e) { Log.Debug("Should be caught in DirectoryWalker {0}", e.GetType().ToString()); } try { obj.LastModified = File.GetLastWriteTimeUtc(path); obj.Created = File.GetCreationTimeUtc(path); } catch (Exception) { } return(obj); }
/// <summary> /// Converts a FileSystemInfo into a FileSystemObject by reading in data about the file /// </summary> /// <param name="fileInfo">A reference to a file on disk.</param> /// <param name="downloadCloud">If the file is hosted in the cloud, the user has the option to include cloud files or not.</param> /// <param name="INCLUDE_CONTENT_HASH">If we should generate a hash of the file.</param> /// <returns></returns> public static FileSystemObject FileSystemInfoToFileSystemObject(FileSystemInfo fileInfo, bool downloadCloud = false, bool INCLUDE_CONTENT_HASH = false) { FileSystemObject obj = new FileSystemObject() { Path = fileInfo.FullName, PermissionsString = FileSystemUtils.GetFilePermissions(fileInfo), }; try { // Get Owner/Group if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { var fileSecurity = new FileSecurity(fileInfo.FullName, AccessControlSections.All); IdentityReference oid = fileSecurity.GetOwner(typeof(SecurityIdentifier)); IdentityReference gid = fileSecurity.GetGroup(typeof(SecurityIdentifier)); // Set the Owner and Group to the SID, in case we can't properly translate obj.Owner = oid.ToString(); obj.Group = gid.ToString(); try { // Translate owner into the string representation. obj.Owner = (oid.Translate(typeof(NTAccount)) as NTAccount).Value; } catch (IdentityNotMappedException) { Log.Verbose("Couldn't find the Owner from SID {0} for file {1}", oid.ToString(), fileInfo.FullName); } try { // Translate group into the string representation. obj.Group = (gid.Translate(typeof(NTAccount)) as NTAccount).Value; } catch (IdentityNotMappedException) { // This is fine. Some SIDs don't map to NT Accounts. Log.Verbose("Couldn't find the Group from SID {0} for file {1}", gid.ToString(), fileInfo.FullName); } obj.Permissions = new List <KeyValuePair <string, string> >(); var rules = fileSecurity.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier)); foreach (FileSystemAccessRule rule in rules) { string name = rule.IdentityReference.Value; try { name = rule.IdentityReference.Translate(typeof(NTAccount)).Value; } catch (IdentityNotMappedException) { // This is fine. Some SIDs don't map to NT Accounts. } foreach (var permission in rule.FileSystemRights.ToString().Split(',')) { obj.Permissions.Add(new KeyValuePair <string, string>(name, permission)); } } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { var file = new UnixFileInfo(fileInfo.FullName); obj.Owner = file.OwnerUser.UserName; obj.Group = file.OwnerGroup.GroupName; obj.SetGid = file.IsSetGroup; obj.SetUid = file.IsSetUser; obj.Permissions = new List <KeyValuePair <string, string> >(); if (file.FileAccessPermissions.ToString().Equals("AllPermissions")) { obj.Permissions.Add(new KeyValuePair <string, string>("User", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("User", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("User", "Execute")); obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Execute")); obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Execute")); } else { foreach (var permission in file.FileAccessPermissions.ToString().Split(',').Where((x) => x.Trim().StartsWith("User"))) { if (permission.Contains("ReadWriteExecute")) { obj.Permissions.Add(new KeyValuePair <string, string>("User", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("User", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("User", "Execute")); } else { obj.Permissions.Add(new KeyValuePair <string, string>("User", permission.Trim().Substring(4))); } } foreach (var permission in file.FileAccessPermissions.ToString().Split(',').Where((x) => x.Trim().StartsWith("Group"))) { if (permission.Contains("ReadWriteExecute")) { obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Execute")); } else { obj.Permissions.Add(new KeyValuePair <string, string>("Group", permission.Trim().Substring(5))); } } foreach (var permission in file.FileAccessPermissions.ToString().Split(',').Where((x) => x.Trim().StartsWith("Other"))) { if (permission.Contains("ReadWriteExecute")) { obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Execute")); } else { obj.Permissions.Add(new KeyValuePair <string, string>("Other", permission.Trim().Substring(5))); } } } } if (fileInfo is DirectoryInfo) { obj.IsDirectory = true; } else if (fileInfo is FileInfo) { obj.Size = (ulong)(fileInfo as FileInfo).Length; obj.IsDirectory = false; if (INCLUDE_CONTENT_HASH) { obj.ContentHash = FileSystemUtils.GetFileHash(fileInfo); } // Set IsExecutable and Signature Status if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (WindowsFileSystemUtils.IsLocal(obj.Path) || downloadCloud) { try { if (WindowsFileSystemUtils.NeedsSignature(obj.Path)) { obj.SignatureStatus = WindowsFileSystemUtils.GetSignatureStatus(fileInfo.FullName); obj.Characteristics = WindowsFileSystemUtils.GetDllCharacteristics(fileInfo.FullName); obj.IsExecutable = FileSystemUtils.IsExecutable(obj.Path); } } catch (System.UnauthorizedAccessException ex) { Log.Verbose(ex, "Couldn't access {0} to check if signature is needed.", fileInfo.FullName); } } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { obj.IsExecutable = FileSystemUtils.IsExecutable(obj.Path); } } } catch (System.UnauthorizedAccessException e) { Log.Verbose(e, "Access Denied {0}", fileInfo?.FullName); } catch (System.IO.IOException e) { Log.Verbose(e, "Couldn't parse {0}", fileInfo?.FullName); } catch (Exception e) { Log.Warning(e, "Error collecting file system information: {0}", e.Message); } return(obj); }
public override void Execute() { if (!CanRunOnPlatform()) { return; } Start(); //Ensure the transaction is started to prevent collisions on the multithreaded code ahead _ = DatabaseManager.Transaction; if (roots == null || !roots.Any()) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { foreach (var driveInfo in DriveInfo.GetDrives()) { if (driveInfo.IsReady && driveInfo.DriveType == DriveType.Fixed) { roots.Add(driveInfo.Name); } } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { roots.Add("/"); // @TODO Improve this } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { roots.Add("/"); // @TODO Improve this } } foreach (var root in roots) { Log.Information("{0} root {1}",Strings.Get("Scanning"),root.ToString()); try { var fileInfoEnumerable = DirectoryWalker.WalkDirectory(root, Helpers.GetPlatformString()); Parallel.ForEach(fileInfoEnumerable, (fileInfo => { try { FileSystemObject obj = null; if (fileInfo is DirectoryInfo) { obj = new FileSystemObject() { Path = fileInfo.FullName, Permissions = FileSystemUtils.GetFilePermissions(fileInfo), IsDirectory = true }; } else { obj = new FileSystemObject() { Path = fileInfo.FullName, Permissions = FileSystemUtils.GetFilePermissions(fileInfo), Size = (ulong)(fileInfo as FileInfo).Length, IsDirectory = false }; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (WindowsFileSystemUtils.IsLocal(obj.Path) || downloadCloud) { if (WindowsFileSystemUtils.NeedsSignature(obj.Path)) { obj.SignatureStatus = WindowsFileSystemUtils.GetSignatureStatus(fileInfo.FullName); obj.Characteristics = WindowsFileSystemUtils.GetDllCharacteristics(fileInfo.FullName); } else { obj.SignatureStatus = "Cloud"; } } } if (INCLUDE_CONTENT_HASH) { obj.ContentHash = FileSystemUtils.GetFileHash(fileInfo); } if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { if (obj.Permissions.Contains("Execute")) { obj.IsExecutable = true; } } else { // TODO: Improve this to detect executables more intelligently if (WindowsFileSystemUtils.NeedsSignature(obj.Path)) { obj.IsExecutable = true; } } if () } if (obj != null) { DatabaseManager.Write(obj,runId); } } catch (Exception ex) { Log.Warning(ex, "Error processing {0}", fileInfo?.FullName); } })); } catch (Exception ex) { Log.Warning(ex, "Error collecting file system information: {0}", ex.Message); } } Stop(); DatabaseManager.Commit(); }