Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / clr / src / BCL / System / Security / Principal / SID.cs / 1 / SID.cs
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;
using System;
using System.Security.Permissions;
using System.Text;
using System.Runtime.InteropServices;
using System.Globalization;
namespace System.Security.Principal
{
//
// Identifier authorities
//
internal enum IdentifierAuthority : long
{
NullAuthority = 0,
WorldAuthority = 1,
LocalAuthority = 2,
CreatorAuthority = 3,
NonUniqueAuthority = 4,
NTAuthority = 5,
SiteServerAuthority = 6,
InternetSiteAuthority = 7,
ExchangeAuthority = 8,
ResourceManagerAuthority = 9,
}
//
// SID name usage
//
internal enum SidNameUse
{
User = 1,
Group = 2,
Domain = 3,
Alias = 4,
WellKnownGroup = 5,
DeletedAccount = 6,
Invalid = 7,
Unknown = 8,
Computer = 9,
}
//
// Well-known SID types
//
[System.Runtime.InteropServices.ComVisible(false)]
public enum WellKnownSidType
{
NullSid = 0,
WorldSid = 1,
LocalSid = 2,
CreatorOwnerSid = 3,
CreatorGroupSid = 4,
CreatorOwnerServerSid = 5,
CreatorGroupServerSid = 6,
NTAuthoritySid = 7,
DialupSid = 8,
NetworkSid = 9,
BatchSid = 10,
InteractiveSid = 11,
ServiceSid = 12,
AnonymousSid = 13,
ProxySid = 14,
EnterpriseControllersSid = 15,
SelfSid = 16,
AuthenticatedUserSid = 17,
RestrictedCodeSid = 18,
TerminalServerSid = 19,
RemoteLogonIdSid = 20,
LogonIdsSid = 21,
LocalSystemSid = 22,
LocalServiceSid = 23,
NetworkServiceSid = 24,
BuiltinDomainSid = 25,
BuiltinAdministratorsSid = 26,
BuiltinUsersSid = 27,
BuiltinGuestsSid = 28,
BuiltinPowerUsersSid = 29,
BuiltinAccountOperatorsSid = 30,
BuiltinSystemOperatorsSid = 31,
BuiltinPrintOperatorsSid = 32,
BuiltinBackupOperatorsSid = 33,
BuiltinReplicatorSid = 34,
BuiltinPreWindows2000CompatibleAccessSid = 35,
BuiltinRemoteDesktopUsersSid = 36,
BuiltinNetworkConfigurationOperatorsSid = 37,
AccountAdministratorSid = 38,
AccountGuestSid = 39,
AccountKrbtgtSid = 40,
AccountDomainAdminsSid = 41,
AccountDomainUsersSid = 42,
AccountDomainGuestsSid = 43,
AccountComputersSid = 44,
AccountControllersSid = 45,
AccountCertAdminsSid = 46,
AccountSchemaAdminsSid = 47,
AccountEnterpriseAdminsSid = 48,
AccountPolicyAdminsSid = 49,
AccountRasAndIasServersSid = 50,
NtlmAuthenticationSid = 51,
DigestAuthenticationSid = 52,
SChannelAuthenticationSid = 53,
ThisOrganizationSid = 54,
OtherOrganizationSid = 55,
BuiltinIncomingForestTrustBuildersSid = 56,
BuiltinPerformanceMonitoringUsersSid = 57,
BuiltinPerformanceLoggingUsersSid = 58,
BuiltinAuthorizationAccessSid = 59,
WinBuiltinTerminalServerLicenseServersSid= 60,
MaxDefined = WinBuiltinTerminalServerLicenseServersSid,
}
//
// This class implements revision 1 SIDs
// NOTE: The SecurityIdentifier class is immutable and must remain this way
//
[System.Runtime.InteropServices.ComVisible(false)]
public sealed class SecurityIdentifier : IdentityReference, IComparable
{
#region Public Constants
//
// Identifier authority must be at most six bytes long
//
internal static readonly long MaxIdentifierAuthority = 0xFFFFFFFFFFFF;
//
// Maximum number of subauthorities in a SID
//
internal static readonly byte MaxSubAuthorities = 15;
//
// Minimum length of a binary representation of a SID
//
public static readonly int MinBinaryLength = 1 + 1 + 6; // Revision (1) + subauth count (1) + identifier authority (6)
//
// Maximum length of a binary representation of a SID
//
public static readonly int MaxBinaryLength = 1 + 1 + 6 + MaxSubAuthorities * 4; // 4 bytes for each subauth
#endregion
#region Private Members
//
// Immutable properties of a SID
//
private IdentifierAuthority _IdentifierAuthority;
private int[] _SubAuthorities;
private byte[] _BinaryForm;
private SecurityIdentifier _AccountDomainSid;
bool _AccountDomainSidInitialized = false;
//
// Computed attributes of a SID
//
private string _SddlForm = null;
#endregion
#region Constructors
//
// Shared constructor logic
// NOTE: subauthorities are really unsigned integers, but due to CLS
// lack of support for unsigned integers the caller must perform
// the typecast
//
private void CreateFromParts( IdentifierAuthority identifierAuthority, int[] subAuthorities )
{
if ( subAuthorities == null )
{
throw new ArgumentNullException( "subAuthorities" );
}
//
// Check the number of subauthorities passed in
//
if ( subAuthorities.Length > MaxSubAuthorities )
{
throw new ArgumentOutOfRangeException(
"subAuthorities.Length",
subAuthorities.Length,
Environment.GetResourceString( "IdentityReference_InvalidNumberOfSubauthorities", MaxSubAuthorities));
}
//
// Identifier authority is atmost 6 bytes long
//
if ( identifierAuthority < 0 ||
(long) identifierAuthority > MaxIdentifierAuthority )
{
throw new ArgumentOutOfRangeException(
"identifierAuthority",
identifierAuthority,
Environment.GetResourceString( "IdentityReference_IdentifierAuthorityTooLarge" ));
}
//
// Create a local copy of the data passed in
//
_IdentifierAuthority = identifierAuthority;
_SubAuthorities = new int[ subAuthorities.Length ];
subAuthorities.CopyTo( _SubAuthorities, 0 );
//
// Compute and store the binary form
//
// typedef struct _SID {
// UCHAR Revision;
// UCHAR SubAuthorityCount;
// SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
// ULONG SubAuthority[ANYSIZE_ARRAY]
// } SID, *PISID;
//
byte i;
_BinaryForm = new byte[1 + 1 + 6 + 4 * this.SubAuthorityCount];
//
// First two bytes contain revision and subauthority count
//
_BinaryForm[0] = Revision;
_BinaryForm[1] = ( byte )this.SubAuthorityCount;
//
// Identifier authority takes up 6 bytes
//
for ( i = 0; i < 6; i++ )
{
_BinaryForm[2+i] = ( byte )(((( ulong )this._IdentifierAuthority ) >> (( 5 - i ) * 8 )) & 0xFF ) ;
}
//
// Subauthorities go last, preserving big-endian representation
//
for ( i = 0; i < this.SubAuthorityCount; i++ )
{
byte shift;
for ( shift = 0; shift < 4; shift += 1 )
{
_BinaryForm[8 + 4*i + shift] = ( byte )((( ulong )_SubAuthorities[i] ) >> ( shift * 8 ));
}
}
}
private void CreateFromBinaryForm( byte[] binaryForm, int offset )
{
IdentifierAuthority Authority;
int[] SubAuthorities;
//
// Give us something to work with
//
if ( binaryForm == null )
{
throw new ArgumentNullException( "binaryForm" );
}
//
// Negative offsets are not allowed
//
if ( offset < 0 )
{
throw new ArgumentOutOfRangeException(
"offset",
offset,
Environment.GetResourceString( "ArgumentOutOfRange_NeedNonNegNum" ));
}
//
// At least a minimum-size SID should fit in the buffer
//
if ( binaryForm.Length - offset < SecurityIdentifier.MinBinaryLength )
{
throw new ArgumentOutOfRangeException(
"binaryForm",
Environment.GetResourceString( "ArgumentOutOfRange_ArrayTooSmall" ));
}
//
// Extract the elements of a SID
//
if ( binaryForm[offset] != Revision )
{
//
// Revision is incorrect
//
throw new ArgumentException(
Environment.GetResourceString( "IdentityReference_InvalidSidRevision" ),
"binaryForm" );
}
//
// Insist on the correct number of subauthorities
//
if ( binaryForm[offset + 1] > MaxSubAuthorities )
{
throw new ArgumentException(
Environment.GetResourceString( "IdentityReference_InvalidNumberOfSubauthorities", MaxSubAuthorities ),
"binaryForm" );
}
//
// Make sure the buffer is big enough
//
int Length = 1 + 1 + 6 + 4 * binaryForm[offset + 1];
if ( binaryForm.Length - offset < Length )
{
throw new ArgumentException(
Environment.GetResourceString( "ArgumentOutOfRange_ArrayTooSmall" ),
"binaryForm" );
}
Authority =
( IdentifierAuthority )(
((( long )binaryForm[offset + 2]) << 40 ) +
((( long )binaryForm[offset + 3]) << 32 ) +
((( long )binaryForm[offset + 4]) << 24 ) +
((( long )binaryForm[offset + 5]) << 16 ) +
((( long )binaryForm[offset + 6]) << 8 ) +
((( long )binaryForm[offset + 7]) ));
SubAuthorities = new int[binaryForm[offset + 1]];
//
// Subauthorities are represented in big-endian format
//
for ( byte i = 0; i < binaryForm[offset + 1]; i++ )
{
SubAuthorities[i] =
( int )(
((( uint )binaryForm[offset + 8 + 4*i + 0]) << 0 ) +
((( uint )binaryForm[offset + 8 + 4*i + 1]) << 8 ) +
((( uint )binaryForm[offset + 8 + 4*i + 2]) << 16 ) +
((( uint )binaryForm[offset + 8 + 4*i + 3]) << 24 ));
}
CreateFromParts( Authority, SubAuthorities );
return;
}
//
// Constructs a SecurityIdentifier object from its string representation
// Returns 'null' if string passed in is not a valid SID
// NOTE: although there is a P/Invoke call involved in the implementation of this method,
// there is no security risk involved, so no security demand is being made.
//
public SecurityIdentifier( string sddlForm )
{
byte[] resultSid;
//
// Give us something to work with
//
if ( sddlForm == null )
{
throw new ArgumentNullException( "sddlForm" );
}
//
// Call into the underlying O/S conversion routine
//
int Error = Win32.CreateSidFromString( sddlForm, out resultSid );
if ( Error == Win32Native.ERROR_INVALID_SID )
{
throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidValue" ), "sddlForm" );
}
else if ( Error == Win32Native.ERROR_NOT_ENOUGH_MEMORY )
{
throw new OutOfMemoryException();
}
else if ( Error != Win32Native.ERROR_SUCCESS )
{
BCLDebug.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32.CreateSidFromString returned unrecognized error {0}", Error ));
throw new SystemException(Win32Native.GetMessage(Error));
}
CreateFromBinaryForm( resultSid, 0 );
}
//
// Constructs a SecurityIdentifier object from its binary representation
//
public SecurityIdentifier( byte[] binaryForm, int offset )
{
CreateFromBinaryForm( binaryForm, offset );
}
//
// Constructs a SecurityIdentifier object from an IntPtr
//
[SecurityPermission(SecurityAction.Demand, UnmanagedCode=true)]
public SecurityIdentifier( IntPtr binaryForm )
: this( binaryForm, true )
{
}
internal SecurityIdentifier( IntPtr binaryForm, bool noDemand )
: this( Win32.ConvertIntPtrSidToByteArraySid( binaryForm ), 0 )
{
}
//
// Constructs a well-known SID
// The 'domainSid' parameter is optional and only used
// by the well-known types that require it
// NOTE: although there is a P/Invoke call involved in the implementation of this constructor,
// there is no security risk involved, so no security demand is being made.
//
public SecurityIdentifier( WellKnownSidType sidType, SecurityIdentifier domainSid )
{
byte[] resultSid;
int Error;
//
// Check if well known sids are supported on this platform
//
if (!Win32.WellKnownSidApisSupported) {
throw new PlatformNotSupportedException( Environment.GetResourceString( "PlatformNotSupported_RequiresW2kSP3" ));
}
//
// sidType must not be equal to LogonIdsSid
//
if (sidType == WellKnownSidType.LogonIdsSid)
{
throw new ArgumentException( Environment.GetResourceString( "IdentityReference_CannotCreateLogonIdsSid" ), "sidType" );
}
//
// sidType should not exceed the max defined value
//
if ((sidType < WellKnownSidType.NullSid) || (sidType > WellKnownSidType.MaxDefined))
{
throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidValue" ), "sidType" );
}
//
// for sidType between 38 to 50, the domainSid parameter must be specified
//
if ((sidType >= WellKnownSidType.AccountAdministratorSid) && (sidType <= WellKnownSidType.AccountRasAndIasServersSid))
{
if (domainSid == null) {
throw new ArgumentNullException( "domainSid", Environment.GetResourceString( "IdentityReference_DomainSidRequired", sidType) );
}
//
// verify that the domain sid is a valid windows domain sid
// to do that we call GetAccountDomainSid and the return value should be the same as the domainSid
//
SecurityIdentifier resultDomainSid;
int ErrorCode;
ErrorCode = Win32.GetWindowsAccountDomainSid( domainSid, out resultDomainSid );
if ( ErrorCode == Win32Native.ERROR_INSUFFICIENT_BUFFER ) {
throw new OutOfMemoryException();
}
else if ( ErrorCode == Win32Native.ERROR_NON_ACCOUNT_SID )
{
// this means that the domain sid is not valid
throw new ArgumentException( Environment.GetResourceString( "IdentityReference_NotAWindowsDomain" ), "domainSid" );
}
else if ( ErrorCode != Win32Native.ERROR_SUCCESS )
{
BCLDebug.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32.GetWindowsAccountDomainSid returned unrecognized error {0}", ErrorCode) );
throw new SystemException(Win32Native.GetMessage(ErrorCode));
}
//
// if domainSid is passed in as S-1-5-21-3-4-5-6, the above api will return S-1-5-21-3-4-5 as the domainSid
// Since these do not match S-1-5-21-3-4-5-6 is not a valid domainSid (wrong number of subauthorities)
//
if (resultDomainSid != domainSid) {
throw new ArgumentException( Environment.GetResourceString( "IdentityReference_NotAWindowsDomain" ), "domainSid" );
}
}
Error = Win32.CreateWellKnownSid( sidType, domainSid, out resultSid );
if ( Error == Win32Native.ERROR_INVALID_PARAMETER )
{
throw new ArgumentException( Win32Native.GetMessage(Error), "sidType/domainSid" );
}
else if ( Error != Win32Native.ERROR_SUCCESS )
{
BCLDebug.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32.CreateWellKnownSid returned unrecognized error {0}", Error ));
throw new SystemException( Win32Native.GetMessage( Error ));
}
CreateFromBinaryForm( resultSid, 0 );
}
internal SecurityIdentifier( SecurityIdentifier domainSid, uint rid )
{
int i;
int[] SubAuthorities = new int[ domainSid.SubAuthorityCount + 1 ];
for ( i = 0; i < domainSid.SubAuthorityCount; i++ )
{
SubAuthorities[i] = domainSid.GetSubAuthority( i );
}
SubAuthorities[i] = ( int )rid;
CreateFromParts( domainSid.IdentifierAuthority, SubAuthorities );
}
internal SecurityIdentifier( IdentifierAuthority identifierAuthority, int[] subAuthorities )
{
CreateFromParts( identifierAuthority, subAuthorities );
}
#endregion
#region Static Properties
//
// Revision is always '1'
//
internal static byte Revision
{
get { return 1; }
}
#endregion
#region Non-static Properties
//
// This is for internal consumption only, hence it is marked 'internal'
// Making this call public would require a deep copy of the data to
// prevent the caller from messing with the internal representation.
//
internal byte[] BinaryForm
{
get { return _BinaryForm; }
}
internal IdentifierAuthority IdentifierAuthority
{
get { return _IdentifierAuthority; }
}
internal int SubAuthorityCount
{
get { return _SubAuthorities.Length; }
}
public int BinaryLength
{
get
{
return _BinaryForm.Length;
}
}
//
// Returns the domain portion of a SID or null if the specified
// SID is not an account SID
// NOTE: although there is a P/Invoke call involved in the implementation of this method,
// there is no security risk involved, so no security demand is being made.
//
public SecurityIdentifier AccountDomainSid
{
get
{
if ( !_AccountDomainSidInitialized )
{
_AccountDomainSid = GetAccountDomainSid();
_AccountDomainSidInitialized = true;
}
return _AccountDomainSid;
}
}
#endregion
#region Inherited properties and methods
public override bool Equals( object o )
{
if ( o == null )
{
return false;
}
SecurityIdentifier sid = o as SecurityIdentifier;
if ( sid == null )
{
return false;
}
return ( this == sid ); // invokes operator==
}
public bool Equals( SecurityIdentifier sid )
{
if ( sid == null )
{
return false;
}
return ( this == sid ); // invokes operator==
}
public override int GetHashCode() {
int hashCode = ((long)this.IdentifierAuthority).GetHashCode();
for(int i = 0; i < SubAuthorityCount; i++) {
hashCode ^= this.GetSubAuthority(i);
}
return hashCode;
}
public override string ToString()
{
if ( _SddlForm == null )
{
StringBuilder result = new StringBuilder();
//
// Typecasting of _IdentifierAuthority to a long below is important, since
// otherwise you would see this: "S-1-NTAuthority-32-544"
//
result.AppendFormat( "S-1-{0}", ( long )_IdentifierAuthority );
for ( int i = 0; i < SubAuthorityCount; i++ )
{
result.AppendFormat( "-{0}", ( uint )( _SubAuthorities[i] ));
}
_SddlForm = result.ToString();
}
return _SddlForm;
}
#if false
public override string Scheme
{
get { return "ms-sid"; }
}
#endif
public override string Value
{
get { return ToString().ToUpper(CultureInfo.InvariantCulture); }
}
internal static bool IsValidTargetTypeStatic( Type targetType )
{
if ( targetType == typeof( NTAccount ))
{
return true;
}
else if ( targetType == typeof( SecurityIdentifier ))
{
return true;
}
else
{
return false;
}
}
public override bool IsValidTargetType( Type targetType )
{
return IsValidTargetTypeStatic( targetType );
}
internal SecurityIdentifier GetAccountDomainSid()
{
SecurityIdentifier ResultSid;
int Error;
Error = Win32.GetWindowsAccountDomainSid( this, out ResultSid );
if ( Error == Win32Native.ERROR_INSUFFICIENT_BUFFER )
{
throw new OutOfMemoryException();
}
else if ( Error == Win32Native.ERROR_NON_ACCOUNT_SID )
{
ResultSid = null;
}
else if ( Error != Win32Native.ERROR_SUCCESS )
{
BCLDebug.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32.GetWindowsAccountDomainSid returned unrecognized error {0}", Error) );
throw new SystemException(Win32Native.GetMessage(Error));
}
return ResultSid;
}
public bool IsAccountSid() {
if ( !_AccountDomainSidInitialized )
{
_AccountDomainSid = GetAccountDomainSid();
_AccountDomainSidInitialized = true;
}
if (_AccountDomainSid == null) {
return false;
}
return true;
}
public override IdentityReference Translate( Type targetType )
{
if ( targetType == null )
{
throw new ArgumentNullException( "targetType" );
}
if ( targetType == typeof( SecurityIdentifier ))
{
return this; // assumes SecurityIdentifier objects are immutable
}
else if ( targetType == typeof( NTAccount ))
{
IdentityReferenceCollection irSource = new IdentityReferenceCollection( 1 );
irSource.Add( this );
IdentityReferenceCollection irTarget;
irTarget = SecurityIdentifier.Translate( irSource, targetType, true );
return irTarget[0];
}
else
{
throw new ArgumentException( Environment.GetResourceString( "IdentityReference_MustBeIdentityReference" ), "targetType" );
}
}
#endregion
#region Operators
public static bool operator== ( SecurityIdentifier left, SecurityIdentifier right )
{
object l = left;
object r = right;
if ( l == null && r == null )
{
return true;
}
else if ( l == null || r == null )
{
return false;
}
else
{
return ( left.CompareTo( right ) == 0 );
}
}
public static bool operator!= ( SecurityIdentifier left, SecurityIdentifier right )
{
return !( left == right );
}
#endregion
#region IComparable implementation
public int CompareTo( SecurityIdentifier sid )
{
if ( sid == null )
{
throw new ArgumentNullException( "sid" );
}
if ( this.IdentifierAuthority < sid.IdentifierAuthority )
{
return -1;
}
if ( this.IdentifierAuthority > sid.IdentifierAuthority )
{
return 1;
}
if ( this.SubAuthorityCount < sid.SubAuthorityCount )
{
return -1;
}
if ( this.SubAuthorityCount > sid.SubAuthorityCount )
{
return 1;
}
for ( int i = 0; i < this.SubAuthorityCount; i++ )
{
int diff = this.GetSubAuthority( i ) - sid.GetSubAuthority( i );
if ( diff != 0 )
{
return diff;
}
}
return 0;
}
#endregion
#region Public Methods
internal int GetSubAuthority( int index )
{
return this._SubAuthorities[ index ];
}
//
// Determines whether this SID is a well known SID of the specified type
//
// NOTE: although there is a P/Invoke call involved in the implementation of this method,
// there is no security risk involved, so no security demand is being made.
//
public bool IsWellKnown( WellKnownSidType type )
{
return Win32.IsWellKnownSid( this, type );
}
public void GetBinaryForm( byte[] binaryForm, int offset )
{
_BinaryForm.CopyTo( binaryForm, offset );
}
//
// NOTE: although there is a P/Invoke call involved in the implementation of this method,
// there is no security risk involved, so no security demand is being made.
//
public bool IsEqualDomainSid( SecurityIdentifier sid )
{
return Win32.IsEqualDomainSid( this, sid );
}
private static IdentityReferenceCollection TranslateToNTAccounts( IdentityReferenceCollection sourceSids, out bool someFailed )
{
//
// Check if the lsa api is supported
//
if (!Win32.LsaApisSupported) {
throw new PlatformNotSupportedException( Environment.GetResourceString( "PlatformNotSupported_Win9x" ));
}
IntPtr[] SidArrayPtr = new IntPtr[ sourceSids.Count ];
GCHandle[] HandleArray = new GCHandle[ sourceSids.Count ];
SafeLsaPolicyHandle LsaHandle = SafeLsaPolicyHandle.InvalidHandle;
SafeLsaMemoryHandle ReferencedDomainsPtr = SafeLsaMemoryHandle.InvalidHandle;
SafeLsaMemoryHandle NamesPtr = SafeLsaMemoryHandle.InvalidHandle;
int i = 0;
if ( sourceSids == null )
{
throw new ArgumentNullException( "sourceSids" );
}
if ( sourceSids.Count == 0 )
{
throw new ArgumentException( Environment.GetResourceString( "Arg_EmptyCollection" ), "sourceSids" );
}
try
{
//
// Pin all elements in the array of SIDs
//
foreach ( IdentityReference id in sourceSids )
{
SecurityIdentifier sid = id as SecurityIdentifier;
if ( sid == null )
{
throw new ArgumentException( Environment.GetResourceString( "Argument_ImproperType" ), "sourceSids" );
}
HandleArray[i] = GCHandle.Alloc( sid.BinaryForm, GCHandleType.Pinned );
SidArrayPtr[i] = HandleArray[i].AddrOfPinnedObject();
i++;
}
//
// Open LSA policy (for lookup requires it)
//
LsaHandle = Win32.LsaOpenPolicy( null, PolicyRights.POLICY_LOOKUP_NAMES );
//
// Perform the actual lookup
//
someFailed = false;
uint ReturnCode;
ReturnCode = Win32Native.LsaLookupSids( LsaHandle, sourceSids.Count, SidArrayPtr, ref ReferencedDomainsPtr, ref NamesPtr );
//
// Make a decision regarding whether it makes sense to proceed
// based on the return code and the value of the forceSuccess argument
//
if ( ReturnCode == Win32Native.STATUS_NO_MEMORY ||
ReturnCode == Win32Native.STATUS_INSUFFICIENT_RESOURCES )
{
throw new OutOfMemoryException();
}
else if ( ReturnCode == Win32Native.STATUS_ACCESS_DENIED )
{
throw new UnauthorizedAccessException();
}
else if ( ReturnCode == Win32Native.STATUS_NONE_MAPPED ||
ReturnCode == Win32Native.STATUS_SOME_NOT_MAPPED )
{
someFailed = true;
}
else if ( ReturnCode != 0 )
{
int win32ErrorCode = Win32Native.LsaNtStatusToWinError(unchecked((int)ReturnCode));
BCLDebug.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32Native.LsaLookupSids returned {0}", win32ErrorCode));
throw new SystemException(Win32Native.GetMessage(win32ErrorCode));
}
//
// Interpret the results and generate NTAccount objects
//
IdentityReferenceCollection Result = new IdentityReferenceCollection( sourceSids.Count );
if ( ReturnCode == 0 || ReturnCode == Win32Native.STATUS_SOME_NOT_MAPPED )
{
//
// Interpret the results and generate NT Account objects
//
Win32Native.LSA_REFERENCED_DOMAIN_LIST rdl = ( Win32Native.LSA_REFERENCED_DOMAIN_LIST )Marshal.PtrToStructure( ReferencedDomainsPtr.DangerousGetHandle(), typeof( Win32Native.LSA_REFERENCED_DOMAIN_LIST ));
string[] ReferencedDomains = new string[ rdl.Entries ];
for ( i = 0; i < rdl.Entries; i++ )
{
Win32Native.LSA_TRUST_INFORMATION ti = ( Win32Native.LSA_TRUST_INFORMATION )Marshal.PtrToStructure( new IntPtr(( long )rdl.Domains + i * Marshal.SizeOf( typeof( Win32Native.LSA_TRUST_INFORMATION ))), typeof( Win32Native.LSA_TRUST_INFORMATION ));
ReferencedDomains[i] = Marshal.PtrToStringUni( ti.Name.Buffer, ti.Name.Length/2 );
}
for ( i = 0; i < sourceSids.Count; i++ )
{
Win32Native.LSA_TRANSLATED_NAME Ltn;
SidNameUse Use;
string Account;
string Domain;
Ltn = ( Win32Native.LSA_TRANSLATED_NAME )Marshal.PtrToStructure( new IntPtr(( long )NamesPtr.DangerousGetHandle() + i * Marshal.SizeOf( typeof( Win32Native.LSA_TRANSLATED_NAME ))), typeof( Win32Native.LSA_TRANSLATED_NAME ));
Use = ( SidNameUse )Ltn.Use;
switch ( Use )
{
case SidNameUse.User:
goto case SidNameUse.WellKnownGroup;
case SidNameUse.Group:
goto case SidNameUse.WellKnownGroup;
case SidNameUse.Alias:
goto case SidNameUse.WellKnownGroup;
case SidNameUse.Computer:
goto case SidNameUse.WellKnownGroup;
case SidNameUse.WellKnownGroup:
Account = Marshal.PtrToStringUni( Ltn.Name.Buffer, Ltn.Name.Length/2 );
Domain = ReferencedDomains[ Ltn.DomainIndex ];
Result.Add( new NTAccount( Domain, Account ));
break;
default:
someFailed = true;
Result.Add( sourceSids[i] );
break;
}
}
}
else
{
for ( i = 0; i < sourceSids.Count; i++ )
{
Result.Add( sourceSids[i] );
}
}
return Result;
}
finally
{
for ( i = 0; i < sourceSids.Count; i++ )
{
if ( HandleArray[i].IsAllocated )
{
HandleArray[i].Free();
}
}
LsaHandle.Dispose();
ReferencedDomainsPtr.Dispose();
NamesPtr.Dispose();
}
}
internal static IdentityReferenceCollection Translate( IdentityReferenceCollection sourceSids, Type targetType, bool forceSuccess)
{
bool SomeFailed = false;
IdentityReferenceCollection Result;
Result = Translate( sourceSids, targetType, out SomeFailed );
if (forceSuccess && SomeFailed) {
IdentityReferenceCollection UnmappedIdentities = new IdentityReferenceCollection();
foreach (IdentityReference id in Result)
{
if (id.GetType() != targetType)
{
UnmappedIdentities.Add(id);
}
}
throw new IdentityNotMappedException(Environment.GetResourceString("IdentityReference_IdentityNotMapped"), UnmappedIdentities);
}
return Result;
}
internal static IdentityReferenceCollection Translate( IdentityReferenceCollection sourceSids, Type targetType, out bool someFailed )
{
if ( sourceSids == null )
{
throw new ArgumentNullException( "sourceSids" );
}
if ( targetType == typeof( NTAccount ))
{
return TranslateToNTAccounts( sourceSids, out someFailed );
}
throw new ArgumentException( Environment.GetResourceString( "IdentityReference_MustBeIdentityReference" ), "targetType" );
}
#endregion
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;
using System;
using System.Security.Permissions;
using System.Text;
using System.Runtime.InteropServices;
using System.Globalization;
namespace System.Security.Principal
{
//
// Identifier authorities
//
internal enum IdentifierAuthority : long
{
NullAuthority = 0,
WorldAuthority = 1,
LocalAuthority = 2,
CreatorAuthority = 3,
NonUniqueAuthority = 4,
NTAuthority = 5,
SiteServerAuthority = 6,
InternetSiteAuthority = 7,
ExchangeAuthority = 8,
ResourceManagerAuthority = 9,
}
//
// SID name usage
//
internal enum SidNameUse
{
User = 1,
Group = 2,
Domain = 3,
Alias = 4,
WellKnownGroup = 5,
DeletedAccount = 6,
Invalid = 7,
Unknown = 8,
Computer = 9,
}
//
// Well-known SID types
//
[System.Runtime.InteropServices.ComVisible(false)]
public enum WellKnownSidType
{
NullSid = 0,
WorldSid = 1,
LocalSid = 2,
CreatorOwnerSid = 3,
CreatorGroupSid = 4,
CreatorOwnerServerSid = 5,
CreatorGroupServerSid = 6,
NTAuthoritySid = 7,
DialupSid = 8,
NetworkSid = 9,
BatchSid = 10,
InteractiveSid = 11,
ServiceSid = 12,
AnonymousSid = 13,
ProxySid = 14,
EnterpriseControllersSid = 15,
SelfSid = 16,
AuthenticatedUserSid = 17,
RestrictedCodeSid = 18,
TerminalServerSid = 19,
RemoteLogonIdSid = 20,
LogonIdsSid = 21,
LocalSystemSid = 22,
LocalServiceSid = 23,
NetworkServiceSid = 24,
BuiltinDomainSid = 25,
BuiltinAdministratorsSid = 26,
BuiltinUsersSid = 27,
BuiltinGuestsSid = 28,
BuiltinPowerUsersSid = 29,
BuiltinAccountOperatorsSid = 30,
BuiltinSystemOperatorsSid = 31,
BuiltinPrintOperatorsSid = 32,
BuiltinBackupOperatorsSid = 33,
BuiltinReplicatorSid = 34,
BuiltinPreWindows2000CompatibleAccessSid = 35,
BuiltinRemoteDesktopUsersSid = 36,
BuiltinNetworkConfigurationOperatorsSid = 37,
AccountAdministratorSid = 38,
AccountGuestSid = 39,
AccountKrbtgtSid = 40,
AccountDomainAdminsSid = 41,
AccountDomainUsersSid = 42,
AccountDomainGuestsSid = 43,
AccountComputersSid = 44,
AccountControllersSid = 45,
AccountCertAdminsSid = 46,
AccountSchemaAdminsSid = 47,
AccountEnterpriseAdminsSid = 48,
AccountPolicyAdminsSid = 49,
AccountRasAndIasServersSid = 50,
NtlmAuthenticationSid = 51,
DigestAuthenticationSid = 52,
SChannelAuthenticationSid = 53,
ThisOrganizationSid = 54,
OtherOrganizationSid = 55,
BuiltinIncomingForestTrustBuildersSid = 56,
BuiltinPerformanceMonitoringUsersSid = 57,
BuiltinPerformanceLoggingUsersSid = 58,
BuiltinAuthorizationAccessSid = 59,
WinBuiltinTerminalServerLicenseServersSid= 60,
MaxDefined = WinBuiltinTerminalServerLicenseServersSid,
}
//
// This class implements revision 1 SIDs
// NOTE: The SecurityIdentifier class is immutable and must remain this way
//
[System.Runtime.InteropServices.ComVisible(false)]
public sealed class SecurityIdentifier : IdentityReference, IComparable
{
#region Public Constants
//
// Identifier authority must be at most six bytes long
//
internal static readonly long MaxIdentifierAuthority = 0xFFFFFFFFFFFF;
//
// Maximum number of subauthorities in a SID
//
internal static readonly byte MaxSubAuthorities = 15;
//
// Minimum length of a binary representation of a SID
//
public static readonly int MinBinaryLength = 1 + 1 + 6; // Revision (1) + subauth count (1) + identifier authority (6)
//
// Maximum length of a binary representation of a SID
//
public static readonly int MaxBinaryLength = 1 + 1 + 6 + MaxSubAuthorities * 4; // 4 bytes for each subauth
#endregion
#region Private Members
//
// Immutable properties of a SID
//
private IdentifierAuthority _IdentifierAuthority;
private int[] _SubAuthorities;
private byte[] _BinaryForm;
private SecurityIdentifier _AccountDomainSid;
bool _AccountDomainSidInitialized = false;
//
// Computed attributes of a SID
//
private string _SddlForm = null;
#endregion
#region Constructors
//
// Shared constructor logic
// NOTE: subauthorities are really unsigned integers, but due to CLS
// lack of support for unsigned integers the caller must perform
// the typecast
//
private void CreateFromParts( IdentifierAuthority identifierAuthority, int[] subAuthorities )
{
if ( subAuthorities == null )
{
throw new ArgumentNullException( "subAuthorities" );
}
//
// Check the number of subauthorities passed in
//
if ( subAuthorities.Length > MaxSubAuthorities )
{
throw new ArgumentOutOfRangeException(
"subAuthorities.Length",
subAuthorities.Length,
Environment.GetResourceString( "IdentityReference_InvalidNumberOfSubauthorities", MaxSubAuthorities));
}
//
// Identifier authority is atmost 6 bytes long
//
if ( identifierAuthority < 0 ||
(long) identifierAuthority > MaxIdentifierAuthority )
{
throw new ArgumentOutOfRangeException(
"identifierAuthority",
identifierAuthority,
Environment.GetResourceString( "IdentityReference_IdentifierAuthorityTooLarge" ));
}
//
// Create a local copy of the data passed in
//
_IdentifierAuthority = identifierAuthority;
_SubAuthorities = new int[ subAuthorities.Length ];
subAuthorities.CopyTo( _SubAuthorities, 0 );
//
// Compute and store the binary form
//
// typedef struct _SID {
// UCHAR Revision;
// UCHAR SubAuthorityCount;
// SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
// ULONG SubAuthority[ANYSIZE_ARRAY]
// } SID, *PISID;
//
byte i;
_BinaryForm = new byte[1 + 1 + 6 + 4 * this.SubAuthorityCount];
//
// First two bytes contain revision and subauthority count
//
_BinaryForm[0] = Revision;
_BinaryForm[1] = ( byte )this.SubAuthorityCount;
//
// Identifier authority takes up 6 bytes
//
for ( i = 0; i < 6; i++ )
{
_BinaryForm[2+i] = ( byte )(((( ulong )this._IdentifierAuthority ) >> (( 5 - i ) * 8 )) & 0xFF ) ;
}
//
// Subauthorities go last, preserving big-endian representation
//
for ( i = 0; i < this.SubAuthorityCount; i++ )
{
byte shift;
for ( shift = 0; shift < 4; shift += 1 )
{
_BinaryForm[8 + 4*i + shift] = ( byte )((( ulong )_SubAuthorities[i] ) >> ( shift * 8 ));
}
}
}
private void CreateFromBinaryForm( byte[] binaryForm, int offset )
{
IdentifierAuthority Authority;
int[] SubAuthorities;
//
// Give us something to work with
//
if ( binaryForm == null )
{
throw new ArgumentNullException( "binaryForm" );
}
//
// Negative offsets are not allowed
//
if ( offset < 0 )
{
throw new ArgumentOutOfRangeException(
"offset",
offset,
Environment.GetResourceString( "ArgumentOutOfRange_NeedNonNegNum" ));
}
//
// At least a minimum-size SID should fit in the buffer
//
if ( binaryForm.Length - offset < SecurityIdentifier.MinBinaryLength )
{
throw new ArgumentOutOfRangeException(
"binaryForm",
Environment.GetResourceString( "ArgumentOutOfRange_ArrayTooSmall" ));
}
//
// Extract the elements of a SID
//
if ( binaryForm[offset] != Revision )
{
//
// Revision is incorrect
//
throw new ArgumentException(
Environment.GetResourceString( "IdentityReference_InvalidSidRevision" ),
"binaryForm" );
}
//
// Insist on the correct number of subauthorities
//
if ( binaryForm[offset + 1] > MaxSubAuthorities )
{
throw new ArgumentException(
Environment.GetResourceString( "IdentityReference_InvalidNumberOfSubauthorities", MaxSubAuthorities ),
"binaryForm" );
}
//
// Make sure the buffer is big enough
//
int Length = 1 + 1 + 6 + 4 * binaryForm[offset + 1];
if ( binaryForm.Length - offset < Length )
{
throw new ArgumentException(
Environment.GetResourceString( "ArgumentOutOfRange_ArrayTooSmall" ),
"binaryForm" );
}
Authority =
( IdentifierAuthority )(
((( long )binaryForm[offset + 2]) << 40 ) +
((( long )binaryForm[offset + 3]) << 32 ) +
((( long )binaryForm[offset + 4]) << 24 ) +
((( long )binaryForm[offset + 5]) << 16 ) +
((( long )binaryForm[offset + 6]) << 8 ) +
((( long )binaryForm[offset + 7]) ));
SubAuthorities = new int[binaryForm[offset + 1]];
//
// Subauthorities are represented in big-endian format
//
for ( byte i = 0; i < binaryForm[offset + 1]; i++ )
{
SubAuthorities[i] =
( int )(
((( uint )binaryForm[offset + 8 + 4*i + 0]) << 0 ) +
((( uint )binaryForm[offset + 8 + 4*i + 1]) << 8 ) +
((( uint )binaryForm[offset + 8 + 4*i + 2]) << 16 ) +
((( uint )binaryForm[offset + 8 + 4*i + 3]) << 24 ));
}
CreateFromParts( Authority, SubAuthorities );
return;
}
//
// Constructs a SecurityIdentifier object from its string representation
// Returns 'null' if string passed in is not a valid SID
// NOTE: although there is a P/Invoke call involved in the implementation of this method,
// there is no security risk involved, so no security demand is being made.
//
public SecurityIdentifier( string sddlForm )
{
byte[] resultSid;
//
// Give us something to work with
//
if ( sddlForm == null )
{
throw new ArgumentNullException( "sddlForm" );
}
//
// Call into the underlying O/S conversion routine
//
int Error = Win32.CreateSidFromString( sddlForm, out resultSid );
if ( Error == Win32Native.ERROR_INVALID_SID )
{
throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidValue" ), "sddlForm" );
}
else if ( Error == Win32Native.ERROR_NOT_ENOUGH_MEMORY )
{
throw new OutOfMemoryException();
}
else if ( Error != Win32Native.ERROR_SUCCESS )
{
BCLDebug.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32.CreateSidFromString returned unrecognized error {0}", Error ));
throw new SystemException(Win32Native.GetMessage(Error));
}
CreateFromBinaryForm( resultSid, 0 );
}
//
// Constructs a SecurityIdentifier object from its binary representation
//
public SecurityIdentifier( byte[] binaryForm, int offset )
{
CreateFromBinaryForm( binaryForm, offset );
}
//
// Constructs a SecurityIdentifier object from an IntPtr
//
[SecurityPermission(SecurityAction.Demand, UnmanagedCode=true)]
public SecurityIdentifier( IntPtr binaryForm )
: this( binaryForm, true )
{
}
internal SecurityIdentifier( IntPtr binaryForm, bool noDemand )
: this( Win32.ConvertIntPtrSidToByteArraySid( binaryForm ), 0 )
{
}
//
// Constructs a well-known SID
// The 'domainSid' parameter is optional and only used
// by the well-known types that require it
// NOTE: although there is a P/Invoke call involved in the implementation of this constructor,
// there is no security risk involved, so no security demand is being made.
//
public SecurityIdentifier( WellKnownSidType sidType, SecurityIdentifier domainSid )
{
byte[] resultSid;
int Error;
//
// Check if well known sids are supported on this platform
//
if (!Win32.WellKnownSidApisSupported) {
throw new PlatformNotSupportedException( Environment.GetResourceString( "PlatformNotSupported_RequiresW2kSP3" ));
}
//
// sidType must not be equal to LogonIdsSid
//
if (sidType == WellKnownSidType.LogonIdsSid)
{
throw new ArgumentException( Environment.GetResourceString( "IdentityReference_CannotCreateLogonIdsSid" ), "sidType" );
}
//
// sidType should not exceed the max defined value
//
if ((sidType < WellKnownSidType.NullSid) || (sidType > WellKnownSidType.MaxDefined))
{
throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidValue" ), "sidType" );
}
//
// for sidType between 38 to 50, the domainSid parameter must be specified
//
if ((sidType >= WellKnownSidType.AccountAdministratorSid) && (sidType <= WellKnownSidType.AccountRasAndIasServersSid))
{
if (domainSid == null) {
throw new ArgumentNullException( "domainSid", Environment.GetResourceString( "IdentityReference_DomainSidRequired", sidType) );
}
//
// verify that the domain sid is a valid windows domain sid
// to do that we call GetAccountDomainSid and the return value should be the same as the domainSid
//
SecurityIdentifier resultDomainSid;
int ErrorCode;
ErrorCode = Win32.GetWindowsAccountDomainSid( domainSid, out resultDomainSid );
if ( ErrorCode == Win32Native.ERROR_INSUFFICIENT_BUFFER ) {
throw new OutOfMemoryException();
}
else if ( ErrorCode == Win32Native.ERROR_NON_ACCOUNT_SID )
{
// this means that the domain sid is not valid
throw new ArgumentException( Environment.GetResourceString( "IdentityReference_NotAWindowsDomain" ), "domainSid" );
}
else if ( ErrorCode != Win32Native.ERROR_SUCCESS )
{
BCLDebug.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32.GetWindowsAccountDomainSid returned unrecognized error {0}", ErrorCode) );
throw new SystemException(Win32Native.GetMessage(ErrorCode));
}
//
// if domainSid is passed in as S-1-5-21-3-4-5-6, the above api will return S-1-5-21-3-4-5 as the domainSid
// Since these do not match S-1-5-21-3-4-5-6 is not a valid domainSid (wrong number of subauthorities)
//
if (resultDomainSid != domainSid) {
throw new ArgumentException( Environment.GetResourceString( "IdentityReference_NotAWindowsDomain" ), "domainSid" );
}
}
Error = Win32.CreateWellKnownSid( sidType, domainSid, out resultSid );
if ( Error == Win32Native.ERROR_INVALID_PARAMETER )
{
throw new ArgumentException( Win32Native.GetMessage(Error), "sidType/domainSid" );
}
else if ( Error != Win32Native.ERROR_SUCCESS )
{
BCLDebug.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32.CreateWellKnownSid returned unrecognized error {0}", Error ));
throw new SystemException( Win32Native.GetMessage( Error ));
}
CreateFromBinaryForm( resultSid, 0 );
}
internal SecurityIdentifier( SecurityIdentifier domainSid, uint rid )
{
int i;
int[] SubAuthorities = new int[ domainSid.SubAuthorityCount + 1 ];
for ( i = 0; i < domainSid.SubAuthorityCount; i++ )
{
SubAuthorities[i] = domainSid.GetSubAuthority( i );
}
SubAuthorities[i] = ( int )rid;
CreateFromParts( domainSid.IdentifierAuthority, SubAuthorities );
}
internal SecurityIdentifier( IdentifierAuthority identifierAuthority, int[] subAuthorities )
{
CreateFromParts( identifierAuthority, subAuthorities );
}
#endregion
#region Static Properties
//
// Revision is always '1'
//
internal static byte Revision
{
get { return 1; }
}
#endregion
#region Non-static Properties
//
// This is for internal consumption only, hence it is marked 'internal'
// Making this call public would require a deep copy of the data to
// prevent the caller from messing with the internal representation.
//
internal byte[] BinaryForm
{
get { return _BinaryForm; }
}
internal IdentifierAuthority IdentifierAuthority
{
get { return _IdentifierAuthority; }
}
internal int SubAuthorityCount
{
get { return _SubAuthorities.Length; }
}
public int BinaryLength
{
get
{
return _BinaryForm.Length;
}
}
//
// Returns the domain portion of a SID or null if the specified
// SID is not an account SID
// NOTE: although there is a P/Invoke call involved in the implementation of this method,
// there is no security risk involved, so no security demand is being made.
//
public SecurityIdentifier AccountDomainSid
{
get
{
if ( !_AccountDomainSidInitialized )
{
_AccountDomainSid = GetAccountDomainSid();
_AccountDomainSidInitialized = true;
}
return _AccountDomainSid;
}
}
#endregion
#region Inherited properties and methods
public override bool Equals( object o )
{
if ( o == null )
{
return false;
}
SecurityIdentifier sid = o as SecurityIdentifier;
if ( sid == null )
{
return false;
}
return ( this == sid ); // invokes operator==
}
public bool Equals( SecurityIdentifier sid )
{
if ( sid == null )
{
return false;
}
return ( this == sid ); // invokes operator==
}
public override int GetHashCode() {
int hashCode = ((long)this.IdentifierAuthority).GetHashCode();
for(int i = 0; i < SubAuthorityCount; i++) {
hashCode ^= this.GetSubAuthority(i);
}
return hashCode;
}
public override string ToString()
{
if ( _SddlForm == null )
{
StringBuilder result = new StringBuilder();
//
// Typecasting of _IdentifierAuthority to a long below is important, since
// otherwise you would see this: "S-1-NTAuthority-32-544"
//
result.AppendFormat( "S-1-{0}", ( long )_IdentifierAuthority );
for ( int i = 0; i < SubAuthorityCount; i++ )
{
result.AppendFormat( "-{0}", ( uint )( _SubAuthorities[i] ));
}
_SddlForm = result.ToString();
}
return _SddlForm;
}
#if false
public override string Scheme
{
get { return "ms-sid"; }
}
#endif
public override string Value
{
get { return ToString().ToUpper(CultureInfo.InvariantCulture); }
}
internal static bool IsValidTargetTypeStatic( Type targetType )
{
if ( targetType == typeof( NTAccount ))
{
return true;
}
else if ( targetType == typeof( SecurityIdentifier ))
{
return true;
}
else
{
return false;
}
}
public override bool IsValidTargetType( Type targetType )
{
return IsValidTargetTypeStatic( targetType );
}
internal SecurityIdentifier GetAccountDomainSid()
{
SecurityIdentifier ResultSid;
int Error;
Error = Win32.GetWindowsAccountDomainSid( this, out ResultSid );
if ( Error == Win32Native.ERROR_INSUFFICIENT_BUFFER )
{
throw new OutOfMemoryException();
}
else if ( Error == Win32Native.ERROR_NON_ACCOUNT_SID )
{
ResultSid = null;
}
else if ( Error != Win32Native.ERROR_SUCCESS )
{
BCLDebug.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32.GetWindowsAccountDomainSid returned unrecognized error {0}", Error) );
throw new SystemException(Win32Native.GetMessage(Error));
}
return ResultSid;
}
public bool IsAccountSid() {
if ( !_AccountDomainSidInitialized )
{
_AccountDomainSid = GetAccountDomainSid();
_AccountDomainSidInitialized = true;
}
if (_AccountDomainSid == null) {
return false;
}
return true;
}
public override IdentityReference Translate( Type targetType )
{
if ( targetType == null )
{
throw new ArgumentNullException( "targetType" );
}
if ( targetType == typeof( SecurityIdentifier ))
{
return this; // assumes SecurityIdentifier objects are immutable
}
else if ( targetType == typeof( NTAccount ))
{
IdentityReferenceCollection irSource = new IdentityReferenceCollection( 1 );
irSource.Add( this );
IdentityReferenceCollection irTarget;
irTarget = SecurityIdentifier.Translate( irSource, targetType, true );
return irTarget[0];
}
else
{
throw new ArgumentException( Environment.GetResourceString( "IdentityReference_MustBeIdentityReference" ), "targetType" );
}
}
#endregion
#region Operators
public static bool operator== ( SecurityIdentifier left, SecurityIdentifier right )
{
object l = left;
object r = right;
if ( l == null && r == null )
{
return true;
}
else if ( l == null || r == null )
{
return false;
}
else
{
return ( left.CompareTo( right ) == 0 );
}
}
public static bool operator!= ( SecurityIdentifier left, SecurityIdentifier right )
{
return !( left == right );
}
#endregion
#region IComparable implementation
public int CompareTo( SecurityIdentifier sid )
{
if ( sid == null )
{
throw new ArgumentNullException( "sid" );
}
if ( this.IdentifierAuthority < sid.IdentifierAuthority )
{
return -1;
}
if ( this.IdentifierAuthority > sid.IdentifierAuthority )
{
return 1;
}
if ( this.SubAuthorityCount < sid.SubAuthorityCount )
{
return -1;
}
if ( this.SubAuthorityCount > sid.SubAuthorityCount )
{
return 1;
}
for ( int i = 0; i < this.SubAuthorityCount; i++ )
{
int diff = this.GetSubAuthority( i ) - sid.GetSubAuthority( i );
if ( diff != 0 )
{
return diff;
}
}
return 0;
}
#endregion
#region Public Methods
internal int GetSubAuthority( int index )
{
return this._SubAuthorities[ index ];
}
//
// Determines whether this SID is a well known SID of the specified type
//
// NOTE: although there is a P/Invoke call involved in the implementation of this method,
// there is no security risk involved, so no security demand is being made.
//
public bool IsWellKnown( WellKnownSidType type )
{
return Win32.IsWellKnownSid( this, type );
}
public void GetBinaryForm( byte[] binaryForm, int offset )
{
_BinaryForm.CopyTo( binaryForm, offset );
}
//
// NOTE: although there is a P/Invoke call involved in the implementation of this method,
// there is no security risk involved, so no security demand is being made.
//
public bool IsEqualDomainSid( SecurityIdentifier sid )
{
return Win32.IsEqualDomainSid( this, sid );
}
private static IdentityReferenceCollection TranslateToNTAccounts( IdentityReferenceCollection sourceSids, out bool someFailed )
{
//
// Check if the lsa api is supported
//
if (!Win32.LsaApisSupported) {
throw new PlatformNotSupportedException( Environment.GetResourceString( "PlatformNotSupported_Win9x" ));
}
IntPtr[] SidArrayPtr = new IntPtr[ sourceSids.Count ];
GCHandle[] HandleArray = new GCHandle[ sourceSids.Count ];
SafeLsaPolicyHandle LsaHandle = SafeLsaPolicyHandle.InvalidHandle;
SafeLsaMemoryHandle ReferencedDomainsPtr = SafeLsaMemoryHandle.InvalidHandle;
SafeLsaMemoryHandle NamesPtr = SafeLsaMemoryHandle.InvalidHandle;
int i = 0;
if ( sourceSids == null )
{
throw new ArgumentNullException( "sourceSids" );
}
if ( sourceSids.Count == 0 )
{
throw new ArgumentException( Environment.GetResourceString( "Arg_EmptyCollection" ), "sourceSids" );
}
try
{
//
// Pin all elements in the array of SIDs
//
foreach ( IdentityReference id in sourceSids )
{
SecurityIdentifier sid = id as SecurityIdentifier;
if ( sid == null )
{
throw new ArgumentException( Environment.GetResourceString( "Argument_ImproperType" ), "sourceSids" );
}
HandleArray[i] = GCHandle.Alloc( sid.BinaryForm, GCHandleType.Pinned );
SidArrayPtr[i] = HandleArray[i].AddrOfPinnedObject();
i++;
}
//
// Open LSA policy (for lookup requires it)
//
LsaHandle = Win32.LsaOpenPolicy( null, PolicyRights.POLICY_LOOKUP_NAMES );
//
// Perform the actual lookup
//
someFailed = false;
uint ReturnCode;
ReturnCode = Win32Native.LsaLookupSids( LsaHandle, sourceSids.Count, SidArrayPtr, ref ReferencedDomainsPtr, ref NamesPtr );
//
// Make a decision regarding whether it makes sense to proceed
// based on the return code and the value of the forceSuccess argument
//
if ( ReturnCode == Win32Native.STATUS_NO_MEMORY ||
ReturnCode == Win32Native.STATUS_INSUFFICIENT_RESOURCES )
{
throw new OutOfMemoryException();
}
else if ( ReturnCode == Win32Native.STATUS_ACCESS_DENIED )
{
throw new UnauthorizedAccessException();
}
else if ( ReturnCode == Win32Native.STATUS_NONE_MAPPED ||
ReturnCode == Win32Native.STATUS_SOME_NOT_MAPPED )
{
someFailed = true;
}
else if ( ReturnCode != 0 )
{
int win32ErrorCode = Win32Native.LsaNtStatusToWinError(unchecked((int)ReturnCode));
BCLDebug.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32Native.LsaLookupSids returned {0}", win32ErrorCode));
throw new SystemException(Win32Native.GetMessage(win32ErrorCode));
}
//
// Interpret the results and generate NTAccount objects
//
IdentityReferenceCollection Result = new IdentityReferenceCollection( sourceSids.Count );
if ( ReturnCode == 0 || ReturnCode == Win32Native.STATUS_SOME_NOT_MAPPED )
{
//
// Interpret the results and generate NT Account objects
//
Win32Native.LSA_REFERENCED_DOMAIN_LIST rdl = ( Win32Native.LSA_REFERENCED_DOMAIN_LIST )Marshal.PtrToStructure( ReferencedDomainsPtr.DangerousGetHandle(), typeof( Win32Native.LSA_REFERENCED_DOMAIN_LIST ));
string[] ReferencedDomains = new string[ rdl.Entries ];
for ( i = 0; i < rdl.Entries; i++ )
{
Win32Native.LSA_TRUST_INFORMATION ti = ( Win32Native.LSA_TRUST_INFORMATION )Marshal.PtrToStructure( new IntPtr(( long )rdl.Domains + i * Marshal.SizeOf( typeof( Win32Native.LSA_TRUST_INFORMATION ))), typeof( Win32Native.LSA_TRUST_INFORMATION ));
ReferencedDomains[i] = Marshal.PtrToStringUni( ti.Name.Buffer, ti.Name.Length/2 );
}
for ( i = 0; i < sourceSids.Count; i++ )
{
Win32Native.LSA_TRANSLATED_NAME Ltn;
SidNameUse Use;
string Account;
string Domain;
Ltn = ( Win32Native.LSA_TRANSLATED_NAME )Marshal.PtrToStructure( new IntPtr(( long )NamesPtr.DangerousGetHandle() + i * Marshal.SizeOf( typeof( Win32Native.LSA_TRANSLATED_NAME ))), typeof( Win32Native.LSA_TRANSLATED_NAME ));
Use = ( SidNameUse )Ltn.Use;
switch ( Use )
{
case SidNameUse.User:
goto case SidNameUse.WellKnownGroup;
case SidNameUse.Group:
goto case SidNameUse.WellKnownGroup;
case SidNameUse.Alias:
goto case SidNameUse.WellKnownGroup;
case SidNameUse.Computer:
goto case SidNameUse.WellKnownGroup;
case SidNameUse.WellKnownGroup:
Account = Marshal.PtrToStringUni( Ltn.Name.Buffer, Ltn.Name.Length/2 );
Domain = ReferencedDomains[ Ltn.DomainIndex ];
Result.Add( new NTAccount( Domain, Account ));
break;
default:
someFailed = true;
Result.Add( sourceSids[i] );
break;
}
}
}
else
{
for ( i = 0; i < sourceSids.Count; i++ )
{
Result.Add( sourceSids[i] );
}
}
return Result;
}
finally
{
for ( i = 0; i < sourceSids.Count; i++ )
{
if ( HandleArray[i].IsAllocated )
{
HandleArray[i].Free();
}
}
LsaHandle.Dispose();
ReferencedDomainsPtr.Dispose();
NamesPtr.Dispose();
}
}
internal static IdentityReferenceCollection Translate( IdentityReferenceCollection sourceSids, Type targetType, bool forceSuccess)
{
bool SomeFailed = false;
IdentityReferenceCollection Result;
Result = Translate( sourceSids, targetType, out SomeFailed );
if (forceSuccess && SomeFailed) {
IdentityReferenceCollection UnmappedIdentities = new IdentityReferenceCollection();
foreach (IdentityReference id in Result)
{
if (id.GetType() != targetType)
{
UnmappedIdentities.Add(id);
}
}
throw new IdentityNotMappedException(Environment.GetResourceString("IdentityReference_IdentityNotMapped"), UnmappedIdentities);
}
return Result;
}
internal static IdentityReferenceCollection Translate( IdentityReferenceCollection sourceSids, Type targetType, out bool someFailed )
{
if ( sourceSids == null )
{
throw new ArgumentNullException( "sourceSids" );
}
if ( targetType == typeof( NTAccount ))
{
return TranslateToNTAccounts( sourceSids, out someFailed );
}
throw new ArgumentException( Environment.GetResourceString( "IdentityReference_MustBeIdentityReference" ), "targetType" );
}
#endregion
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- NotImplementedException.cs
- BuildManager.cs
- CompleteWizardStep.cs
- AssociativeAggregationOperator.cs
- ReliableSession.cs
- ThrowHelper.cs
- Hex.cs
- WindowsListViewGroup.cs
- PackageFilter.cs
- Hashtable.cs
- NullableIntAverageAggregationOperator.cs
- SoapAttributeAttribute.cs
- GorillaCodec.cs
- QilScopedVisitor.cs
- XmlAttributeProperties.cs
- PermissionAttributes.cs
- MouseWheelEventArgs.cs
- SingleObjectCollection.cs
- TextContainerHelper.cs
- SupportingTokenProviderSpecification.cs
- SiteMapNode.cs
- DataTransferEventArgs.cs
- ParameterModifier.cs
- ThemeDirectoryCompiler.cs
- XpsFilter.cs
- SvcMapFile.cs
- QuaternionIndependentAnimationStorage.cs
- DeferredElementTreeState.cs
- BrowserCapabilitiesFactory.cs
- Transform.cs
- TreeBuilderXamlTranslator.cs
- XmlValidatingReader.cs
- MetadataItemEmitter.cs
- RecognitionEventArgs.cs
- EncryptedKey.cs
- AsyncResult.cs
- AppDomain.cs
- FlatButtonAppearance.cs
- CopyAction.cs
- TaskDesigner.cs
- FormClosingEvent.cs
- ConfigurationManagerHelperFactory.cs
- LineServicesRun.cs
- ImageButton.cs
- ListParagraph.cs
- TextEditorDragDrop.cs
- SerializationObjectManager.cs
- ColorTranslator.cs
- FloaterBaseParagraph.cs
- ReadWriteObjectLock.cs
- FontFamilyIdentifier.cs
- MaterialGroup.cs
- QueryAsyncResult.cs
- EditingMode.cs
- WebServiceReceiveDesigner.cs
- XPathItem.cs
- ReachDocumentReferenceSerializer.cs
- ToolStripPanelRow.cs
- LocalizationParserHooks.cs
- PeerNameRecordCollection.cs
- KerberosSecurityTokenProvider.cs
- ProgressBarRenderer.cs
- NotSupportedException.cs
- CatalogPartCollection.cs
- XmlSchemaType.cs
- WebPartRestoreVerb.cs
- InstancePersistenceEvent.cs
- QueryValue.cs
- DayRenderEvent.cs
- LocationUpdates.cs
- ObjectStateFormatter.cs
- ContextMenuStrip.cs
- embossbitmapeffect.cs
- LicenseException.cs
- NotSupportedException.cs
- OrthographicCamera.cs
- RSAOAEPKeyExchangeFormatter.cs
- AssemblyEvidenceFactory.cs
- TreeView.cs
- StorageEntityTypeMapping.cs
- ImageSource.cs
- Stylesheet.cs
- DataGridViewRowHeightInfoPushedEventArgs.cs
- GcSettings.cs
- HttpHandlersSection.cs
- RuleSettings.cs
- ParserContext.cs
- XPathMultyIterator.cs
- TextBox.cs
- ToolStripDropTargetManager.cs
- InputLanguageEventArgs.cs
- EdmType.cs
- SqlReferenceCollection.cs
- RequestValidator.cs
- DataGridHyperlinkColumn.cs
- ValidationErrorEventArgs.cs
- Int32.cs
- CompilerInfo.cs
- PointUtil.cs
- InternalBufferOverflowException.cs