locked
FileNotFoundException on SetPassword RRS feed

  • 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,
    Ali
    Monday, 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