c748652c34
commit 8cec8f150da7583b7af5efbe2853efee0179750c
203 lines
7.5 KiB
C#
203 lines
7.5 KiB
C#
using System.Runtime.InteropServices;
|
|
using System.Security;
|
|
using System.Security.Principal;
|
|
using System.Text.RegularExpressions;
|
|
|
|
using Microsoft.PowerShell.Commands;
|
|
using Microsoft.PowerShell.LocalAccounts;
|
|
|
|
namespace System.Management.Automation.SecurityAccountsManager.Extensions
|
|
{
|
|
/// <summary>
|
|
/// Provides extension methods for the Cmdlet class
|
|
/// </summary>
|
|
internal static class CmdletExtensions
|
|
{
|
|
/// <summary>
|
|
/// Attempt to create a SID from a string.
|
|
/// </summary>
|
|
/// <param name="cmdlet">The cmdlet being extended with this method.</param>
|
|
/// <param name="s">The string to be converted to a SID.</param>
|
|
/// <param name="allowSidConstants">
|
|
/// A boolean indicating whether SID constants, such as "BA", are considered.
|
|
/// </param>
|
|
/// <returns>
|
|
/// A <see cref="SecurityIdentifier"/> object if the conversion was successful,
|
|
/// null otherwise.
|
|
/// </returns>
|
|
internal static SecurityIdentifier TrySid(this Cmdlet cmdlet,
|
|
string s,
|
|
bool allowSidConstants = false)
|
|
{
|
|
if (!allowSidConstants)
|
|
if (!(s.Length > 2 && s.StartsWith("S-", StringComparison.Ordinal) && Char.IsDigit(s[2])))
|
|
return null;
|
|
|
|
SecurityIdentifier sid = null;
|
|
|
|
try
|
|
{
|
|
sid = new SecurityIdentifier(s);
|
|
}
|
|
catch (ArgumentException)
|
|
{
|
|
// do nothing here, just fall through to the return
|
|
}
|
|
|
|
return sid;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Provides extension methods for the PSCmdlet class
|
|
/// </summary>
|
|
internal static class PSExtensions
|
|
{
|
|
/// <summary>
|
|
/// Determine if a given parameter was provided to the cmdlet
|
|
/// </summary>
|
|
/// <param name="cmdlet">
|
|
/// The <see cref="PSCmdlet"/> object to check.
|
|
/// </param>
|
|
/// <param name="parameterName">
|
|
/// A string containing the name of the parameter. This should be in the
|
|
/// same letter-casing as the defined parameter.
|
|
/// </param>
|
|
/// <returns>
|
|
/// True if the specified parameter was given on the cmdlet invocation,
|
|
/// false otherwise.
|
|
/// </returns>
|
|
internal static bool HasParameter(this PSCmdlet cmdlet, string parameterName)
|
|
{
|
|
var invocation = cmdlet.MyInvocation;
|
|
if (invocation != null)
|
|
{
|
|
var parameters = invocation.BoundParameters;
|
|
|
|
if (parameters != null)
|
|
{
|
|
// PowerShell sets the parameter names in the BoundParameters dictionary
|
|
// to their "proper" casing, so we don't have to do a case-insensitive search.
|
|
if (parameters.ContainsKey(parameterName))
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Provides extension methods for the SecurityIdentifier class.
|
|
/// </summary>
|
|
internal static class SidExtensions
|
|
{
|
|
/// <summary>
|
|
/// Get the Relative ID (RID) from a <see cref="SecurityIdentifier"/> object.
|
|
/// </summary>
|
|
/// <param name="sid">The SecurityIdentifier containing the desired Relative ID.</param>
|
|
/// <returns>
|
|
/// A UInt32 value containing the Relative ID in the SecurityIdentifier.
|
|
/// </returns>
|
|
internal static UInt32 GetRid(this SecurityIdentifier sid)
|
|
{
|
|
byte[] sidBinary = new byte[sid.BinaryLength];
|
|
sid.GetBinaryForm(sidBinary, 0);
|
|
|
|
return System.BitConverter.ToUInt32(sidBinary, sidBinary.Length-4);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the Identifier Authority portion of a <see cref="SecurityIdentifier"/>
|
|
/// </summary>
|
|
/// <param name="sid">The SecurityIdentifier containing the desired Authority.</param>
|
|
/// <returns>
|
|
/// A long integer value containing the SecurityIdentifier's Identifier Authority value.
|
|
/// </returns>
|
|
/// <remarks>
|
|
/// This method is used primarily for determining the Source of a Principal.
|
|
/// The Win32 API LsaLookupUserAccountType function does not (yet) properly
|
|
/// identify MicrosoftAccount principals.
|
|
/// </remarks>
|
|
internal static long GetIdentifierAuthority(this SecurityIdentifier sid)
|
|
{
|
|
byte[] sidBinary = new byte[sid.BinaryLength];
|
|
|
|
sid.GetBinaryForm(sidBinary, 0);
|
|
|
|
// The Identifier Authority is six bytes wide,
|
|
// in big-endian format, starting at the third byte
|
|
long authority = (long) (((long)sidBinary[2]) << 40) +
|
|
(((long)sidBinary[3]) << 32) +
|
|
(((long)sidBinary[4]) << 24) +
|
|
(((long)sidBinary[5]) << 16) +
|
|
(((long)sidBinary[6]) << 8) +
|
|
(((long)sidBinary[7]) );
|
|
|
|
return authority;
|
|
}
|
|
|
|
internal static bool IsMsaAccount(this SecurityIdentifier sid)
|
|
{
|
|
return sid.GetIdentifierAuthority() == 11;
|
|
}
|
|
}
|
|
|
|
internal static class SecureStringExtensions
|
|
{
|
|
/// <summary>
|
|
/// Extension method to extract clear text from a
|
|
/// <see cref="System.Security.SecureString"/> object.
|
|
/// </summary>
|
|
/// <param name="str">
|
|
/// This SecureString object, containing encrypted text.
|
|
/// </param>
|
|
/// <returns>
|
|
/// A string containing the SecureString object's original text.
|
|
/// </returns>
|
|
internal static string AsString(this SecureString str)
|
|
{
|
|
#if CORECLR
|
|
IntPtr buffer = SecureStringMarshal.SecureStringToCoTaskMemUnicode(str);
|
|
string clear = Marshal.PtrToStringUni(buffer);
|
|
SecureStringMarshal.ZeroFreeCoTaskMemUnicode(buffer);
|
|
#else
|
|
var bstr = Marshal.SecureStringToBSTR(str);
|
|
string clear = Marshal.PtrToStringAuto(bstr);
|
|
Marshal.ZeroFreeBSTR(bstr);
|
|
#endif
|
|
return clear;
|
|
}
|
|
}
|
|
|
|
internal static class ExceptionExtensions
|
|
{
|
|
internal static ErrorRecord MakeErrorRecord(this Exception ex,
|
|
string errorId,
|
|
ErrorCategory errorCategory,
|
|
object target = null)
|
|
{
|
|
return new ErrorRecord(ex, errorId, errorCategory, target);
|
|
}
|
|
|
|
internal static ErrorRecord MakeErrorRecord(this Exception ex, object target = null)
|
|
{
|
|
// This part is somewhat less than beautiful, but it prevents
|
|
// having to have multiple exception handlers in every cmdlet command.
|
|
var exTemp = ex as LocalAccountsException;
|
|
|
|
if (exTemp != null)
|
|
return MakeErrorRecord(exTemp, target ?? exTemp.Target);
|
|
|
|
return new ErrorRecord(ex,
|
|
Strings.UnspecifiedError,
|
|
ErrorCategory.NotSpecified,
|
|
target);
|
|
}
|
|
|
|
internal static ErrorRecord MakeErrorRecord(this LocalAccountsException ex, object target = null)
|
|
{
|
|
return ex.MakeErrorRecord(ex.ErrorName, ex.ErrorCategory, target ?? ex.Target);
|
|
}
|
|
}
|
|
} |