Problem querying LDAP and/or Active Directory

A

Andrew

Hey all,

Working on revamping our Intranet here and making use of the LDPA, Active
Directory, Directory Services, etc. that .Net provides. I am still fairly
new on this subject, so the problem I have run into I am not sure how to
fix, and really not sure what is causing it.

Here's what is going on (test server - Windows 2003 Server):
I have a page in a folder (under anonymous authentication in IIS6) that has
a link on it that redirects the user to a page in a folder that is set to
use Integrated Windows Authentication but not anonymous. When redirected,
the IIS security setting forces the user to log in. Now, in the code of
this "login page" I get the user name via
"Context.User.Identity.Name.ToString" and store that to a Session Variable.
I found a bit of code that queries the LDAP server for the full name of a
user
(http://www.411asp.net/func/content?tree=411asp/tutorial/howto/usermana&id=3
972310) which I have put into a class file. After storing the user name, I
set the properties and query the LDAP server, using the function of that
class file, for the user's Full Name. I then save the full name to a
Session Variable as well. The last thing the page does is redirect back to
the starting page. Back on the starting page I then display the contents of
the user and full name Session Variables.
The point here is so I can keep my pages set to Anonymous under II6, but if
I can "authenticate" the visitor, then I can have the code-behind page "turn
on" extra features and what not. Other wise, the page comes up in normal
mode.

My problem...
This all works just fine as long as I am viewing the page from a browser on
the test box. When I fire up a browser on my machine and navigate to the
page on the test box, it errors out. The error is occurring on the second
page described above. I save the error message to a Session Variable and
display that variable's contents back on the first page if an error
occurred. This is the error I get:

System.Runtime.InteropServices.COMException (0x80072020): An operations
error occurred
at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
at System.DirectoryServices.DirectoryEntry.Bind()
at System.DirectoryServices.DirectoryEntry.get_AdsObject()
at System.DirectoryServices.DirectorySearcher.FindAll(Boolean
findMoreThanOne)
at System.DirectoryServices.DirectorySearcher.FindAll()
at WinAuth.Auth.adsi.GetUserProps() in
c:\inetpub\wwwroot\WinAuth\adsi.vb:line 66
at WinAuth.index.Page_Load(Object sender, EventArgs e) in
c:\inetpub\wwwroot\WinAuth\login\index.aspx.vb:line 35

I need help here understanding what is going on and why this is happening.
I am thinking it is a permissions issue...in that when I am on the test box,
I can run stuff, but when viewing from a remote box I can't. Or could it be
trying to query the LDAP box from a remote machine? I am at a bit of a loss
here.

Your help is greatly appreciated.

-- Andrew

[Code Segment]

** First Page HTML **
----------------------------------------------------------
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="index.aspx.vb"
Inherits="WinAuth.index1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<title>index</title>
<meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
<meta content="Visual Basic .NET 7.1" name="CODE_LANGUAGE">
<meta content="JavaScript" name="vs_defaultClientScript">
<meta content="http://schemas.microsoft.com/intellisense/ie5"
name="vs_targetSchema">
</HEAD>
<body style="MARGIN: 0px">
<form id="Form1" method="post" runat="server">
<TABLE id="Table1" cellSpacing="1" cellPadding="5" width="100%"
border="0">
<TR>
<TD vAlign="top" noWrap align="center" width="125">
<P><asp:label id="lblStatus" runat="server"
Visible="false"></asp:label><br>
<asp:linkbutton id="lnkLogin" runat="server"
Visible="false">Please Log In</asp:linkbutton><asp:label id="lblName"
runat="server" Visible="false"></asp:label></P>
</TD>
<TD vAlign="top" width="100%">
<DIV align="center"><asp:label id="Label2" runat="server"
Font-Bold="True" Font-Size="18pt"
Font-Names="Tahoma">Welcome</asp:label></DIV>
<P align="justify">&nbsp;&nbsp;&nbsp;&nbsp;Lorem ipsum dolor sit
amet,
consectetuer adipiscing elit. Praesent consequat porta sapien.
Fusce eleifend
urna sit amet justo. Nunc pellentesque justo vel neque. Donec
nonummy ante vel
metus. In aliquam vehicula leo. Curabitur metus. Donec arcu
orci, ultrices ac,
rutrum id, hendrerit vel, tellus. Duis lobortis malesuada
odio. Proin sed enim.
Proin vitae turpis. Integer mollis. Aenean ac quam. Quisque
vulputate purus sit
amet risus.
<br>
</P>
<div align="right"><asp:linkbutton id="lnkEdit" runat="server"
Visible="false">Edit Text</asp:linkbutton></div>
</TD>
</TR>
</TABLE>
<div align="center" style="width:500px;">
<p align="justify">
<asp:Label id="lblError" runat="server"
Visible="false"></asp:Label>
</p>
</div>
</form>
</body>
</HTML>
----------------------------------------------------------

** First Page Code-Behind **
----------------------------------------------------------
Public Class index1
Inherits System.Web.UI.Page

#Region " Web Form Designer Generated Code "

'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()

End Sub
Protected WithEvents lblStatus As System.Web.UI.WebControls.Label
Protected WithEvents Label2 As System.Web.UI.WebControls.Label
Protected WithEvents lnkEdit As System.Web.UI.WebControls.LinkButton
Protected WithEvents lnkLogin As System.Web.UI.WebControls.LinkButton
Protected WithEvents lblName As System.Web.UI.WebControls.Label
Protected WithEvents lblError As System.Web.UI.WebControls.Label

'NOTE: The following placeholder declaration is required by the Web Form
Designer.
'Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object

Private Sub Page_Init(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub

#End Region

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
'Put user code to initialize the page here
If Not Page.IsPostBack Then
Select Case UserIsKnown()
Case False
lblStatus.Text = "Anonymous User"
lblStatus.Visible = True
lnkLogin.Visible = True
Case True
Response.Write("<!-- Session(""FullName""): " &
Session("FullName") & " -->" & ControlChars.NewLine)
Response.Write("<!-- Session(""UserName""): " &
Session("UserName") & " -->" & ControlChars.NewLine)
Dim FullName As String = Session("FullName")
Dim UserName As String = Session("UserName")
lblStatus.Text = "Welcome Back!"
lblStatus.Visible = True
lblName.Text = FullName
lblName.Visible = True
lnkEdit.Visible = True
End Select
If Not Session("Error") Is Nothing Then
lblError.Text = "<PRE>" & ControlChars.NewLine &
Session("Error") & "</PRE>"
lblError.Visible = True
End If
End If
End Sub

Private Function UserIsKnown() As Boolean
If Session("LoggedIn") Is Nothing Then Session("LoggedIn") = False
Return (Context.User.Identity.IsAuthenticated Or
Session("LoggedIn"))
End Function

Private Sub lnkLogin_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles lnkLogin.Click
Response.Redirect("/WinAuth/Login/", True)
End Sub
End Class

----------------------------------------------------------

** Second Page HTML **
----------------------------------------------------------
No HTML was added to default "new page html"
----------------------------------------------------------

** Second Page Code-Behind **
----------------------------------------------------------
Public Class index
Inherits System.Web.UI.Page
Private cADSI As New Auth.adsi

#Region " Web Form Designer Generated Code "

'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()

End Sub

'NOTE: The following placeholder declaration is required by the Web Form
Designer.
'Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object

Private Sub Page_Init(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub

#End Region

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
'Put user code to initialize the page here
If Context.User.Identity.IsAuthenticated Then
Try
Session("LoggedIn") = True
Session("UserName") = Context.User.Identity.Name.ToString
Session("UserName") =
Session("UserName").Substring(Session("UserName").IndexOf("\") + 1)
With cADSI
.AD_ServerName = "pdcdns"
.AD_ServiceProvider = "LDAP"
.AD_UserName = Session("UserName")
Session("FullName") = .GetUserProps()
End With
If Session("FullName") = "" Then
Session("LoggedIn") = False
End If
Catch ex As Exception
Session("LoggedIn") = False
Session("Error") = ex.ToString
End Try
End If
Response.Redirect("/WinAuth/", True)
End Sub

End Class

----------------------------------------------------------

** Class File **
----------------------------------------------------------
'// Example By James Arceri
'// Please send comments or questions to: (e-mail address removed)
'// Code taken from:
http://www.411asp.net/func/content?tree=411asp/tutorial/howto/usermana&id=3972310
Imports System
Imports System.DirectoryServices
Imports System.Text

Namespace Auth

' Active Directory Services Interfaces
Public Class adsi

Private mvar_AD_ServerName As String
Private mvar_AD_ServiceProvider As String
Private mvar_AD_UserName As String

' Active Directory server name
Public Property AD_ServerName() As String
Get
Return mvar_AD_ServerName
End Get
Set(ByVal Value As String)
mvar_AD_ServerName = Value
End Set
End Property

' Active Directory Service provider
Public Property AD_ServiceProvider() As String
Get
Return mvar_AD_ServiceProvider
End Get
Set(ByVal Value As String)
mvar_AD_ServiceProvider = Value
End Set
End Property

' Active Directory username
Public Property AD_UserName() As String
Get
Return mvar_AD_UserName
End Get
Set(ByVal Value As String)
mvar_AD_UserName = Value
End Set
End Property

' Gets the info for a specific user
' Currently only supports Lightweight Directory Access Protocol
(LDAP) binding
Public Function GetUserProps() As String
Try
Dim strUserName As Array = Split(mvar_AD_UserName, "\", -1,
1)
Dim strFullName As String
Dim sPath As String
Dim objDirEnt As New
DirectoryServices.DirectoryEntry(mvar_AD_ServiceProvider & "://" &
mvar_AD_ServerName)
Dim objSearcher As New
System.DirectoryServices.DirectorySearcher(objDirEnt)
Dim objSearchRes As System.DirectoryServices.SearchResult
objSearcher.Filter = ("(anr=" & strUserName(0) & ")")
For Each objSearchRes In objSearcher.FindAll
sPath = objSearchRes.GetDirectoryEntry.Path
Next
objDirEnt.Close()
objDirEnt.Path = sPath
strFullName = objDirEnt.Invoke("GET", "Name")
Return strFullName
Catch ex As Exception
Throw
End Try
End Function

End Class

End Namespace
----------------------------------------------------------
 
K

Kevin Spencer

I need help here understanding what is going on and why this is happening.
I am thinking it is a permissions issue...in that when I am on the test box,
I can run stuff, but when viewing from a remote box I can't. Or could it be
trying to query the LDAP box from a remote machine? I am at a bit of a loss
here.

Hard to answer, Andy. Is the remote machine a member of the same domain as
the machine on which you're testing? Are you using machine-level AD or
domain-level? In an Active Directory domain, you would want to be querying
the domain's Active Directory, not the local machine's. In addition, if you
want to get the currently logged-on user, that user must have had to log on
to the web site without using Anonymous access. IOW, you need to require a
domain login for the web site on which this app is running, so that the
client must log in with domain credentials instead of anonymous credentials.

--
HTH,
Kevin Spencer
..Net Developer
Microsoft MVP
Big things are made up
of lots of little things.

Andrew said:
Hey all,

Working on revamping our Intranet here and making use of the LDPA, Active
Directory, Directory Services, etc. that .Net provides. I am still fairly
new on this subject, so the problem I have run into I am not sure how to
fix, and really not sure what is causing it.

Here's what is going on (test server - Windows 2003 Server):
I have a page in a folder (under anonymous authentication in IIS6) that has
a link on it that redirects the user to a page in a folder that is set to
use Integrated Windows Authentication but not anonymous. When redirected,
the IIS security setting forces the user to log in. Now, in the code of
this "login page" I get the user name via
"Context.User.Identity.Name.ToString" and store that to a Session Variable.
I found a bit of code that queries the LDAP server for the full name of a
user
(http://www.411asp.net/func/content?tree=411asp/tutorial/howto/usermana&id=3
972310) which I have put into a class file. After storing the user name, I
set the properties and query the LDAP server, using the function of that
class file, for the user's Full Name. I then save the full name to a
Session Variable as well. The last thing the page does is redirect back to
the starting page. Back on the starting page I then display the contents of
the user and full name Session Variables.
The point here is so I can keep my pages set to Anonymous under II6, but if
I can "authenticate" the visitor, then I can have the code-behind page "turn
on" extra features and what not. Other wise, the page comes up in normal
mode.

My problem...
This all works just fine as long as I am viewing the page from a browser on
the test box. When I fire up a browser on my machine and navigate to the
page on the test box, it errors out. The error is occurring on the second
page described above. I save the error message to a Session Variable and
display that variable's contents back on the first page if an error
occurred. This is the error I get:

System.Runtime.InteropServices.COMException (0x80072020): An operations
error occurred
at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
at System.DirectoryServices.DirectoryEntry.Bind()
at System.DirectoryServices.DirectoryEntry.get_AdsObject()
at System.DirectoryServices.DirectorySearcher.FindAll(Boolean
findMoreThanOne)
at System.DirectoryServices.DirectorySearcher.FindAll()
at WinAuth.Auth.adsi.GetUserProps() in
c:\inetpub\wwwroot\WinAuth\adsi.vb:line 66
at WinAuth.index.Page_Load(Object sender, EventArgs e) in
c:\inetpub\wwwroot\WinAuth\login\index.aspx.vb:line 35

I need help here understanding what is going on and why this is happening.
I am thinking it is a permissions issue...in that when I am on the test box,
I can run stuff, but when viewing from a remote box I can't. Or could it be
trying to query the LDAP box from a remote machine? I am at a bit of a loss
here.

Your help is greatly appreciated.

-- Andrew

[Code Segment]

** First Page HTML **
----------------------------------------------------------
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="index.aspx.vb"
Inherits="WinAuth.index1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<title>index</title>
<meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
<meta content="Visual Basic .NET 7.1" name="CODE_LANGUAGE">
<meta content="JavaScript" name="vs_defaultClientScript">
<meta content="http://schemas.microsoft.com/intellisense/ie5"
name="vs_targetSchema">
</HEAD>
<body style="MARGIN: 0px">
<form id="Form1" method="post" runat="server">
<TABLE id="Table1" cellSpacing="1" cellPadding="5" width="100%"
border="0">
<TR>
<TD vAlign="top" noWrap align="center" width="125">
<P><asp:label id="lblStatus" runat="server"
Visible="false"></asp:label><br>
<asp:linkbutton id="lnkLogin" runat="server"
Visible="false">Please Log In</asp:linkbutton><asp:label id="lblName"
runat="server" Visible="false"></asp:label></P>
</TD>
<TD vAlign="top" width="100%">
<DIV align="center"><asp:label id="Label2" runat="server"
Font-Bold="True" Font-Size="18pt"
Font-Names="Tahoma">Welcome</asp:label></DIV>
<P align="justify">&nbsp;&nbsp;&nbsp;&nbsp;Lorem ipsum dolor sit
amet,
consectetuer adipiscing elit. Praesent consequat porta sapien.
Fusce eleifend
urna sit amet justo. Nunc pellentesque justo vel neque. Donec
nonummy ante vel
metus. In aliquam vehicula leo. Curabitur metus. Donec arcu
orci, ultrices ac,
rutrum id, hendrerit vel, tellus. Duis lobortis malesuada
odio. Proin sed enim.
Proin vitae turpis. Integer mollis. Aenean ac quam. Quisque
vulputate purus sit
amet risus.
<br>
</P>
<div align="right"><asp:linkbutton id="lnkEdit" runat="server"
Visible="false">Edit Text</asp:linkbutton></div>
</TD>
</TR>
</TABLE>
<div align="center" style="width:500px;">
<p align="justify">
<asp:Label id="lblError" runat="server"
Visible="false"></asp:Label>
</p>
</div>
</form>
</body>
</HTML>
----------------------------------------------------------

** First Page Code-Behind **
----------------------------------------------------------
Public Class index1
Inherits System.Web.UI.Page

#Region " Web Form Designer Generated Code "

'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()

End Sub
Protected WithEvents lblStatus As System.Web.UI.WebControls.Label
Protected WithEvents Label2 As System.Web.UI.WebControls.Label
Protected WithEvents lnkEdit As System.Web.UI.WebControls.LinkButton
Protected WithEvents lnkLogin As System.Web.UI.WebControls.LinkButton
Protected WithEvents lblName As System.Web.UI.WebControls.Label
Protected WithEvents lblError As System.Web.UI.WebControls.Label

'NOTE: The following placeholder declaration is required by the Web Form
Designer.
'Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object

Private Sub Page_Init(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub

#End Region

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
'Put user code to initialize the page here
If Not Page.IsPostBack Then
Select Case UserIsKnown()
Case False
lblStatus.Text = "Anonymous User"
lblStatus.Visible = True
lnkLogin.Visible = True
Case True
Response.Write("<!-- Session(""FullName""): " &
Session("FullName") & " -->" & ControlChars.NewLine)
Response.Write("<!-- Session(""UserName""): " &
Session("UserName") & " -->" & ControlChars.NewLine)
Dim FullName As String = Session("FullName")
Dim UserName As String = Session("UserName")
lblStatus.Text = "Welcome Back!"
lblStatus.Visible = True
lblName.Text = FullName
lblName.Visible = True
lnkEdit.Visible = True
End Select
If Not Session("Error") Is Nothing Then
lblError.Text = "<PRE>" & ControlChars.NewLine &
Session("Error") & "</PRE>"
lblError.Visible = True
End If
End If
End Sub

Private Function UserIsKnown() As Boolean
If Session("LoggedIn") Is Nothing Then Session("LoggedIn") = False
Return (Context.User.Identity.IsAuthenticated Or
Session("LoggedIn"))
End Function

Private Sub lnkLogin_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles lnkLogin.Click
Response.Redirect("/WinAuth/Login/", True)
End Sub
End Class

----------------------------------------------------------

** Second Page HTML **
----------------------------------------------------------
No HTML was added to default "new page html"
----------------------------------------------------------

** Second Page Code-Behind **
----------------------------------------------------------
Public Class index
Inherits System.Web.UI.Page
Private cADSI As New Auth.adsi

#Region " Web Form Designer Generated Code "

'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()

End Sub

'NOTE: The following placeholder declaration is required by the Web Form
Designer.
'Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object

Private Sub Page_Init(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub

#End Region

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
'Put user code to initialize the page here
If Context.User.Identity.IsAuthenticated Then
Try
Session("LoggedIn") = True
Session("UserName") = Context.User.Identity.Name.ToString
Session("UserName") =
Session("UserName").Substring(Session("UserName").IndexOf("\") + 1)
With cADSI
.AD_ServerName = "pdcdns"
.AD_ServiceProvider = "LDAP"
.AD_UserName = Session("UserName")
Session("FullName") = .GetUserProps()
End With
If Session("FullName") = "" Then
Session("LoggedIn") = False
End If
Catch ex As Exception
Session("LoggedIn") = False
Session("Error") = ex.ToString
End Try
End If
Response.Redirect("/WinAuth/", True)
End Sub

End Class

----------------------------------------------------------

** Class File **
----------------------------------------------------------
'// Example By James Arceri
'// Please send comments or questions to: (e-mail address removed)
'// Code taken from:
http://www.411asp.net/func/content?tree=411asp/tutorial/howto/usermana&id=3972310
Imports System
Imports System.DirectoryServices
Imports System.Text

Namespace Auth

' Active Directory Services Interfaces
Public Class adsi

Private mvar_AD_ServerName As String
Private mvar_AD_ServiceProvider As String
Private mvar_AD_UserName As String

' Active Directory server name
Public Property AD_ServerName() As String
Get
Return mvar_AD_ServerName
End Get
Set(ByVal Value As String)
mvar_AD_ServerName = Value
End Set
End Property

' Active Directory Service provider
Public Property AD_ServiceProvider() As String
Get
Return mvar_AD_ServiceProvider
End Get
Set(ByVal Value As String)
mvar_AD_ServiceProvider = Value
End Set
End Property

' Active Directory username
Public Property AD_UserName() As String
Get
Return mvar_AD_UserName
End Get
Set(ByVal Value As String)
mvar_AD_UserName = Value
End Set
End Property

' Gets the info for a specific user
' Currently only supports Lightweight Directory Access Protocol
(LDAP) binding
Public Function GetUserProps() As String
Try
Dim strUserName As Array = Split(mvar_AD_UserName, "\", -1,
1)
Dim strFullName As String
Dim sPath As String
Dim objDirEnt As New
DirectoryServices.DirectoryEntry(mvar_AD_ServiceProvider & "://" &
mvar_AD_ServerName)
Dim objSearcher As New
System.DirectoryServices.DirectorySearcher(objDirEnt)
Dim objSearchRes As System.DirectoryServices.SearchResult
objSearcher.Filter = ("(anr=" & strUserName(0) & ")")
For Each objSearchRes In objSearcher.FindAll
sPath = objSearchRes.GetDirectoryEntry.Path
Next
objDirEnt.Close()
objDirEnt.Path = sPath
strFullName = objDirEnt.Invoke("GET", "Name")
Return strFullName
Catch ex As Exception
Throw
End Try
End Function

End Class

End Namespace
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top