Ok, but you have to remember that you must ask for those attributes using LDP.exe. If you did not ask, they will not show. Ideally, we would like to verify that the username exists first using Anonymous search, then bind using SSL to that object and verify
the password. Crank out the VB.NET and let's see where we can get.
I confirmed that I had those attributes in ldp.exe. Here's the code I'm using based on your code and some changes just for troubleshooting in case I'm not getting the right thing from the server.
Public Sub LDAP2()
Dim username
As String =
"sreiche" '"uid=sreiche,ou=identify,dc=purdue,dc=edu"
Dim passwrd As
String = "mypass"
Dim adsPath As
String =
"LDAP://dbm.i2a2.purdue.edu/uid=sreiche,ou=identify,dc=purdue,dc=edu"
Dim adsPathSSL
As String =
"LDAP://dbm.i2a2.purdue.edu:636/uid=sreiche,ou=identify,dc=purdue,dc=edu"
Dim userdn As
String = ""
Dim userPath As
String = ""
Dim authenticated
As Boolean =
False
Dim root As DirectoryEntry =
New DirectoryEntry(adsPath,
"", "", AuthenticationTypes.None)
Dim ds As DirectorySearcher =
New DirectorySearcher(root,
"(uid=" & username &
")", New
String() {"cn"})
Try
Dim sr As SearchResult =
Nothing
Dim src As SearchResultCollection = ds.FindAll
If src.Count > 0
Then sr = src(0)
If sr Is
Nothing Then
Throw New ArgumentException("User not found, check username")
userdn = sr.Properties("cn")(0).ToString()userPath = sr.Path
Catch ex As Exception
lblPost.Text = ex.ToString
Finally
root.Dispose()
End Try
Dim SSLEntry As DirectoryEntry =
New DirectoryEntry(adsPath,
"uid=sreiche,ou=authorize,dc=purdue,dc=edu", passwrd, AuthenticationTypes.SecureSocketsLayer)
Try
SSLEntry.RefreshCache()
authenticated = True
Catch ex As Exception
authenticated = False
If lblPost.Text =
"" Then lblPost.Text = ex.ToString()
Finally
SSLEntry.Dispose()
End Try
If lblPost.Text = ""
Then lblPost.Text = authenticated.ToString
End Sub
I added the other path because I wasn't sure if .SecureSocketsLayer would use 636 by default or not. It didn't seem to have any effect though. Anyway, the error I get is on the .RefreshCache line. I get the same "The server is not operational". I changed
the string in the second entry to make sure I was passing the correct username, but I'm not even sure I'm talking to the server based on the error msg. If I pass it a username/pass without using SSL, I get an invalid username/pass error msg from the server
since it won't validate credentials unless using SSL. So to me, it seems as though I'm not getting to the server using SSL. I'm not sure what the difference is in what is happening between .net and ldp.exe.
I will say there's progress. I can now pull up attributes that have read permission without being binded in the first section. At least we're getting somewhere. I'm not sure I understand the difference between some of the things I was trying in the first
revision of code and what is happening in the first section of this version, but I'm happy I can at least get some info.
Is there anything I should do to troublshoot the bind entry/section?
I think you are close. If we are trying to authenticate a uid and password, let's try something like this:
'We will intentionally let the Exception bubble
Public Function Authenticate(username as String, password as String) as Boolean
Dim adsPath As String = "LDAP://dbm.i2a2.purdue.edu/dc=purdue,dc=edu"
Dim userdn As String = String.Empty
Dim userPath As String = String.Empty
'Binds Anonymously
Dim root As DirectoryEntry = New DirectoryEntry( _
adsPath, _
Nothing, _
Nothing, _
AuthenticationTypes.None _
)
Try
Dim ds As DirectorySearcher = New DirectorySearcher( _
root, _
String.Format("(uid={0})", username), _
New String() {"distinguishedName", "dn"} _
)
'It's ok to use FindOne in v2.0 of Fx
Dim sr As SearchResult = ds.FindOne()
If sr Is Nothing Then Throw New ArgumentException("User not found, check username")
'We want the distinguishedName and a binding point for next time
userdn = sr.Properties("dn")(0).ToString()
userPath = sr.Path
'Or we parse the path for the DN if we can't get it directly
'userdn = sr.Path.Split(new char[]{'\\'})[3]
Finally
root.Dispose()
End Try
'Create our secure entry for passing credentials
Dim SSLEntry As DirectoryEntry = New DirectoryEntry( _
userPath, _
userdn, _
password, _
AuthenticationTypes.SecureSocketsLayer _
)
Try
'Forces a bind
Dim object o = SSLEntry.NativeObject
return True
Catch ex As COMException
'Re-throw if not a logon failure
If ex.ErrorCode <> -2147023570 Then Throw
return False
Finally
SSLEntry.Dispose()
End Try
End Function
You should just have to pass a username and password and it will return a boolean if they are authenticated or not. Now, you should wrap this entire method to catch errors since it is designed to let it bubble up. The part you should hook into and inspect
surrounds getting the user's DN. Notice I have commented out one way of doing it. It is best to just ask the directory for the DN directly, but sometimes I don't know which attribute it is held on and it turns out to be easier to just parse the .Path. Just
make sure it is in the 'UID=Foo,...DC=domain' format.
By default, SecureSocketsLayer is going to try and connect to 636, so we don't have to worry about it. Notice I did not bind directly to an object, but the root partition instead. This allows me to find anyone, not just one account.
If you still get the "server not operational error", try putting AuthenticationTypes.None instead of .SecureSocketsLayer to test if it is an issue there.
OK, I tried that code and got the same results. If I change the authentication type to .none, I get an invalid credential as the server automatically rejects any credentials not sent over SSL. I really think this is some sort of issue with the SSL part.
Here's another tidbit. We must have a client certificate. It is installed on our server (through IE). After we did that is when ldp.exe worked so I assumed that it would also make any .net app work also. Is this not true? Do I need to somehow specify
and send the cert with the bind?
This definitely makes me think it has to do with the SSL part. I've been googling like crazy and haven't found anyone successfully using SSL with non-AD. FWIW, this thread is popping up on almost every search I've typed. We're getting popular.
My understanding is that if you have the certificate installed on your machine (either trusted by a root cert or added manually to the trusted root store) then SSL negotiation is automatic. This is much the same way that IE works when browsing to HTTPS:.
Here is what I suspect - you have installed the certificate on the IIS server into the "My" store for the current user and not the machine account. Since ASPNET executes without loading a user profile, the cert must be loaded from the machine certificate store
as no user store will be available. I would try futzing with the certificate store settings and see if you can't get it working.
There are a couple ways to install the certificate and I believe only the Cert Store MMC will let you put it in the machine store, while double-clicking a cert would launch a similar wizard, but no option for a machine store. Check on this and see what you
find.
FINALLY!!! That was it. It was the cert the whole time. Well, at least I learned a lot about LDAP in this whole process. Thank you so much and I hope this helps others.
FINALLY!!! That was it. It was the cert the whole time. Well, at least I learned a lot about LDAP in this whole process. Thank you so much and I hope this helps others.
That's great news, I probably should have asked earlier, but since you said you had ldp.exe working with SSL... I just assumed it was already setup for you. You are now an LDAP troubleshooting pro.
dunnry
Star
9098 Points
1806 Posts
Re: Unknown Error - talking to LDAP not AD
Oct 19, 2005 09:17 PM|LINK
Weblog
The Book
LDAP Programming Help
PurdueGuy
Member
140 Points
28 Posts
Re: Unknown Error - talking to LDAP not AD
Oct 24, 2005 01:53 PM|LINK
I confirmed that I had those attributes in ldp.exe. Here's the code I'm using based on your code and some changes just for troubleshooting in case I'm not getting the right thing from the server.
Public Sub LDAP2()
Dim username As String = "sreiche" '"uid=sreiche,ou=identify,dc=purdue,dc=edu"
Dim passwrd As String = "mypass"
Dim adsPath As String = "LDAP://dbm.i2a2.purdue.edu/uid=sreiche,ou=identify,dc=purdue,dc=edu"
Dim adsPathSSL As String = "LDAP://dbm.i2a2.purdue.edu:636/uid=sreiche,ou=identify,dc=purdue,dc=edu"
Dim userdn As String = ""
Dim userPath As String = ""
Dim authenticated As Boolean = False
Dim root As DirectoryEntry = New DirectoryEntry(adsPath, "", "", AuthenticationTypes.None)
Dim ds As DirectorySearcher = New DirectorySearcher(root, "(uid=" & username & ")", New String() {"cn"})
Try
Dim sr As SearchResult = Nothing
Dim src As SearchResultCollection = ds.FindAll
If src.Count > 0 Then sr = src(0)
If sr Is Nothing Then Throw New ArgumentException("User not found, check username")
userdn = sr.Properties("cn")(0).ToString()userPath = sr.Path
Catch ex As Exception
lblPost.Text = ex.ToString
Finally
root.Dispose()
End Try
Dim SSLEntry As DirectoryEntry = New DirectoryEntry(adsPath, "uid=sreiche,ou=authorize,dc=purdue,dc=edu", passwrd, AuthenticationTypes.SecureSocketsLayer)
Try
SSLEntry.RefreshCache()
authenticated = True
Catch ex As Exception
authenticated = False
If lblPost.Text = "" Then lblPost.Text = ex.ToString()
Finally
SSLEntry.Dispose()
End Try
If lblPost.Text = "" Then lblPost.Text = authenticated.ToString
End Sub
I added the other path because I wasn't sure if .SecureSocketsLayer would use 636 by default or not. It didn't seem to have any effect though. Anyway, the error I get is on the .RefreshCache line. I get the same "The server is not operational". I changed the string in the second entry to make sure I was passing the correct username, but I'm not even sure I'm talking to the server based on the error msg. If I pass it a username/pass without using SSL, I get an invalid username/pass error msg from the server since it won't validate credentials unless using SSL. So to me, it seems as though I'm not getting to the server using SSL. I'm not sure what the difference is in what is happening between .net and ldp.exe.
I will say there's progress. I can now pull up attributes that have read permission without being binded in the first section. At least we're getting somewhere. I'm not sure I understand the difference between some of the things I was trying in the first revision of code and what is happening in the first section of this version, but I'm happy I can at least get some info.
Is there anything I should do to troublshoot the bind entry/section?
Thanks
dunnry
Star
9098 Points
1806 Posts
Re: Unknown Error - talking to LDAP not AD
Oct 24, 2005 09:44 PM|LINK
'We will intentionally let the Exception bubble
Public Function Authenticate(username as String, password as String) as Boolean
Dim adsPath As String = "LDAP://dbm.i2a2.purdue.edu/dc=purdue,dc=edu"
Dim userdn As String = String.Empty
Dim userPath As String = String.Empty
'Binds Anonymously
Dim root As DirectoryEntry = New DirectoryEntry( _
adsPath, _
Nothing, _
Nothing, _
AuthenticationTypes.None _
)
Try
Dim ds As DirectorySearcher = New DirectorySearcher( _
root, _
String.Format("(uid={0})", username), _
New String() {"distinguishedName", "dn"} _
)
'It's ok to use FindOne in v2.0 of Fx
Dim sr As SearchResult = ds.FindOne()
If sr Is Nothing Then Throw New ArgumentException("User not found, check username")
'We want the distinguishedName and a binding point for next time
userdn = sr.Properties("dn")(0).ToString()
userPath = sr.Path
'Or we parse the path for the DN if we can't get it directly
'userdn = sr.Path.Split(new char[]{'\\'})[3]
Finally
root.Dispose()
End Try
'Create our secure entry for passing credentials
Dim SSLEntry As DirectoryEntry = New DirectoryEntry( _
userPath, _
userdn, _
password, _
AuthenticationTypes.SecureSocketsLayer _
)
Try
'Forces a bind
Dim object o = SSLEntry.NativeObject
return True
Catch ex As COMException
'Re-throw if not a logon failure
If ex.ErrorCode <> -2147023570 Then Throw
return False
Finally
SSLEntry.Dispose()
End Try
End Function
You should just have to pass a username and password and it will return a boolean if they are authenticated or not. Now, you should wrap this entire method to catch errors since it is designed to let it bubble up. The part you should hook into and inspect surrounds getting the user's DN. Notice I have commented out one way of doing it. It is best to just ask the directory for the DN directly, but sometimes I don't know which attribute it is held on and it turns out to be easier to just parse the .Path. Just make sure it is in the 'UID=Foo,...DC=domain' format.
By default, SecureSocketsLayer is going to try and connect to 636, so we don't have to worry about it. Notice I did not bind directly to an object, but the root partition instead. This allows me to find anyone, not just one account.
If you still get the "server not operational error", try putting AuthenticationTypes.None instead of .SecureSocketsLayer to test if it is an issue there.
Weblog
The Book
LDAP Programming Help
PurdueGuy
Member
140 Points
28 Posts
Re: Unknown Error - talking to LDAP not AD
Oct 26, 2005 03:34 PM|LINK
This definitely makes me think it has to do with the SSL part. I've been googling like crazy and haven't found anyone successfully using SSL with non-AD. FWIW, this thread is popping up on almost every search I've typed. We're getting popular.
dunnry
Star
9098 Points
1806 Posts
Re: Unknown Error - talking to LDAP not AD
Oct 26, 2005 08:39 PM|LINK
Here is what I suspect - you have installed the certificate on the IIS server into the "My" store for the current user and not the machine account. Since ASPNET executes without loading a user profile, the cert must be loaded from the machine certificate store as no user store will be available. I would try futzing with the certificate store settings and see if you can't get it working.
There are a couple ways to install the certificate and I believe only the Cert Store MMC will let you put it in the machine store, while double-clicking a cert would launch a similar wizard, but no option for a machine store. Check on this and see what you find.
Weblog
The Book
LDAP Programming Help
PurdueGuy
Member
140 Points
28 Posts
Re: Unknown Error - talking to LDAP not AD
Oct 27, 2005 01:04 PM|LINK
dunnry
Star
9098 Points
1806 Posts
Re: Unknown Error - talking to LDAP not AD
Oct 27, 2005 07:51 PM|LINK
That's great news, I probably should have asked earlier, but since you said you had ldp.exe working with SSL... I just assumed it was already setup for you. You are now an LDAP troubleshooting pro.
Good luck -
Weblog
The Book
LDAP Programming Help