// Writes Owner and Effective Permissions private void WriteFileSystemObjectOwner(FileSystemInfo fileSystemInfo) { try { FileSystemSecurity accessControl = null; if (fileSystemInfo is FileInfo) { FileInfo fileInfo = fileSystemInfo as FileInfo; accessControl = File.GetAccessControl(fileInfo.FullName); } if (fileSystemInfo is DirectoryInfo) { DirectoryInfo directoryInfo = fileSystemInfo as DirectoryInfo; accessControl = Directory.GetAccessControl(directoryInfo.FullName); } WriteAttribute("Owner", accessControl.GetOwner()); WriteAttribute("Permissions", accessControl.GetEffectivePermissions()); } catch (Exception exception) { NotifyExceptionOccured(exception); } }
public void SetSecurity(FileSystemSecurity security, AccessControlSections sections) { lock (Lock) { if ((sections & AccessControlSections.Owner) != 0) { _directory.Owner = (SecurityIdentifier)security.GetOwner(typeof(SecurityIdentifier)); } if ((sections & AccessControlSections.Group) != 0) { _directory.Group = (SecurityIdentifier)security.GetGroup(typeof(SecurityIdentifier)); } if ((sections & AccessControlSections.Access) != 0) { _fileSystem.RemoveAccessRules(_directory); foreach (var r in security.GetAccessRules(true, false, typeof(SecurityIdentifier))) { _fileSystem.AddAccessRule(_directory, (FileSystemAccessRule)r); } } if ((sections & AccessControlSections.Audit) != 0) { _fileSystem.RemoveAuditRules(_directory); foreach (var r in security.GetAuditRules(true, false, typeof(SecurityIdentifier))) { _fileSystem.AddAuditRule(_directory, (FileSystemAuditRule)r); } } } }
public void AnalyzeFile(string fileName) { Trace.WriteLine("working on filenode=" + fileName); try { InsertFileNode(fileName); // when connecting a login password, unc path starting the with domain name (<> domain controller) fails // rebuild it by replacing the domain name by the domain controller name Uri uri; if (!Uri.TryCreate(fileName, UriKind.RelativeOrAbsolute, out uri)) { Trace.WriteLine("Unable to parse the url: " + fileName); return; } if (!uri.IsUnc) { Trace.WriteLine("File " + fileName + " is not a unc path"); return; } // SYSVOL volume cannot be accessed with login / password login // in this case, the server (aka the domain) needs to be replaced with the FQDN of the server if (uri.Host.Equals(DomainInfo.DomainName, StringComparison.InvariantCultureIgnoreCase)) { UriBuilder builder = new UriBuilder(uri); builder.Host = DomainInfo.DnsHostName; uri = builder.Uri; } string alternativeFilepath = uri.LocalPath; FileSystemInfo info = null; FileAttributes attr = File.GetAttributes(alternativeFilepath); FileSystemSecurity fss = null; // insert relation related to security descriptor if ((attr & FileAttributes.Directory) == FileAttributes.Directory) { info = new DirectoryInfo(alternativeFilepath); fss = ((DirectoryInfo)info).GetAccessControl(); } else { info = new FileInfo(alternativeFilepath); fss = ((FileInfo)info).GetAccessControl(); } InsertFileDescriptorRelation(fileName, fss, false, null); // try to find illegitimate soons if (info as DirectoryInfo != null) { // analyse SD of files in directory AnalyzeFile(fileName, (DirectoryInfo)info, fss.GetOwner(typeof(SecurityIdentifier)).Value); // find hidden relations AnalyzeGPODirectory(fileName, (DirectoryInfo)info); } } catch (Exception ex) { Trace.WriteLine("An exception occured while working on the file '" + fileName + "':" + ex.Message); } }
void AnalyzeAccessControl(StreamWriter sw, FileSystemSecurity security, string name, bool includeInherited) { var Owner = (SecurityIdentifier)security.GetOwner(typeof(SecurityIdentifier)); var matchOwner = MatchesUsersToCheck(Owner); if (matchOwner.HasValue) { sw.WriteLine(name + "\t" + matchOwner.Value.Value + "\tOwner"); } var accessRules = security.GetAccessRules(true, includeInherited, typeof(SecurityIdentifier)); if (accessRules == null) { return; } foreach (FileSystemAccessRule accessrule in accessRules) { if (accessrule.AccessControlType == AccessControlType.Deny) { continue; } if ((FileSystemRights.Write & accessrule.FileSystemRights) != FileSystemRights.Write) { continue; } var match = MatchesUsersToCheck(accessrule.IdentityReference); if (!match.HasValue) { continue; } sw.WriteLine(name + "\t" + match.Value.Value + "\t" + accessrule.FileSystemRights.ToString()); } }
// Gets file/folder owner public static string GetOwner(this FileSystemSecurity fileSystemSecurity) { IdentityReference identityReference = fileSystemSecurity.GetOwner(typeof(SecurityIdentifier)); IdentityReference account = identityReference.Translate(typeof(NTAccount)); return(account.Value); }
private Dictionary <string, List <RelationType> > AnalyzeFileSecurityDescriptor(string filepath, FileSystemSecurity sd, bool skipInherited) { // relations can be duplicated - will slow down import Dictionary <string, List <RelationType> > relationToAdd = new Dictionary <string, List <RelationType> >(); Storage.InsertRelation(sd.GetOwner(typeof(SecurityIdentifier)).Value, MappingType.Sid, filepath, MappingType.FileName, RelationType.FILE_OWNER); foreach (FileSystemAccessRule accessrule in sd.GetAccessRules(true, true, typeof(SecurityIdentifier))) { // ignore audit / denied ace if (accessrule.AccessControlType != AccessControlType.Allow) { continue; } if (skipInherited && accessrule.IsInherited) { continue; } // GEN_RIGHT_ALL if (IsRightSetinAccessRule(accessrule, FileSystemRights.FullControl)) { IncludeRelationInDictionary(relationToAdd, accessrule.IdentityReference.Value, RelationType.GEN_RIGHT_ALL); } else { // GEN_RIGHT_WRITE if (IsRightSetinAccessRule(accessrule, FileSystemRights.Write)) { IncludeRelationInDictionary(relationToAdd, accessrule.IdentityReference.Value, RelationType.GEN_RIGHT_WRITE); } // STAND_RIGHT_WRITE_DAC if (IsRightSetinAccessRule(accessrule, FileSystemRights.ChangePermissions)) { IncludeRelationInDictionary(relationToAdd, accessrule.IdentityReference.Value, RelationType.STAND_RIGHT_WRITE_DAC); } // STAND_RIGHT_WRITE_OWNER if (IsRightSetinAccessRule(accessrule, FileSystemRights.TakeOwnership)) { IncludeRelationInDictionary(relationToAdd, accessrule.IdentityReference.Value, RelationType.STAND_RIGHT_WRITE_OWNER); } // FILE_WRITEDATA_ADDFILE if (IsRightSetinAccessRule(accessrule, FileSystemRights.WriteData)) { IncludeRelationInDictionary(relationToAdd, accessrule.IdentityReference.Value, RelationType.FS_RIGHT_WRITEDATA_ADDFILE); } // FILE_APPENDDATA_ADDSUBDIR if (IsRightSetinAccessRule(accessrule, FileSystemRights.AppendData)) { IncludeRelationInDictionary(relationToAdd, accessrule.IdentityReference.Value, RelationType.FS_RIGHT_APPENDDATA_ADDSUBDIR); } } } return(relationToAdd); }
public static FileSystemPrincipal GetOwner(FileSystemInfo item, LookupCache cache) { SecurityIdentifier ownerSID = null; IdentityReference ownerNTAccount = null; CachedUserPrincipal ownerPrincipal = null; try { FileSystemSecurity fac = null; if (item is FileInfo) { fac = File.GetAccessControl(item.FullName); } if (item is DirectoryInfo) { fac = Directory.GetAccessControl(item.FullName); } if (fac != null) { ownerSID = fac.GetOwner(typeof(SecurityIdentifier)) as SecurityIdentifier; if (ownerSID != null) { ownerNTAccount = cache.GetName <NTAccount>(FileSystemObjectTypes.NTAccount, ownerSID); ownerPrincipal = cache.GetName <CachedUserPrincipal>(FileSystemObjectTypes.Principal, ownerSID); } } return(new FileSystemPrincipal(ownerSID, ownerNTAccount, ownerPrincipal)); } catch (Exception) { } return(null); }
// filePath is different from filenode // SYSVOL volume cannot be accessed with login / password login // in this case, the server (aka the domain) needs to be replaced with the FQDN of the server private void InsertFile(string filenode, string filepath) { Trace.WriteLine("working on filenode=" + filenode); try { InsertFileNode(filenode); FileSystemInfo info = null; FileAttributes attr = File.GetAttributes(filepath); FileSystemSecurity fss = null; // insert relation related to security descriptor if ((attr & FileAttributes.Directory) == FileAttributes.Directory) { info = new DirectoryInfo(filepath); fss = ((DirectoryInfo)info).GetAccessControl(); } else { info = new FileInfo(filepath); fss = ((FileInfo)info).GetAccessControl(); } InsertFileDescriptorRelation(filenode, fss, false, null); // try to find illegitimate soons if (info as DirectoryInfo != null) { // analyse SD of files in directory AnalyzeFile(filenode, (DirectoryInfo)info, fss.GetOwner(typeof(SecurityIdentifier)).Value); // find hidden relations AnalyzeGPODirectory(filenode, (DirectoryInfo)info); } } catch (Exception ex) { Trace.WriteLine("An exception occured while working on the file '" + filenode + "':" + ex.Message); } }
// return true if there is new relation(s) created private bool InsertFileDescriptorRelation(string filenode, FileSystemSecurity sd, bool skipInherited, string knownOwner) { bool newRelation = false; if (!sd.GetOwner(typeof(SecurityIdentifier)).Value.Equals(knownOwner, StringComparison.InvariantCultureIgnoreCase)) { Storage.InsertRelation(sd.GetOwner(typeof(SecurityIdentifier)).Value, MappingType.Sid, filenode, MappingType.Name, RelationType.FILE_OWNER); newRelation = true; } // relations can be duplicated - will slow down import Dictionary <string, List <RelationType> > relationToAdd = new Dictionary <string, List <RelationType> >(); foreach (FileSystemAccessRule accessrule in sd.GetAccessRules(true, true, typeof(SecurityIdentifier))) { // ignore audit / denied ace if (accessrule.AccessControlType != AccessControlType.Allow) { continue; } if (skipInherited && accessrule.IsInherited) { continue; } // GEN_RIGHT_ALL if ((accessrule.FileSystemRights & FileSystemRights.FullControl) == FileSystemRights.FullControl) { IncludeRelationInDictionary(relationToAdd, accessrule.IdentityReference.Value, RelationType.GEN_RIGHT_ALL); } // GEN_RIGHT_WRITE if ((accessrule.FileSystemRights & FileSystemRights.Write) == FileSystemRights.Write) { IncludeRelationInDictionary(relationToAdd, accessrule.IdentityReference.Value, RelationType.GEN_RIGHT_WRITE); } // STAND_RIGHT_WRITE_DAC if ((accessrule.FileSystemRights & FileSystemRights.ChangePermissions) == FileSystemRights.ChangePermissions) { IncludeRelationInDictionary(relationToAdd, accessrule.IdentityReference.Value, RelationType.STAND_RIGHT_WRITE_DAC); } // STAND_RIGHT_WRITE_OWNER if ((accessrule.FileSystemRights & FileSystemRights.TakeOwnership) == FileSystemRights.TakeOwnership) { IncludeRelationInDictionary(relationToAdd, accessrule.IdentityReference.Value, RelationType.STAND_RIGHT_WRITE_OWNER); } // FILE_WRITEDATA_ADDFILE if ((accessrule.FileSystemRights & FileSystemRights.WriteData) == FileSystemRights.WriteData) { IncludeRelationInDictionary(relationToAdd, accessrule.IdentityReference.Value, RelationType.FS_RIGHT_WRITEDATA_ADDFILE); } // FILE_APPENDDATA_ADDSUBDIR if ((accessrule.FileSystemRights & FileSystemRights.AppendData) == FileSystemRights.AppendData) { IncludeRelationInDictionary(relationToAdd, accessrule.IdentityReference.Value, RelationType.FS_RIGHT_APPENDDATA_ADDSUBDIR); } } foreach (string target in relationToAdd.Keys) { foreach (RelationType link in relationToAdd[target]) { Storage.InsertRelation(target, MappingType.Sid, filenode, MappingType.Name, link); newRelation = true; } } return(newRelation); }
/// <summary> /// Sets the SecurityDescriptor at the specified path. /// </summary> /// <param name="path"> /// The path of the item to set the security descriptor on. /// It may be a drive or provider-qualified path and may include. /// glob characters. /// </param> /// <param name="securityDescriptor"> /// The new security descriptor for the item. /// </param> /// <exception cref="System.ArgumentException"> /// path is null or empty. /// </exception> /// <exception cref="System.ArgumentNullException"> /// securitydescriptor is null. /// </exception> public void SetSecurityDescriptor( string path, ObjectSecurity securityDescriptor) { if (string.IsNullOrEmpty(path)) { throw PSTraceSource.NewArgumentException("path"); } path = NormalizePath(path); if (securityDescriptor == null) { throw PSTraceSource.NewArgumentNullException("securityDescriptor"); } if (!File.Exists(path) && !Directory.Exists(path)) { ThrowTerminatingError(CreateErrorRecord(path, "SetSecurityDescriptor_FileNotFound")); } FileSystemSecurity sd = securityDescriptor as FileSystemSecurity; if (sd == null) { throw PSTraceSource.NewArgumentException("securityDescriptor"); } else { // This algorithm works around the following security descriptor complexities: // // - In order to copy an ACL between files, you need to use the // binary form, and transfer all sections. If you don't use the binary form, // then the FileSystem only applies changes that have happened to that specific // ACL object -- which will not be present if you are just stamping a specific // ACL on a lot of files. // - Copying a full ACL means copying its Audit section, which normal users // don't have access to. // // In order to make this cmdlet support regular users modifying their own files, // the solution is to: // // - First attempt to copy the entire security descriptor as we did in V1. // This ensures backward compatability for administrator scripts that currently // work. // - If the attempt fails due to a PrivilegeNotHeld exception, try again with // an estimate of the minimum required subset. This is an estimate, since the // ACL object doesn't tell you exactly what's changed. // - If their ACL doesn't include any audit rules, don't try to set the // audit section. If it does contain Audit rules, continue to try and // set the section, so they get an appropriate error message. // - If their ACL has the same Owner / Group as the destination file, // also don't try to set those sections. // If they added audit rules, or made changes to the Owner / Group, they will // still get an error message. // // We can't roll the two steps into one, as the second step can't handle the // situation where an admin wants to _clear_ the audit entries. It would be nice to // detect a difference in audit entries (like we do with Owner and Group,) but // retrieving the Audit entries requires SeSecurityPrivilege as well. try { // Try to set the entire security descriptor SetSecurityDescriptor(path, sd, AccessControlSections.All); } catch (PrivilegeNotHeldException) { // Get the security descriptor of the destination path ObjectSecurity existingDescriptor = new FileInfo(path).GetAccessControl(); Type ntAccountType = typeof(System.Security.Principal.NTAccount); AccessControlSections sections = AccessControlSections.All; // If they didn't modify any audit information, don't try to set // the audit section. int auditRuleCount = sd.GetAuditRules(true, true, ntAccountType).Count; if ((auditRuleCount == 0) && (sd.AreAuditRulesProtected == existingDescriptor.AreAccessRulesProtected)) { sections &= ~AccessControlSections.Audit; } // If they didn't modify the owner, don't try to set that section. if (sd.GetOwner(ntAccountType) == existingDescriptor.GetOwner(ntAccountType)) { sections &= ~AccessControlSections.Owner; } // If they didn't modify the group, don't try to set that section. if (sd.GetGroup(ntAccountType) == existingDescriptor.GetGroup(ntAccountType)) { sections &= ~AccessControlSections.Group; } // Try to set the security descriptor again, this time with a reduced set // of sections. SetSecurityDescriptor(path, sd, sections); } } }
internal static void SetAccessControlExtracted(FileSystemSecurity security, string name) { //security.WriteLock(); AccessControlSections includeSections = AccessControlSections.Owner | AccessControlSections.Group; if (security.GetAccessRules(true, false, typeof(SecurityIdentifier)).Count > 0) { includeSections |= AccessControlSections.Access; } if (security.GetAuditRules(true, false, typeof(SecurityIdentifier)).Count > 0) { includeSections |= AccessControlSections.Audit; } SecurityInfos securityInfo = (SecurityInfos)0; SecurityIdentifier owner = null; SecurityIdentifier group = null; SystemAcl sacl = null; DiscretionaryAcl dacl = null; if ((includeSections & AccessControlSections.Owner) != AccessControlSections.None) { owner = (SecurityIdentifier)security.GetOwner(typeof(SecurityIdentifier)); if (owner != null) { securityInfo = securityInfo | SecurityInfos.Owner; } } if ((includeSections & AccessControlSections.Group) != AccessControlSections.None) { @group = (SecurityIdentifier)security.GetGroup(typeof(SecurityIdentifier)); if (@group != null) { securityInfo = securityInfo | SecurityInfos.Group; } } var securityDescriptorBinaryForm = security.GetSecurityDescriptorBinaryForm(); RawSecurityDescriptor rawSecurityDescriptor = null; bool isDiscretionaryAclPresent = false; if (securityDescriptorBinaryForm != null) { rawSecurityDescriptor = new RawSecurityDescriptor(securityDescriptorBinaryForm, 0); isDiscretionaryAclPresent = (rawSecurityDescriptor.ControlFlags & ControlFlags.DiscretionaryAclPresent) != ControlFlags.None; } if ((includeSections & AccessControlSections.Audit) != AccessControlSections.None) { securityInfo = securityInfo | SecurityInfos.SystemAcl; sacl = null; if (rawSecurityDescriptor != null) { var isSystemAclPresent = (rawSecurityDescriptor.ControlFlags & ControlFlags.SystemAclPresent) != ControlFlags.None; if (isSystemAclPresent && rawSecurityDescriptor.SystemAcl != null && rawSecurityDescriptor.SystemAcl.Count > 0) { // are all system acls on a file not a container? const bool notAContainer = false; const bool notADirectoryObjectACL = false; sacl = new SystemAcl(notAContainer, notADirectoryObjectACL, rawSecurityDescriptor.SystemAcl); } securityInfo = (SecurityInfos)(((rawSecurityDescriptor.ControlFlags & ControlFlags.SystemAclProtected) == ControlFlags.None ? (uint)securityInfo | UnprotectedSystemAcl : (uint)securityInfo | ProtectedSystemAcl)); } } if ((includeSections & AccessControlSections.Access) != AccessControlSections.None && isDiscretionaryAclPresent) { securityInfo = securityInfo | SecurityInfos.DiscretionaryAcl; dacl = null; if (rawSecurityDescriptor != null) { //if (!this._securityDescriptor.DiscretionaryAcl.EveryOneFullAccessForNullDacl) { dacl = new DiscretionaryAcl(false, false, rawSecurityDescriptor.DiscretionaryAcl); } securityInfo = (SecurityInfos)(((rawSecurityDescriptor.ControlFlags & ControlFlags.DiscretionaryAclProtected) == ControlFlags.None ? (uint)securityInfo | UnprotectedDiscretionaryAcl : (uint)securityInfo | ProtectedDiscretionaryAcl)); } } if (securityInfo == 0) { return; } int errorNum = SetSecurityInfo(ResourceType.FileObject, name, null, securityInfo, owner, @group, sacl, dacl); if (errorNum != 0) { Exception exception = GetExceptionFromWin32Error(errorNum, name); if (exception == null) { if (errorNum == NativeMethods.ERROR_ACCESS_DENIED) { exception = new UnauthorizedAccessException(); } else if (errorNum == NativeMethods.ERROR_INVALID_OWNER) { exception = new InvalidOperationException("Invalid owner"); } else if (errorNum == NativeMethods.ERROR_INVALID_PRIMARY_GROUP) { exception = new InvalidOperationException("Invalid group"); } else if (errorNum == NativeMethods.ERROR_INVALID_NAME) { exception = new ArgumentException("Invalid name", "name"); } else if (errorNum == NativeMethods.ERROR_INVALID_HANDLE) { exception = new NotSupportedException("Invalid Handle"); } else if (errorNum == NativeMethods.ERROR_FILE_NOT_FOUND) { exception = new FileNotFoundException(); } else if (errorNum != NativeMethods.ERROR_NO_SECURITY_ON_OBJECT) { exception = new InvalidOperationException("Unexpected error"); } else { exception = new NotSupportedException("No associated security"); } } throw exception; } //finally //{ //security.WriteLUnlck(); //} }
public static void SetAccessControlExtracted([NotNull] this FileSystemSecurity security, [NotNull] String name) { if (security == null) { throw new ArgumentNullException(paramName: nameof(security)); } name = name.ThrowIfBlank(); var includeSections = AccessControlSections.Owner | AccessControlSections.Group; if (security.GetAccessRules(true, false, typeof(SecurityIdentifier)).Count > 0) { includeSections |= AccessControlSections.Access; } if (security.GetAuditRules(true, false, typeof(SecurityIdentifier)).Count > 0) { includeSections |= AccessControlSections.Audit; } UInt32 securityInfo = 0; SecurityIdentifier owner = null; SecurityIdentifier group = null; SystemAcl sacl = null; DiscretionaryAcl dacl = null; if ((includeSections & AccessControlSections.Owner) != AccessControlSections.None) { owner = security.GetOwner(typeof(SecurityIdentifier)) as SecurityIdentifier; if (owner != null) { securityInfo |= ( UInt32 )SecurityInfos.Owner; } } if ((includeSections & AccessControlSections.Group) != AccessControlSections.None) { group = security.GetGroup(typeof(SecurityIdentifier)) as SecurityIdentifier; if (group != null) { securityInfo |= ( UInt32 )SecurityInfos.Group; } } var securityDescriptorBinaryForm = security.GetSecurityDescriptorBinaryForm(); var rawSecurityDescriptor = new RawSecurityDescriptor(securityDescriptorBinaryForm, 0); var isDiscretionaryAclPresent = (rawSecurityDescriptor.ControlFlags & ControlFlags.DiscretionaryAclPresent) != ControlFlags.None; if ((includeSections & AccessControlSections.Audit) != AccessControlSections.None) { securityInfo |= ( UInt32 )SecurityInfos.SystemAcl; var isSystemAclPresent = (rawSecurityDescriptor.ControlFlags & ControlFlags.SystemAclPresent) != ControlFlags.None; if (isSystemAclPresent && rawSecurityDescriptor.SystemAcl != null && rawSecurityDescriptor.SystemAcl.Count > 0) { // are all system acls on a file not a container? const Boolean notAContainer = false; const Boolean notADirectoryObjectACL = false; sacl = new SystemAcl(notAContainer, notADirectoryObjectACL, rawSecurityDescriptor.SystemAcl); } if ((rawSecurityDescriptor.ControlFlags & ControlFlags.SystemAclProtected) == ControlFlags.None) { securityInfo |= UnprotectedSystemAcl; } else { securityInfo |= ProtectedSystemAcl; } } if ((includeSections & AccessControlSections.Access) != AccessControlSections.None && isDiscretionaryAclPresent) { securityInfo |= ( UInt32 )SecurityInfos.DiscretionaryAcl; dacl = new DiscretionaryAcl(false, false, rawSecurityDescriptor.DiscretionaryAcl); securityInfo = (rawSecurityDescriptor.ControlFlags & ControlFlags.DiscretionaryAclProtected) == ControlFlags.None ? securityInfo | UnprotectedDiscretionaryAcl : securityInfo | ProtectedDiscretionaryAcl; } if (securityInfo == 0) { return; } var errorNum = SetSecurityInfo(ResourceType.FileObject, name, ( SecurityInfos )securityInfo, owner, group, sacl, dacl); //eh? if (errorNum != 0) { var exception = GetExceptionFromWin32Error(errorNum, name); throw exception; } }
public virtual IdentityReference GetOwner(Type targetType) { return(_fileSystemSecurity.GetOwner(targetType)); }