2017-04-02 00:36:06 +00:00
// This code is derived from jcifs smb client library <jcifs at samba dot org>
// Ported by J. Arturo <webmaster at komodosoft dot net>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System ;
using System.Collections ;
using System.Collections.Generic ;
using System.IO ;
using SharpCifs.Dcerpc ;
using SharpCifs.Dcerpc.Msrpc ;
using SharpCifs.Util ;
using SharpCifs.Util.Sharpen ;
using Hashtable = SharpCifs . Util . Sharpen . Hashtable ; //not System.Collections.Hashtable
namespace SharpCifs.Smb
{
2017-06-21 06:46:57 +00:00
/// <summary>
/// A Windows SID is a numeric identifier used to represent Windows
/// accounts.
/// </summary>
/// <remarks>
/// A Windows SID is a numeric identifier used to represent Windows
/// accounts. SIDs are commonly represented using a textual format such as
/// <tt>S-1-5-21-1496946806-2192648263-3843101252-1029</tt> but they may
/// also be resolved to yield the name of the associated Windows account
/// such as <tt>Administrators</tt> or <tt>MYDOM\alice</tt>.
/// <p>
/// Consider the following output of <tt>examples/SidLookup.java</tt>:
/// <pre>
/// toString: S-1-5-21-4133388617-793952518-2001621813-512
/// toDisplayString: WNET\Domain Admins
/// getType: 2
/// getTypeText: Domain group
/// getDomainName: WNET
/// getAccountName: Domain Admins
/// </pre>
/// </remarks>
public class Sid : Rpc . SidT
{
public const int SidTypeUseNone = Lsarpc . SidNameUseNone ;
public const int SidTypeUser = Lsarpc . SidNameUser ;
public const int SidTypeDomGrp = Lsarpc . SidNameDomGrp ;
public const int SidTypeDomain = Lsarpc . SidNameDomain ;
public const int SidTypeAlias = Lsarpc . SidNameAlias ;
public const int SidTypeWknGrp = Lsarpc . SidNameWknGrp ;
public const int SidTypeDeleted = Lsarpc . SidNameDeleted ;
public const int SidTypeInvalid = Lsarpc . SidNameInvalid ;
public const int SidTypeUnknown = Lsarpc . SidNameUnknown ;
internal static readonly string [ ] SidTypeNames =
{
"0" , "User" , "Domain group" , "Domain" , "Local group" ,
"Builtin group" , "Deleted" , "Invalid" , "Unknown"
} ;
public const int SidFlagResolveSids = unchecked ( 0x0001 ) ;
public static Sid Everyone ;
public static Sid CreatorOwner ;
public static Sid SYSTEM ;
static Sid ( )
{
try
{
Everyone = new Sid ( "S-1-1-0" ) ;
CreatorOwner = new Sid ( "S-1-3-0" ) ;
SYSTEM = new Sid ( "S-1-5-18" ) ;
}
catch ( SmbException )
{
}
}
internal static Hashtable SidCache = new Hashtable ( ) ;
/// <exception cref="System.IO.IOException"></exception>
internal static void ResolveSids ( DcerpcHandle handle ,
LsaPolicyHandle policyHandle ,
Sid [ ] sids )
{
MsrpcLookupSids rpc = new MsrpcLookupSids ( policyHandle , sids ) ;
handle . Sendrecv ( rpc ) ;
switch ( rpc . Retval )
{
case 0 :
case NtStatus . NtStatusNoneMapped :
case unchecked ( 0x00000107 ) :
{
// NT_STATUS_SOME_NOT_MAPPED
break ;
}
default :
{
throw new SmbException ( rpc . Retval , false ) ;
}
}
for ( int si = 0 ; si < sids . Length ; si + + )
{
sids [ si ] . Type = rpc . Names . Names [ si ] . SidType ;
sids [ si ] . DomainName = null ;
switch ( sids [ si ] . Type )
{
case SidTypeUser :
case SidTypeDomGrp :
case SidTypeDomain :
case SidTypeAlias :
case SidTypeWknGrp :
{
int sidIndex = rpc . Names . Names [ si ] . SidIndex ;
Rpc . Unicode_string ustr = rpc . Domains . Domains [ sidIndex ] . Name ;
sids [ si ] . DomainName = ( new UnicodeString ( ustr , false ) ) . ToString ( ) ;
break ;
}
}
sids [ si ] . AcctName = ( new UnicodeString ( rpc . Names . Names [ si ] . Name , false ) ) . ToString ( ) ;
sids [ si ] . OriginServer = null ;
sids [ si ] . OriginAuth = null ;
}
}
/// <exception cref="System.IO.IOException"></exception>
internal static void ResolveSids0 ( string authorityServerName ,
NtlmPasswordAuthentication auth ,
Sid [ ] sids )
{
DcerpcHandle handle = null ;
LsaPolicyHandle policyHandle = null ;
lock ( SidCache )
{
try
{
handle = DcerpcHandle . GetHandle ( "ncacn_np:" + authorityServerName
+ "[\\PIPE\\lsarpc]" , auth ) ;
string server = authorityServerName ;
int dot = server . IndexOf ( '.' ) ;
if ( dot > 0 & & char . IsDigit ( server [ 0 ] ) = = false )
{
server = Runtime . Substring ( server , 0 , dot ) ;
}
policyHandle = new LsaPolicyHandle ( handle , "\\\\" + server , unchecked ( 0x00000800 ) ) ;
ResolveSids ( handle , policyHandle , sids ) ;
}
finally
{
if ( handle ! = null )
{
if ( policyHandle ! = null )
{
policyHandle . Close ( ) ;
}
handle . Close ( ) ;
}
}
}
}
/// <exception cref="System.IO.IOException"></exception>
public static void ResolveSids ( string authorityServerName ,
NtlmPasswordAuthentication auth ,
Sid [ ] sids ,
int offset ,
int length )
{
List < object > list = new List < object > ( ) ; //new List<object>(sids.Length);
int si ;
lock ( SidCache )
{
for ( si = 0 ; si < length ; si + + )
{
Sid sid = ( Sid ) SidCache . Get ( sids [ offset + si ] ) ;
if ( sid ! = null )
{
sids [ offset + si ] . Type = sid . Type ;
sids [ offset + si ] . DomainName = sid . DomainName ;
sids [ offset + si ] . AcctName = sid . AcctName ;
}
else
{
list . Add ( sids [ offset + si ] ) ;
}
}
if ( list . Count > 0 )
{
//sids = (Jcifs.Smb.SID[])Sharpen.Collections.ToArray(list, new Jcifs.Smb.SID[0]);
2017-04-02 00:36:06 +00:00
sids = ( Sid [ ] ) list . ToArray ( ) ;
2017-06-21 06:46:57 +00:00
ResolveSids0 ( authorityServerName , auth , sids ) ;
for ( si = 0 ; si < sids . Length ; si + + )
{
SidCache . Put ( sids [ si ] , sids [ si ] ) ;
}
}
}
}
/// <summary>Resolve an array of SIDs using a cache and at most one MSRPC request.</summary>
/// <remarks>
/// Resolve an array of SIDs using a cache and at most one MSRPC request.
///
/// This method will attempt
/// to resolve SIDs using a cache and cache the results of any SIDs that
/// required resolving with the authority. SID cache entries are currently not
/// expired because under normal circumstances SID information never changes.
/// </remarks>
/// <param name="authorityServerName">
/// The hostname of the server that should be queried. For maximum efficiency this should be the hostname of a domain controller however a member server will work as well and a domain controller may not return names for SIDs corresponding to local accounts for which the domain controller is not an authority.
/// </param>
/// <param name="auth">
/// The credentials that should be used to communicate with the named server. As usual, <tt>null</tt> indicates that default credentials should be used.
/// </param>
/// <param name="sids">
/// The SIDs that should be resolved. After this function is called, the names associated with the SIDs may be queried with the <tt>toDisplayString</tt>, <tt>getDomainName</tt>, and <tt>getAccountName</tt> methods.
/// </param>
/// <exception cref="System.IO.IOException"></exception>
public static void ResolveSids ( string authorityServerName ,
NtlmPasswordAuthentication auth ,
Sid [ ] sids )
{
List < object > list = new List < object > ( ) ; //new List<object>(sids.Length);
int si ;
lock ( SidCache )
{
for ( si = 0 ; si < sids . Length ; si + + )
{
Sid sid = ( Sid ) SidCache . Get ( sids [ si ] ) ;
if ( sid ! = null )
{
sids [ si ] . Type = sid . Type ;
sids [ si ] . DomainName = sid . DomainName ;
sids [ si ] . AcctName = sid . AcctName ;
}
else
{
list . Add ( sids [ si ] ) ;
}
}
if ( list . Count > 0 )
{
//sids = (Jcifs.Smb.SID[])Sharpen.Collections.ToArray(list, new Jcifs.Smb.SID[0]);
sids = ( Sid [ ] ) list . ToArray ( ) ;
ResolveSids0 ( authorityServerName , auth , sids ) ;
for ( si = 0 ; si < sids . Length ; si + + )
{
SidCache . Put ( sids [ si ] , sids [ si ] ) ;
}
}
}
}
/// <exception cref="System.IO.IOException"></exception>
public static Sid GetServerSid ( string server ,
NtlmPasswordAuthentication auth )
{
DcerpcHandle handle = null ;
LsaPolicyHandle policyHandle = null ;
Lsarpc . LsarDomainInfo info = new Lsarpc . LsarDomainInfo ( ) ;
MsrpcQueryInformationPolicy rpc ;
lock ( SidCache )
{
try
{
handle = DcerpcHandle . GetHandle ( "ncacn_np:" + server + "[\\PIPE\\lsarpc]" , auth ) ;
// NetApp doesn't like the 'generic' access mask values
policyHandle = new LsaPolicyHandle ( handle , null , unchecked ( 0x00000001 ) ) ;
rpc = new MsrpcQueryInformationPolicy ( policyHandle ,
Lsarpc . PolicyInfoAccountDomain ,
info ) ;
handle . Sendrecv ( rpc ) ;
if ( rpc . Retval ! = 0 )
{
throw new SmbException ( rpc . Retval , false ) ;
}
return new Sid ( info . Sid ,
SidTypeDomain ,
( new UnicodeString ( info . Name , false ) ) . ToString ( ) ,
null ,
false ) ;
}
finally
{
if ( handle ! = null )
{
if ( policyHandle ! = null )
{
policyHandle . Close ( ) ;
}
handle . Close ( ) ;
}
}
}
}
public static byte [ ] ToByteArray ( Rpc . SidT sid )
{
byte [ ] dst = new byte [ 1 + 1 + 6 + sid . SubAuthorityCount * 4 ] ;
int di = 0 ;
dst [ di + + ] = sid . Revision ;
dst [ di + + ] = sid . SubAuthorityCount ;
Array . Copy ( sid . IdentifierAuthority , 0 , dst , di , 6 ) ;
di + = 6 ;
for ( int ii = 0 ; ii < sid . SubAuthorityCount ; ii + + )
{
Encdec . Enc_uint32le ( sid . SubAuthority [ ii ] , dst , di ) ;
di + = 4 ;
}
return dst ;
}
internal int Type ;
internal string DomainName ;
internal string AcctName ;
internal string OriginServer ;
internal NtlmPasswordAuthentication OriginAuth ;
public Sid ( byte [ ] src , int si )
{
Revision = src [ si + + ] ;
SubAuthorityCount = src [ si + + ] ;
IdentifierAuthority = new byte [ 6 ] ;
Array . Copy ( src , si , IdentifierAuthority , 0 , 6 ) ;
si + = 6 ;
if ( SubAuthorityCount > 100 )
{
throw new RuntimeException ( "Invalid SID sub_authority_count" ) ;
}
SubAuthority = new int [ SubAuthorityCount ] ;
for ( int i = 0 ; i < SubAuthorityCount ; i + + )
{
SubAuthority [ i ] = ServerMessageBlock . ReadInt4 ( src , si ) ;
si + = 4 ;
}
}
/// <summary>
/// Construct a SID from it's textual representation such as
/// <tt>S-1-5-21-1496946806-2192648263-3843101252-1029</tt>.
/// </summary>
/// <remarks>
/// Construct a SID from it's textual representation such as
/// <tt>S-1-5-21-1496946806-2192648263-3843101252-1029</tt>.
/// </remarks>
/// <exception cref="SharpCifs.Smb.SmbException"></exception>
public Sid ( string textual )
{
StringTokenizer st = new StringTokenizer ( textual , "-" ) ;
if ( st . CountTokens ( ) < 3 | | ! st . NextToken ( ) . Equals ( "S" ) )
{
// need S-N-M
throw new SmbException ( "Bad textual SID format: " + textual ) ;
}
Revision = byte . Parse ( st . NextToken ( ) ) ;
string tmp = st . NextToken ( ) ;
long id = 0 ;
if ( tmp . StartsWith ( "0x" ) )
{
//id = long.Parse(Sharpen.Runtime.Substring(tmp, 2), 16);
2017-04-02 00:36:06 +00:00
id = long . Parse ( Runtime . Substring ( tmp , 2 ) ) ;
2017-06-21 06:46:57 +00:00
}
else
{
id = long . Parse ( tmp ) ;
}
IdentifierAuthority = new byte [ 6 ] ;
for ( int i = 5 ; id > 0 ; i - - )
{
IdentifierAuthority [ i ] = unchecked ( ( byte ) ( id % 256 ) ) ;
id > > = 8 ;
}
SubAuthorityCount = unchecked ( ( byte ) st . CountTokens ( ) ) ;
if ( SubAuthorityCount > 0 )
{
SubAuthority = new int [ SubAuthorityCount ] ;
for ( int i1 = 0 ; i1 < SubAuthorityCount ; i1 + + )
{
SubAuthority [ i1 ] = ( int ) ( long . Parse ( st . NextToken ( ) ) & unchecked ( 0xFFFFFFFFL ) ) ;
}
}
}
/// <summary>
/// Construct a SID from a domain SID and an RID
/// (relative identifier).
/// </summary>
/// <remarks>
/// Construct a SID from a domain SID and an RID
/// (relative identifier). For example, a domain SID
/// <tt>S-1-5-21-1496946806-2192648263-3843101252</tt> and RID <tt>1029</tt> would
/// yield the SID <tt>S-1-5-21-1496946806-2192648263-3843101252-1029</tt>.
/// </remarks>
public Sid ( Sid domsid , int rid )
{
Revision = domsid . Revision ;
IdentifierAuthority = domsid . IdentifierAuthority ;
SubAuthorityCount = unchecked ( ( byte ) ( domsid . SubAuthorityCount + 1 ) ) ;
SubAuthority = new int [ SubAuthorityCount ] ;
int i ;
for ( i = 0 ; i < domsid . SubAuthorityCount ; i + + )
{
SubAuthority [ i ] = domsid . SubAuthority [ i ] ;
}
SubAuthority [ i ] = rid ;
}
public Sid ( Rpc . SidT sid ,
int type ,
string domainName ,
string acctName ,
bool decrementAuthority )
{
Revision = sid . Revision ;
SubAuthorityCount = sid . SubAuthorityCount ;
IdentifierAuthority = sid . IdentifierAuthority ;
SubAuthority = sid . SubAuthority ;
this . Type = type ;
this . DomainName = domainName ;
this . AcctName = acctName ;
if ( decrementAuthority )
{
SubAuthorityCount - - ;
SubAuthority = new int [ SubAuthorityCount ] ;
for ( int i = 0 ; i < SubAuthorityCount ; i + + )
{
SubAuthority [ i ] = sid . SubAuthority [ i ] ;
}
}
}
public virtual Sid GetDomainSid ( )
{
return new Sid ( this ,
SidTypeDomain ,
DomainName ,
null ,
GetType ( ) ! = SidTypeDomain ) ;
}
public virtual int GetRid ( )
{
if ( GetType ( ) = = SidTypeDomain )
{
throw new ArgumentException ( "This SID is a domain sid" ) ;
}
return SubAuthority [ SubAuthorityCount - 1 ] ;
}
/// <summary>Returns the type of this SID indicating the state or type of account.</summary>
/// <remarks>
/// Returns the type of this SID indicating the state or type of account.
/// <p>
/// SID types are described in the following table.
/// <tt>
/// <table>
/// <tr><th>Type</th><th>Name</th></tr>
/// <tr><td>SID_TYPE_USE_NONE</td><td>0</td></tr>
/// <tr><td>SID_TYPE_USER</td><td>User</td></tr>
/// <tr><td>SID_TYPE_DOM_GRP</td><td>Domain group</td></tr>
/// <tr><td>SID_TYPE_DOMAIN</td><td>Domain</td></tr>
/// <tr><td>SID_TYPE_ALIAS</td><td>Local group</td></tr>
/// <tr><td>SID_TYPE_WKN_GRP</td><td>Builtin group</td></tr>
/// <tr><td>SID_TYPE_DELETED</td><td>Deleted</td></tr>
/// <tr><td>SID_TYPE_INVALID</td><td>Invalid</td></tr>
/// <tr><td>SID_TYPE_UNKNOWN</td><td>Unknown</td></tr>
/// </table>
/// </tt>
/// </remarks>
public virtual int GetType ( )
{
if ( OriginServer ! = null )
{
ResolveWeak ( ) ;
}
return Type ;
}
/// <summary>
/// Return text represeting the SID type suitable for display to
/// users.
/// </summary>
/// <remarks>
/// Return text represeting the SID type suitable for display to
/// users. Text includes 'User', 'Domain group', 'Local group', etc.
/// </remarks>
public virtual string GetTypeText ( )
{
if ( OriginServer ! = null )
{
ResolveWeak ( ) ;
}
return SidTypeNames [ Type ] ;
}
/// <summary>
/// Return the domain name of this SID unless it could not be
/// resolved in which case the numeric representation is returned.
/// </summary>
/// <remarks>
/// Return the domain name of this SID unless it could not be
/// resolved in which case the numeric representation is returned.
/// </remarks>
public virtual string GetDomainName ( )
{
if ( OriginServer ! = null )
{
ResolveWeak ( ) ;
}
if ( Type = = SidTypeUnknown )
{
string full = ToString ( ) ;
return Runtime . Substring ( full , 0 , full . Length - GetAccountName ( ) . Length - 1 ) ;
}
return DomainName ;
}
/// <summary>
/// Return the sAMAccountName of this SID unless it could not
/// be resolved in which case the numeric RID is returned.
/// </summary>
/// <remarks>
/// Return the sAMAccountName of this SID unless it could not
/// be resolved in which case the numeric RID is returned. If this
/// SID is a domain SID, this method will return an empty String.
/// </remarks>
public virtual string GetAccountName ( )
{
if ( OriginServer ! = null )
{
ResolveWeak ( ) ;
}
if ( Type = = SidTypeUnknown )
{
return string . Empty + SubAuthority [ SubAuthorityCount - 1 ] ;
}
if ( Type = = SidTypeDomain )
{
return string . Empty ;
}
return AcctName ;
}
public override int GetHashCode ( )
{
int hcode = IdentifierAuthority [ 5 ] ;
for ( int i = 0 ; i < SubAuthorityCount ; i + + )
{
hcode + = 65599 * SubAuthority [ i ] ;
}
return hcode ;
}
public override bool Equals ( object obj )
{
if ( obj is Sid )
{
Sid sid = ( Sid ) obj ;
if ( sid = = this )
{
return true ;
}
if ( sid . SubAuthorityCount = = SubAuthorityCount )
{
int i = SubAuthorityCount ;
while ( i - - > 0 )
{
if ( sid . SubAuthority [ i ] ! = SubAuthority [ i ] )
{
return false ;
}
}
for ( i = 0 ; i < 6 ; i + + )
{
if ( sid . IdentifierAuthority [ i ] ! = IdentifierAuthority [ i ] )
{
return false ;
}
}
return sid . Revision = = Revision ;
}
}
return false ;
}
/// <summary>
/// Return the numeric representation of this sid such as
/// <tt>S-1-5-21-1496946806-2192648263-3843101252-1029</tt>.
/// </summary>
/// <remarks>
/// Return the numeric representation of this sid such as
/// <tt>S-1-5-21-1496946806-2192648263-3843101252-1029</tt>.
/// </remarks>
public override string ToString ( )
{
string ret = "S-" + ( Revision & unchecked ( 0xFF ) ) + "-" ;
if ( IdentifierAuthority [ 0 ] ! = unchecked ( 0 )
| | IdentifierAuthority [ 1 ] ! = unchecked ( 0 ) )
{
ret + = "0x" ;
ret + = Hexdump . ToHexString ( IdentifierAuthority , 0 , 6 ) ;
}
else
{
int shift = 0 ;
long id = 0 ;
for ( int i = 5 ; i > 1 ; i - - )
{
id + = ( IdentifierAuthority [ i ] & unchecked ( 0xFFL ) ) < < shift ;
shift + = 8 ;
}
ret + = id ;
}
for ( int i1 = 0 ; i1 < SubAuthorityCount ; i1 + + )
{
ret + = "-" + ( SubAuthority [ i1 ] & unchecked ( 0xFFFFFFFFL ) ) ;
}
return ret ;
}
/// <summary>
/// Return a String representing this SID ideal for display to
/// users.
/// </summary>
/// <remarks>
/// Return a String representing this SID ideal for display to
/// users. This method should return the same text that the ACL
/// editor in Windows would display.
/// <p>
/// Specifically, if the SID has
/// been resolved and it is not a domain SID or builtin account,
/// the full DOMAIN\name form of the account will be
/// returned (e.g. MYDOM\alice or MYDOM\Domain Users).
/// If the SID has been resolved but it is is a domain SID,
/// only the domain name will be returned (e.g. MYDOM).
/// If the SID has been resolved but it is a builtin account,
/// only the name component will be returned (e.g. SYSTEM).
/// If the sid cannot be resolved the numeric representation from
/// toString() is returned.
/// </remarks>
public virtual string ToDisplayString ( )
{
if ( OriginServer ! = null )
{
ResolveWeak ( ) ;
}
if ( DomainName ! = null )
{
string str ;
if ( Type = = SidTypeDomain )
{
str = DomainName ;
}
else
{
if ( Type = = SidTypeWknGrp | | DomainName . Equals ( "BUILTIN" ) )
{
if ( Type = = SidTypeUnknown )
{
str = ToString ( ) ;
}
else
{
str = AcctName ;
}
}
else
{
str = DomainName + "\\" + AcctName ;
}
}
return str ;
}
return ToString ( ) ;
}
/// <summary>Manually resolve this SID.</summary>
/// <remarks>
/// Manually resolve this SID. Normally SIDs are automatically
/// resolved. However, if a SID is constructed explicitly using a SID
/// constructor, JCIFS will have no knowledge of the server that created the
/// SID and therefore cannot possibly resolve it automatically. In this case,
/// this method will be necessary.
/// </remarks>
/// <param name="authorityServerName">The FQDN of the server that is an authority for the SID.
/// </param>
/// <param name="auth">Credentials suitable for accessing the SID's information.</param>
/// <exception cref="System.IO.IOException"></exception>
public virtual void Resolve ( string authorityServerName ,
NtlmPasswordAuthentication auth )
{
Sid [ ] sids = new Sid [ 1 ] ;
sids [ 0 ] = this ;
ResolveSids ( authorityServerName , auth , sids ) ;
}
internal virtual void ResolveWeak ( )
{
if ( OriginServer ! = null )
{
try
{
Resolve ( OriginServer , OriginAuth ) ;
}
catch ( IOException )
{
}
finally
{
OriginServer = null ;
OriginAuth = null ;
}
}
}
/// <exception cref="System.IO.IOException"></exception>
internal static Sid [ ] GetGroupMemberSids0 ( DcerpcHandle handle ,
SamrDomainHandle domainHandle ,
Sid domsid ,
int rid ,
int flags )
{
SamrAliasHandle aliasHandle = null ;
Lsarpc . LsarSidArray sidarray = new Lsarpc . LsarSidArray ( ) ;
MsrpcGetMembersInAlias rpc = null ;
try
{
aliasHandle = new SamrAliasHandle ( handle , domainHandle , unchecked ( 0x0002000c ) , rid ) ;
rpc = new MsrpcGetMembersInAlias ( aliasHandle , sidarray ) ;
handle . Sendrecv ( rpc ) ;
if ( rpc . Retval ! = 0 )
{
throw new SmbException ( rpc . Retval , false ) ;
}
Sid [ ] sids = new Sid [ rpc . Sids . NumSids ] ;
string originServer = handle . GetServer ( ) ;
NtlmPasswordAuthentication originAuth
= ( NtlmPasswordAuthentication ) handle . GetPrincipal ( ) ;
for ( int i = 0 ; i < sids . Length ; i + + )
{
sids [ i ] = new Sid ( rpc . Sids . Sids [ i ] . Sid , 0 , null , null , false ) ;
sids [ i ] . OriginServer = originServer ;
sids [ i ] . OriginAuth = originAuth ;
}
if ( sids . Length > 0 & & ( flags & SidFlagResolveSids ) ! = 0 )
{
ResolveSids ( originServer , originAuth , sids ) ;
}
return sids ;
}
finally
{
if ( aliasHandle ! = null )
{
aliasHandle . Close ( ) ;
}
}
}
/// <exception cref="System.IO.IOException"></exception>
public virtual Sid [ ] GetGroupMemberSids ( string authorityServerName ,
NtlmPasswordAuthentication auth ,
int flags )
{
if ( Type ! = SidTypeDomGrp & & Type ! = SidTypeAlias )
{
return new Sid [ 0 ] ;
}
DcerpcHandle handle = null ;
SamrPolicyHandle policyHandle = null ;
SamrDomainHandle domainHandle = null ;
Sid domsid = GetDomainSid ( ) ;
lock ( SidCache )
{
try
{
handle = DcerpcHandle . GetHandle ( "ncacn_np:" + authorityServerName
+ "[\\PIPE\\samr]" , auth ) ;
policyHandle = new SamrPolicyHandle ( handle ,
authorityServerName ,
unchecked ( 0x00000030 ) ) ;
domainHandle = new SamrDomainHandle ( handle ,
policyHandle ,
unchecked ( 0x00000200 ) ,
domsid ) ;
return GetGroupMemberSids0 ( handle ,
domainHandle ,
domsid ,
GetRid ( ) ,
flags ) ;
}
finally
{
if ( handle ! = null )
{
if ( policyHandle ! = null )
{
if ( domainHandle ! = null )
{
domainHandle . Close ( ) ;
}
policyHandle . Close ( ) ;
}
handle . Close ( ) ;
}
}
}
}
/// <summary>
/// This specialized method returns a Map of users and local groups for the
/// target server where keys are SIDs representing an account and each value
/// is an List<object> of SIDs represents the local groups that the account is
/// a member of.
/// </summary>
/// <remarks>
/// This specialized method returns a Map of users and local groups for the
/// target server where keys are SIDs representing an account and each value
/// is an List<object> of SIDs represents the local groups that the account is
/// a member of.
/// <p/>
/// This method is designed to assist with computing access control for a
/// given user when the target object's ACL has local groups. Local groups
/// are not listed in a user's group membership (e.g. as represented by the
/// tokenGroups constructed attribute retrived via LDAP).
/// <p/>
/// Domain groups nested inside a local group are currently not expanded. In
/// this case the key (SID) type will be SID_TYPE_DOM_GRP rather than
/// SID_TYPE_USER.
/// </remarks>
/// <param name="authorityServerName">The server from which the local groups will be queried.
/// </param>
/// <param name="auth">The credentials required to query groups and group members.</param>
/// <param name="flags">
/// Flags that control the behavior of the operation. When all
/// name associated with SIDs will be required, the SID_FLAG_RESOLVE_SIDS
/// flag should be used which causes all group member SIDs to be resolved
/// together in a single more efficient operation.
/// </param>
/// <exception cref="System.IO.IOException"></exception>
internal static Hashtable GetLocalGroupsMap ( string authorityServerName , NtlmPasswordAuthentication
auth , int flags )
{
Sid domsid = GetServerSid ( authorityServerName , auth ) ;
DcerpcHandle handle = null ;
SamrPolicyHandle policyHandle = null ;
SamrDomainHandle domainHandle = null ;
Samr . SamrSamArray sam = new Samr . SamrSamArray ( ) ;
MsrpcEnumerateAliasesInDomain rpc ;
lock ( SidCache )
{
try
{
handle = DcerpcHandle . GetHandle ( "ncacn_np:" + authorityServerName
+ "[\\PIPE\\samr]" , auth ) ;
policyHandle = new SamrPolicyHandle ( handle ,
authorityServerName ,
unchecked ( 0x02000000 ) ) ;
domainHandle = new SamrDomainHandle ( handle ,
policyHandle ,
unchecked ( 0x02000000 ) ,
domsid ) ;
rpc = new MsrpcEnumerateAliasesInDomain ( domainHandle ,
unchecked ( 0xFFFF ) ,
sam ) ;
handle . Sendrecv ( rpc ) ;
if ( rpc . Retval ! = 0 )
{
throw new SmbException ( rpc . Retval , false ) ;
}
2017-04-02 00:36:06 +00:00
Hashtable map = new Hashtable ( ) ;
2017-06-21 06:46:57 +00:00
for ( int ei = 0 ; ei < rpc . Sam . Count ; ei + + )
{
Samr . SamrSamEntry entry = rpc . Sam . Entries [ ei ] ;
Sid [ ] mems = GetGroupMemberSids0 ( handle ,
domainHandle ,
domsid ,
entry . Idx ,
flags ) ;
Sid groupSid = new Sid ( domsid , entry . Idx ) ;
groupSid . Type = SidTypeAlias ;
groupSid . DomainName = domsid . GetDomainName ( ) ;
groupSid . AcctName = ( new UnicodeString ( entry . Name , false ) ) . ToString ( ) ;
for ( int mi = 0 ; mi < mems . Length ; mi + + )
{
List < object > groups = ( List < object > ) map . Get ( mems [ mi ] ) ;
if ( groups = = null )
{
groups = new List < object > ( ) ;
map . Put ( mems [ mi ] , groups ) ;
}
if ( ! groups . Contains ( groupSid ) )
{
groups . Add ( groupSid ) ;
}
}
}
return map ;
}
finally
{
if ( handle ! = null )
{
if ( policyHandle ! = null )
{
if ( domainHandle ! = null )
{
domainHandle . Close ( ) ;
}
policyHandle . Close ( ) ;
}
handle . Close ( ) ;
}
}
}
}
}
2017-04-02 00:36:06 +00:00
}