Sunday, January 22, 2012

Fetching logins from various sources - Active Directory, WIndows local logins and SQL Logins

At times there is need to get the list of logins from active directory, windows local logins or sql logins.Microsoft has done very good job of providing namespaces to fetch login info from various sources.Small example attached shows you how to use the namespace and gives some insight about the namespace, hope this helps someone out there.

Active Directory Users:


Windows Logins:

SQL logins:

Private Sub GetUser(ByVal sr As SearchResult, ByVal d As Domain, ByVal domainName As String, ByRef groupMembers As SortedList(Of String, CustomLoginNode))

If sr.Properties(LDAP_PROPERTY_USER_NAME) Is Nothing Then Return

Dim adn As New CustomLoginNode
Dim Searcher As DirectorySearcher
Dim Result As SearchResult
Dim UserEntry As DirectoryEntry

If sr.Properties(LDAP_PROPERTY_USER_NAME) IsNot Nothing Then
''this doamin name is PME , d.name = pme.local
adn.DomainName = domainName
adn.UserName = sr.Properties(LDAP_PROPERTY_USER_NAME)(0).ToString()
adn.UserNameWithDomainName = adn.DomainName + "\" + adn.UserName
End If

Searcher = New DirectorySearcher(d.GetDirectoryEntry)
Searcher.Filter = "(&(objectCategory=person)(objectClass=user)(samaccountname=" & adn.UserName & "))"
Searcher.PropertiesToLoad.Add(LDAP_PROPERTY_FIRST_NAME)
Searcher.PropertiesToLoad.Add(LDAP_PROPERTY_LAST_NAME)
Searcher.PropertiesToLoad.Add(LDAP_PROPERTY_EMAIL)

Result = Searcher.FindOne

If Result IsNot Nothing Then

UserEntry = Result.GetDirectoryEntry()

If UserEntry.Properties(LDAP_PROPERTY_FIRST_NAME).Value IsNot Nothing Then
adn.FirstName = UserEntry.Properties(LDAP_PROPERTY_FIRST_NAME).Value.ToString()
End If
If UserEntry.Properties(LDAP_PROPERTY_LAST_NAME).Value IsNot Nothing Then
adn.LastName = UserEntry.Properties(LDAP_PROPERTY_LAST_NAME).Value.ToString()
End If
If UserEntry.Properties(LDAP_PROPERTY_EMAIL).Value IsNot Nothing Then
adn.Email = UserEntry.Properties(LDAP_PROPERTY_EMAIL).Value.ToString()
End If

End If

adn.UserNameWithDomainNameAndFullName = GetFullName(adn.UserNameWithDomainName, adn.FirstName, adn.LastName)

If Not groupMembers.ContainsKey(adn.UserNameWithDomainName) Then
groupMembers.Add(adn.UserNameWithDomainName, adn)
End If

End Sub


Private Function getUsersInGroup(ByVal strGroupDN As String, ByVal d As Domain) As SortedList(Of String, CustomLoginNode)
Dim groupMembers As New SortedList(Of String, CustomLoginNode)

''To get the users from the nested groups
Dim CurrentGroupsAndNestedGroups As New SortedList(Of String, String)
Dim DomainName As String = String.Empty

''this doamin name is PME , d.name = pme.local
DomainName = d.GetDirectoryEntry.Properties("dc").Value.ToString.ToUpper

Dim ds As New DirectorySearcher(d.GetDirectoryEntry)
ds.PropertiesToLoad.Add(LDAP_PROPERTY_USER_NAME)

Try
If String.IsNullOrEmpty(strGroupDN) Then
ds.Filter = "(&(objectClass=user)(objectCategory=person))"
For Each sr As SearchResult In ds.FindAll()
WriteLog("getUsersInGroup first for DomainName " + DomainName)
GetUser(sr, d, DomainName, groupMembers)
Next
Return groupMembers
Else
''get the nested groups of the current group
CurrentGroupsAndNestedGroups = GetGroups(strGroupDN, d)

''adding the current group to the list
If Not CurrentGroupsAndNestedGroups.ContainsKey(strGroupDN) Then
CurrentGroupsAndNestedGroups.Add(strGroupDN, strGroupDN)
End If

For Each kv As KeyValuePair(Of String, String) In CurrentGroupsAndNestedGroups
ds.Filter = [String].Format("(&(memberOf={0})(objectClass=person))", kv.Key)

For Each sr As SearchResult In ds.FindAll()
WriteLog("getUsersInGroup DomainName second for " + DomainName)
GetUser(sr, d, DomainName, groupMembers)
Next
Next

Return groupMembers
End If
Catch ex As Exception
ProcessException(ex)
End Try

Return groupMembers
End Function

Private Function GetGroups(ByVal strGroupDN As String, ByVal d As Domain) As SortedList(Of String, String)
''for sorting and to avoid duplicates, otherwise would have used list of string
Dim groups As New SortedList(Of String, String)

' find all nested groups in this group
Dim ds As New DirectorySearcher(d.GetDirectoryEntry)

''if groupdn is not sent then return all the groups in the domain
If String.IsNullOrWhiteSpace(strGroupDN) Then
ds.Filter = "(&(objectClass=group))"
Else
''if groupdn is there then return the groups of the groupdn(nested groups)
ds.Filter = [String].Format("(&(memberOf={0})(objectClass=group))", strGroupDN)
End If

ds.PropertiesToLoad.Add(LDAP_PROPERTY_GROUP)

For Each sr As SearchResult In ds.FindAll()
WriteLog("GetGroups for " + strGroupDN)
Dim grpname As String = sr.Properties(LDAP_PROPERTY_GROUP)(0).ToString()
If Not groups.ContainsKey(grpname) Then
groups.Add(grpname, grpname)
End If
Next

Return groups
End Function



Private Sub LoadServerLocalGroupUsers(ByVal grpname As String, ByVal grpnode As TreeNode)

Dim serverName As String = txtServerName.Text
If String.IsNullOrEmpty(serverName) Then Return

Using groupEntry As New DirectoryEntry("WinNT://" + serverName + "/" + grpname + ",group")
For Each member As Object In DirectCast(groupEntry.Invoke("Members"), IEnumerable)
Using memberEntry As New DirectoryEntry(member)
If memberEntry.Parent.Name.ToLower = serverName.ToLower Then
BuildUserNodeForLocalUser(memberEntry, grpnode)
End If
End Using
Next
End Using
End Sub

Private Sub LoadWindowsUsers()
Dim serverName As String = txtServerName.Text
If String.IsNullOrEmpty(serverName) Then Return

Dim localMachinede As DirectoryEntry = New DirectoryEntry("WinNT://" + serverName)

Dim snd As New TreeNode
snd.Text = serverName
trvwUsers.Nodes.Add(snd)

Dim pund As New TreeNode
pund.Text = NODE_TEXT_USERS
snd.Nodes.Add(pund)

Dim gsnd As New TreeNode
gsnd.Text = NODE_TEXT_GROUPS
snd.Nodes.Add(gsnd)

For Each UserEntry As DirectoryEntry In localMachinede.Children
If UserEntry.SchemaClassName = "User" Then
BuildUserNodeForLocalUser(UserEntry, pund)
ElseIf UserEntry.SchemaClassName = "Group" Then
Dim gnd As New TreeNode
gnd.Text = UserEntry.Name
Dim adn1 As New CustomLoginNode
adn1.Source = CustomLoginNode.Sources.WindowsLocal
adn1.DomainName = UserEntry.Name
adn1.DirectoryEntry = localMachinede
adn1.NodeType = CustomLoginNode.NodeTypes.Groups
adn1.UserType = CustomLoginNode.UserTypes.WindowsLogin
gnd.Tag = adn1
gsnd.Nodes.Add(gnd)
gnd.Nodes.Add("")
End If
UserEntry.Dispose()
Next
trvwUsers.SelectedNode = pund
End Sub

Private Sub LoadSQLServerUsers()

Dim svr As Server = New Server(txtServerName.Text)
svr.ConnectionContext.LoginSecure = True

Dim pund As New TreeNode
pund.Text = NODE_TEXT_USERS
trvwUsers.Nodes.Add(pund)

For Each login As Login In svr.Logins
If login.LoginType = LoginType.SqlLogin Then
Dim und As New TreeNode
und.Text = login.Name
Dim adn1 As New CustomLoginNode
adn1.NodeType = CustomLoginNode.NodeTypes.User
adn1.UserType = CustomLoginNode.UserTypes.SQLLogin
und.Tag = adn1
pund.Nodes.Add(und)
End If
Next

trvwUsers.SelectedNode = pund
End Sub

Imports System.DirectoryServices.ActiveDirectory
Imports System.DirectoryServices
Imports Microsoft.SqlServer.Management.Smo

Download Sample

No comments:

Post a Comment

IIS Manager Crashes on Load/Start Windows 7, IIS 7.5

IIS Manager Crashes on Start  Windows 7, IIS 7.5, Power Shell 5.1. Here is the error I got in the event viewer. IISMANAGER_CRASH IIS Ma...