Asked by:
FileNotFoundException on SetPassword

Question
-
User-1497164058 posted
Hi,
I'm receiving a FileNotFoundException when running the following code:
Public Sub SetPassword(ByVal path As String, ByVal sNewPassword As String)
Dim usr As DirectoryEntry = New DirectoryEntry
Try
usr.Path = path
usr.AuthenticationType = AuthenticationTypes.Secure
Dim password As Object() = New Object() {sNewPassword}
Dim ret As Object = usr.Invoke("SetPassword", password) ***Throws Exception
usr.CommitChanges()
Catch ex As Exception
Throw ex
Finally
usr.Close()
usr.Dispose()
End Try
End Sub
I've seen this problem discussed in a few places, including this site at
http://forums.asp.net/thread/486973.aspx
and
http://forums.asp.net/thread/320803.aspx
But haven't found anything that is solving the problem. I'll try not to rant about why I would get a FileNotFoundException at this point... (it doesn't make sense does it?) but has anyone encountered this problem before and can they offer any advice?
Thanks in advance,
AliMonday, July 31, 2006 11:30 AM
All replies
-
User1354132231 posted
What is the platform? What is the security context of this code?Monday, July 31, 2006 6:46 PM -
User-1497164058 posted
It's running on Windows Server 2003, I'm not too sure what you mean by the security context of this code (I'm pretty new to this active directory thing!) but it is a asp.net application that uses active directory to verify users and is limited to administrators through role based security.Tuesday, August 1, 2006 4:14 AM -
User1354132231 posted
Take a look at the sticky post here. It explains a bit about security contexts. You need to make sure that your security context has permission to set a password. Looking at your code, unless you have set an IIS App Pool to a domain service account or have delegation setup and are using a admin as client, then it will cause your issue. The error message sucks, but it is most like your security context.
Tuesday, August 1, 2006 4:44 PM -
User-1497164058 posted
Hi Dunnry, thanks for your help,
I have set up Kerberos delegation as per your instructions at
http://forums.asp.net/thread/971665.aspx
I am using <identity impersonate="true"> in web.config to impersonate a user that is a domain admin. Fairly sure I have done this correctly though I am using Server 2003 and haven't yet looked at the extra steps that you mention (constrained delegation? - though I think you imply these steps are only required to save server resources). Is there any way of confirming that I have this working (ie a function that returns the username that the code is currently executing under)?
I get the same error whether accessing the site from localhost or from my dev machine. I'm tempted to impersonate the admin directly in the code but if it's not working via the impersonation in web.config then I guess it won't work in the code either.
Friday, August 4, 2006 10:07 AM -
User-1497164058 posted
I've been looking over the code again (I've inherited someone else's broken code which is part of the confusion) and have slightly changed things, but am still receiving the filenotfoundexception. I still have impersonation turned on but perhaps this is irrelevant as I am also setting the LDAP username and password for an admin user. Here's a bit more code, perhaps this will shed some light on what I'm doing...
Public Sub ResetPassword(ByVal userLoginID As String, ByVal newPassword As String)
Dim directoryEntryOfUser As DirectoryEntry
Try
'// Get the directory entry for the user.
directoryEntryOfUser = Me.GetUserDirectoryEntry(userLoginID)
SetPassword(directoryEntryOfUser, newPassword)
Catch ex As System.Reflection.TargetInvocationException
Throw ex
Catch ex As Exception
Throw ex
Finally
If Not directoryEntryOfUser Is Nothing Then
directoryEntryOfUser.Close()
directoryEntryOfUser.Dispose()
End If
End Try
End Sub
Public Function GetUserDirectoryEntry(ByVal userLoginID As String) As System.DirectoryServices.DirectoryEntry
Dim adEntry As New DirectoryEntry
Dim adSearch As New DirectorySearcher
Dim adResult As SearchResult
Dim directoryEntry As DirectoryEntry
adEntry.Path = Me.LDAPServer
adEntry.AuthenticationType = DirectoryServices.AuthenticationTypes.Secure
adEntry.Username = Me.LDAPUserName
adEntry.Password = Me.LDAPPassword
adSearch.SearchRoot = adEntry
adSearch.Filter = "(sAMAccountName=" & userLoginID & ")"
adSearch.SearchScope = SearchScope.Subtree
LoadAttributesForSearch(adSearch)
Try
adResult = adSearch.FindOne
If Not adResult Is Nothing Then
directoryEntry = adResult.GetDirectoryEntry
End If
Catch ex As Exception
Throw ex
End Try
Return directoryEntry
End Function
Public Sub SetPassword(ByVal usr As System.DirectoryServices.DirectoryEntry, ByVal sNewPassword As String)
Try
usr.AuthenticationType = AuthenticationTypes.Secure
Dim password As Object() = New Object() {sNewPassword}
Dim ret As Object = usr.Invoke("SetPassword", password)
usr.CommitChanges()
Catch ex As Exception
Throw ex
Finally
usr.Close()
usr.Dispose()
End Try
End Sub
FYI the application is (amongst other things) supposed to allow users belonging to a paticular group the access to reset other user's passwords via a web interface (Dunnry, I see from one of your posts that you have worked on something similar in the past!)
Friday, August 4, 2006 11:56 AM -
User1354132231 posted
Well... this is kinda confusing to explain sometimes. I believe (and I would need to check the source again to confirm) that Windows 2003 will make a call to LogonUser first during SetPassword operations and attempt to change the thread context to the Me.LDAPUserName's account (assuming that the SSL LDAP password change and Kerberos password change attempts have failed). The last try using NetUserSetInfo uses the current thread context (hence the need to use LogonUser). However, when your current thread is already impersonating (the <impersonation> tag) it gets messy. I am not sure what will happen.
So, you can try removing the impersonation tag. You don't need it if you are using explicit credentials and it will only complicate things. That, or you can run this code in an app pool in IIS that runs under a domain account that has permission to reset passwords. Then, do not specify explicit credentials (use Nothing) and the DirectoryEntry will run as that account and SetPassword will succeed. I think this would be the easiest.
Also, you can check our code samples in Ch. 10 and see how we can reset passwords using native LDAP (LdapConnection class). If you are using .NET 2.0 and Windows 2003 AD this is pretty good too.Monday, August 14, 2006 1:36 PM