2010-08-12 5 views
2

Lorsque vous travaillez avec les règles d'accès renvoyés parComment vérifier si un objet NTAccount représente un groupe ou un utilisateur?

GetAccessRules(True, True, GetType(System.Security.Principal.NTAccount)) 

comment puis-je savoir si l'objet NTAccount référencé dans chaque règle est un compte d'utilisateur ou un groupe?

Mise à jour:

j'ai pu résoudre cela comme suit. Notez que l'intention de ce code est de renvoyer True si le NTAccount est un groupe et False sinon ou si une erreur se produit lors de la vérification.

Y a-t-il une meilleure façon de procéder?

Public Function IsGroup(ByVal account As NTAccount) as Boolean 
    Dim samAccountName as string = account.Value 
    Dim accountNameParts() As String = samAccountName.Split("\") 
    If accountNameParts.Count() = 2 Then 
     Dim principalContext As PrincipalContext 
     Try 
      principalContext = New PrincipalContext(ContextType.Domain, accountNameParts(0)) 
     Catch 
      Try 
       principalContext = New PrincipalContext(ContextType.Machine, accountNameParts(0)) 
      Catch 
       principalContext = Nothing 
      End Try 
     End Try 
     If Not principalContext Is Nothing Then 
      Dim principal As Principal 
      principal = principal.FindByIdentity(principalContext, _samAccountName) 
      If Not principal Is Nothing then 
       return TypeOf principal Is GroupPrincipal 
      End If 
     End If 
    End If 
    Return False 
End Function 

Une autre mise à jour:

La solution ci-dessus était correct pour la plupart des serveurs \ objets de compte, mais il échoue pour les objets groupe local sur les serveurs NAS EMC Celerra que nous avons. J'essaie d'utiliser les appels API NetUserGetInfo/NetLocalGroupGetInfo Win pour voir si cela fonctionnera, mais je ne peux pas les faire fonctionner correctement. Voir NetUserGetInfo/NetLocalGroupGetInfo returning error 1722 pour plus de détails.

+0

J'ai travaillé le maintenant. Merci. –

Répondre

1

La réponse à cette question était en effet d'utiliser les API Windows (NetUserGetInfo et NetLocalGroupGetInfo).

Class NetApi 
    Private Declare Unicode Function NetUserGetInfo Lib "Netapi32.dll" (_ 
     ByVal ServerName As String, _ 
     ByVal UserName As String, _ 
     ByVal level As Integer, _ 
     ByRef BufPtr As IntPtr) As Integer 

    Private Declare Unicode Function NetLocalGroupGetInfo Lib "Netapi32.dll" (_ 
     ByVal ServerName As String, _ 
     ByVal GroupName As String, _ 
     ByVal level As Integer, _ 
     ByRef BufPtr As IntPtr) As Integer 

    Declare Unicode Function NetApiBufferFree Lib "netapi32.dll" _ 
    (ByRef buffer As IntPtr) As Long 

    Public Shared Function PrincipalIsGroup(ByVal MachineName As String, ByVal AccountName As String) As String 
     If String.IsNullOrEmpty(MachineName) Then 
      Throw New ArgumentException("MachineName is Required") 
     End If 
     If String.IsNullOrEmpty(AccountName) Then 
      Throw New ArgumentException("AccountName is Required") 
     End If 
     Dim returnValue As String = "NotFound" 
     Dim bufPtr As IntPtr 
     Dim lngReturn As Integer = NetLocalGroupGetInfo("\\" & MachineName, AccountName, 0, bufPtr) 
     Call NetApiBufferFree(bufPtr) 
     bufPtr = IntPtr.Zero 
     If lngReturn = 0 Then 
      returnValue = "True" 
     Else 
      lngReturn = NetUserGetInfo("\\" & MachineName, AccountName, 0, bufPtr) 
      Call NetApiBufferFree(bufPtr) 
      bufPtr = IntPtr.Zero 
      If lngReturn = 0 Then 
       returnValue = "False" 
      End If 
     End If 
     Return returnValue 
    End Function 
End Class 
2

je suis tombé sur le même problème que vous avez. Après avoir fait quelques recherches partout j'ai finalement trouvé une solution décente pour résoudre ceci: L'idée est d'utiliser WinAPI LookupAccountSid. J'ai testé cela à la fois contre les comptes de domaine et locaux. Domaine \ Utilisateur, Autorité NT \ Système, Nom machine \ Administrateurs fonctionneront tous. Notez que je ne mets aucune gestion des exceptions là. Vous pouvez juger quel genre de manipulation est acceptable pour votre scénario. Pour obtenir l'exception, vous pouvez utiliser System.Runtime.InteropServices.Marshal.GetLastWin32Error()

public enum PrincipalType 
{ 
    User, 
    Group 
} 
public bool TryGetPrincipalType(string domainQualifiedName, out PrincipalType type) 
{ 
     var name = new StringBuilder(); 
     var cchName = (uint) name.Capacity; 
     var referencedDomainName = new StringBuilder(); 
     var cchReferencedDomainName = (uint) referencedDomainName.Capacity; 
     SID_NAME_USE sidType; 

     var account = new NTAccount(domainQualifiedName); 

     var id = new SecurityIdentifier(account.Translate(typeof (SecurityIdentifier)).Value); 
     var sidBuffer = new byte[id.BinaryLength]; 
     id.GetBinaryForm(sidBuffer, 0); 

     if (LookupAccountSid(null, sidBuffer, name, ref cchName, referencedDomainName, 
          ref cchReferencedDomainName, out sidType)) 
     { 
      switch (sidType) 
      { 
       case SID_NAME_USE.SidTypeGroup: 
       case SID_NAME_USE.SidTypeWellKnownGroup: 
       case SID_NAME_USE.SidTypeAlias: 
        type = PrincipalType.Group; 
        return true; 
       case SID_NAME_USE.SidTypeUser: 
        type = PrincipalType.User; 
        return true; 
      } 
     } 
     type = default(PrincipalType); 
     return false; 
    } 
private enum SID_NAME_USE 
{ 
    SidTypeUser = 1, 
    SidTypeGroup, 
    SidTypeDomain, 
    SidTypeAlias, 
    SidTypeWellKnownGroup, 
    SidTypeDeletedAccount, 
    SidTypeInvalid, 
    SidTypeUnknown, 
    SidTypeComputer 
} 
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
private static extern bool LookupAccountSid(
     string lpSystemName, 
     [MarshalAs(UnmanagedType.LPArray)] byte[] Sid, 
     StringBuilder lpName, 
     ref uint cchName, 
     StringBuilder ReferencedDomainName, 
     ref uint cchReferencedDomainName, 
     out SID_NAME_USE peUse); 
Questions connexes