Example #1
0
        /// <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);
        }
Example #4
0
        /// <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);
        }
Example #5
0
        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();
        }