// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. using System.Collections.ObjectModel; using System.Management.Automation.Provider; using System.Security.AccessControl; namespace System.Management.Automation { /// /// Holds the state of a Monad Shell session /// internal sealed partial class SessionStateInternal { #region private methods /// /// Gets an instance of an ISecurityDescriptorCmdletProvider given the provider ID. /// /// /// /// An instance of a CmdletProvider. /// /// /// /// An instance of a ISecurityDescriptorCmdletProvider for the specified provider ID. /// /// /// /// ArgumentNullException if providerId is null. /// NotSupportedException if the providerId is not for a provider /// that is derived from ISecurityDescriptorCmdletProvider. /// /// internal static ISecurityDescriptorCmdletProvider GetPermissionProviderInstance(CmdletProvider providerInstance) { if (providerInstance == null) { throw PSTraceSource.NewArgumentNullException("providerInstance"); } ISecurityDescriptorCmdletProvider permissionCmdletProvider = providerInstance as ISecurityDescriptorCmdletProvider; if (permissionCmdletProvider == null) { throw PSTraceSource.NewNotSupportedException( ProviderBaseSecurity.ISecurityDescriptorCmdletProvider_NotSupported); } return permissionCmdletProvider; } // GetPermissionProviderInstance #endregion private methods #region GetSecurityDescriptor /// /// Gets the security descriptor from the specified item. /// /// /// /// The path to the item to retrieve the security descriptor from. /// /// /// /// Specifies the parts of a security descriptor to retrieve. /// /// /// /// The security descriptor for the item at the specified path. /// /// internal Collection GetSecurityDescriptor(string path, AccessControlSections sections) { if (path == null) { throw PSTraceSource.NewArgumentNullException("path"); } CmdletProviderContext context = new CmdletProviderContext(this.ExecutionContext); GetSecurityDescriptor(path, sections, context); context.ThrowFirstErrorOrDoNothing(); Collection contextResults = context.GetAccumulatedObjects() ?? new Collection(); return contextResults; } // GetSecurityDescriptor /// /// Gets the security descriptor from the specified item. /// /// /// /// The path to the item to retrieve the security descriptor from. /// /// /// /// Specifies the parts of a security descriptor to retrieve. /// /// /// /// The context which the core command is running. /// /// /// /// Nothing. The security descriptor for the item at the specified path is /// written to the context. /// /// /// /// If does not contain glob characters and /// could not be found. /// /// internal void GetSecurityDescriptor( string path, AccessControlSections sections, CmdletProviderContext context) { if (path == null) { throw PSTraceSource.NewArgumentNullException("path"); } ProviderInfo provider = null; CmdletProvider providerInstance = null; Collection providerPaths = Globber.GetGlobbedProviderPathsFromMonadPath( path, false, context, out provider, out providerInstance); foreach (string providerPath in providerPaths) { GetSecurityDescriptor(providerInstance, providerPath, sections, context); } } // GetSecurityDescriptor private void GetSecurityDescriptor( CmdletProvider providerInstance, string path, AccessControlSections sections, CmdletProviderContext context) { // All parameters should have been validated by caller Diagnostics.Assert( providerInstance != null, "Caller should validate providerInstance before calling this method"); Diagnostics.Assert( path != null, "Caller should validate path before calling this method"); Diagnostics.Assert( context != null, "Caller should validate context before calling this method"); // This just verifies that the provider supports the interface. GetPermissionProviderInstance(providerInstance); try { providerInstance.GetSecurityDescriptor(path, sections, context); } catch (LoopFlowException) { throw; } catch (PipelineStoppedException) { throw; } catch (ActionPreferenceStopException) { throw; } catch (Exception e) // Catch-all OK, 3rd party callout. { throw NewProviderInvocationException( "GetSecurityDescriptorProviderException", SessionStateStrings.GetSecurityDescriptorProviderException, providerInstance.ProviderInfo, path, e); } } // GetSecurityDescriptor #endregion GetSecurityDescriptor #region SetSecurityDescriptor /// /// Sets the security descriptor on the specified item. /// /// /// /// The path to the item to set the security descriptor on. /// /// /// /// The security descriptor to set on the item at the specified path. /// /// /// /// The security descriptor that was set on the item at the specified path. /// /// internal Collection SetSecurityDescriptor(string path, ObjectSecurity securityDescriptor) { if (path == null) { throw PSTraceSource.NewArgumentNullException("path"); } if (securityDescriptor == null) { throw PSTraceSource.NewArgumentNullException("securityDescriptor"); } CmdletProviderContext context = new CmdletProviderContext(this.ExecutionContext); SetSecurityDescriptor(path, securityDescriptor, context); context.ThrowFirstErrorOrDoNothing(); // Return an empty array instead of null Collection contextResults = context.GetAccumulatedObjects() ?? new Collection(); return contextResults; } // SetSecurityDescriptor /// /// Sets the security descriptor on the specified item. /// /// /// /// The path to the item to set the security descriptor on. /// /// /// /// The security descriptor to set on the item at the specified path. /// /// /// /// The context which the core command is running. /// /// /// /// Nothing. The security descriptor that was set on the item at the specified path /// is written to the context. /// /// /// /// If does not contain glob characters and /// could not be found. /// /// internal void SetSecurityDescriptor( string path, ObjectSecurity securityDescriptor, CmdletProviderContext context) { if (path == null) { throw PSTraceSource.NewArgumentNullException("path"); } if (securityDescriptor == null) { throw PSTraceSource.NewArgumentNullException("securityDescriptor"); } ProviderInfo provider = null; CmdletProvider providerInstance = null; Collection providerPaths = Globber.GetGlobbedProviderPathsFromMonadPath( path, false, context, out provider, out providerInstance); foreach (string providerPath in providerPaths) { SetSecurityDescriptor( providerInstance, providerPath, securityDescriptor, context); } } // SetSecurityDescriptor private void SetSecurityDescriptor( CmdletProvider providerInstance, string path, ObjectSecurity securityDescriptor, CmdletProviderContext context) { // All parameters should have been validated by caller Diagnostics.Assert( providerInstance != null, "Caller should validate providerInstance before calling this method"); Diagnostics.Assert( path != null, "Caller should validate path before calling this method"); Diagnostics.Assert( securityDescriptor != null, "Caller should validate securityDescriptor before calling this method"); Diagnostics.Assert( context != null, "Caller should validate context before calling this method"); // This just verifies that the provider supports the interface. GetPermissionProviderInstance(providerInstance); try { providerInstance.SetSecurityDescriptor(path, securityDescriptor, context); } catch (LoopFlowException) { throw; } catch (PipelineStoppedException) { throw; } catch (ActionPreferenceStopException) { throw; } catch (PrivilegeNotHeldException e) { // // thrown if one tries to set SACL and does not have // SeSecurityPrivilege // context.WriteError(new ErrorRecord(e, e.GetType().FullName, ErrorCategory.PermissionDenied, path)); } catch (UnauthorizedAccessException e) { // // thrown if // -- owner or pri. group are invalid OR // -- marta returns ERROR_ACCESS_DENIED // context.WriteError(new ErrorRecord(e, e.GetType().FullName, ErrorCategory.PermissionDenied, path)); } catch (NotSupportedException e) { // // thrown if path points to an item that does not // support access control. // // for example, FAT or FAT32 file in case of file system provider // context.WriteError(new ErrorRecord(e, e.GetType().FullName, ErrorCategory.InvalidOperation, path)); } catch (SystemException e) { // // thrown if the CLR gets back unexpected error // from OS security or marta // context.WriteError(new ErrorRecord(e, e.GetType().FullName, ErrorCategory.InvalidOperation, path)); } catch (Exception e) // Catch-all OK, 3rd party callout. { throw NewProviderInvocationException( "SetSecurityDescriptorProviderException", SessionStateStrings.SetSecurityDescriptorProviderException, providerInstance.ProviderInfo, path, e); } } // SetSecurityDescriptor #endregion SetSecurityDescriptor #region NewSecurityDescriptor /// /// Gets the security descriptor from the specified item. /// /// /// /// The path to the item to retrieve the security descriptor from. /// /// /// /// Specifies the parts of a security descriptor to retrieve. /// /// /// /// Nothing. The security descriptor for the item at the specified path is /// written to the context. /// /// /// /// If does not contain glob characters and /// could not be found. /// /// internal ObjectSecurity NewSecurityDescriptorFromPath( string path, AccessControlSections sections) { ObjectSecurity sd = null; if (path == null) { throw PSTraceSource.NewArgumentNullException("path"); } ProviderInfo provider = null; CmdletProvider providerInstance = null; Collection providerPaths = Globber.GetGlobbedProviderPathsFromMonadPath( path, false, out provider, out providerInstance); // // path must resolve to exact 1 item, // any other case is an error // if (providerPaths.Count == 1) { sd = NewSecurityDescriptorFromPath(providerInstance, providerPaths[0], sections); } else { throw PSTraceSource.NewArgumentException("path"); } return sd; } // NewSecurityDescriptor private ObjectSecurity NewSecurityDescriptorFromPath( CmdletProvider providerInstance, string path, AccessControlSections sections) { ObjectSecurity sd = null; // All parameters should have been validated by caller Diagnostics.Assert( providerInstance != null, "Caller should validate providerInstance before calling this method"); Diagnostics.Assert( path != null, "Caller should validate path before calling this method"); Diagnostics.Assert( ExecutionContext != null, "Caller should validate context before calling this method"); // This just verifies that the provider supports the interface. ISecurityDescriptorCmdletProvider sdProvider = GetPermissionProviderInstance(providerInstance); try { sd = sdProvider.NewSecurityDescriptorFromPath(path, sections); } catch (LoopFlowException) { throw; } catch (PipelineStoppedException) { throw; } catch (ActionPreferenceStopException) { throw; } catch (Exception e) // Catch-all OK, 3rd party callout. { throw NewProviderInvocationException( "NewSecurityDescriptorProviderException", SessionStateStrings.GetSecurityDescriptorProviderException, providerInstance.ProviderInfo, path, e); } return sd; } // NewSecurityDescriptor /// /// Gets the security descriptor from the specified item. /// /// /// /// The type of the item which corresponds to the security /// descriptor that we want to create. /// /// /// /// The name of the provider. /// /// /// /// Specifies the parts of a security descriptor to retrieve. /// /// /// /// Nothing. The security descriptor for the item at the specified type is /// written to the context. /// /// internal ObjectSecurity NewSecurityDescriptorOfType( string providerId, string type, AccessControlSections sections) { CmdletProvider providerInstance = GetProviderInstance(providerId); return NewSecurityDescriptorOfType(providerInstance, type, sections); } /// /// Gets the security descriptor from the specified item. /// /// /// /// The type of the item which corresponds to the security /// descriptor that we want to create. /// /// /// /// The type of the item which corresponds to the security /// descriptor that we want to create. /// /// /// /// Specifies the parts of a security descriptor to retrieve. /// /// /// /// Nothing. The security descriptor for the item at the specified type is /// written to the context. /// /// internal ObjectSecurity NewSecurityDescriptorOfType( CmdletProvider providerInstance, string type, AccessControlSections sections) { ObjectSecurity sd = null; if (type == null) { throw PSTraceSource.NewArgumentNullException("type"); } if (providerInstance == null) { throw PSTraceSource.NewArgumentNullException("providerInstance"); } // This just verifies that the provider supports the interface. ISecurityDescriptorCmdletProvider sdProvider = GetPermissionProviderInstance(providerInstance); try { sd = sdProvider.NewSecurityDescriptorOfType(type, sections); } catch (LoopFlowException) { throw; } catch (PipelineStoppedException) { throw; } catch (ActionPreferenceStopException) { throw; } catch (Exception e) // Catch-all OK, 3rd party callout. { throw NewProviderInvocationException( "NewSecurityDescriptorProviderException", SessionStateStrings.GetSecurityDescriptorProviderException, providerInstance.ProviderInfo, type, e); } return sd; } // NewSecurityDescriptorOfType #endregion NewSecurityDescriptor } }