locked
AD-queries using System.DirectoryServices on ASP.Net Win2003 Svr. RRS feed

  • Question

  • Hi,

    I am querying our AD through an ASP.Net-application managed by IIS on Windows 2003.

    My code is this:

    1 string sUserName = <my username>;  
    2 DirectorySearcher search = new DirectorySearcher();  
    3 search.Filter = String.Format("(SAMAccountName={0})", sUserName);  
    4 search.PropertiesToLoad.Add("memberOf");  
    5 SearchResult result = search.FindOne(); 

    However, when line 5 is executed, an exception is thrown:

    System.Runtime.InteropServices.COMException: An operations error occurred.

    The exception in my Eventlog on the server is:

    Application information:
        Application domain: /LM/W3SVC/1/Root/BLSTHavkvalitet-1-128764104370549695
        Trust level: Full
        Application Virtual Path: /BLSTHavkvalitet
        Application Path: E:\BLST\Havkvalitet\
        Machine name: S-SQL001U
     
    Process information:
        Process ID: 85168
        Process name: w3wp.exe
        Account name: NT AUTHORITY\NETWORK SERVICE
     
    Exception information:
        Exception type: COMException
        Exception message: An operations error occurred.
     
     
    Request information:
        Request URL: http://s-sql001u/blsthavkvalitet/default.aspx
        Request path: /blsthavkvalitet/default.aspx
        User host address: 172.24.4.138
        User: RES\xjest
        Is authenticated: True
        Authentication Type: Negotiate
        Thread account name: NT AUTHORITY\NETWORK SERVICE
     
    Thread information:
        Thread ID: 1
        Thread account name: NT AUTHORITY\NETWORK SERVICE
        Is impersonating: False
        Stack trace:    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.FindOne()

    I had the same issue locally on my Win XP desktop, where it was solved by adding an <Identity impersonation="true"/>-element to web.config. Otherwise it would be the local "ASPNET machine account" querying our AD, and it lacks the permission to do so.

    Now, if I look at the exception from my EventLog, it seems odd to me that "NT AUTHORITY\NETWORK SERVICE" is associated with the process and thread. But if I look in IIS, my application runs in an app pool managed by "NETWORK SERVICE".

    So - the big question is: how do I solve this? If the app pool association to NETWORK SERVICE is the culprit, how do I best change it? Should I use a specified domain account to control the app pool?

    Thanks - and I hope this all makes a bit of sense.

    :o)
    www.idippedut.dk
    Wednesday, January 14, 2009 1:24 PM

Answers

  • There are different ways to handle this. You could perform web impersonation, as you mentioned, but that would run the entire request as the specified user, which could give you unintended consequences (as well as access to things the web code shouldn't have priveledges to). The same would be true if you changed app pool credentials. Then, all requests for any web app in that pool would run as that user.

    A different way of handling it is to specify credentials just for the AD call. The searcher runs with the credentials supplied by the "root" DirectoryEntry (the search queries everything under that node, depending on the query scope). If you don't supply a DirectoryEntry object (by either using a path string or no arguments in the constructor, for example), the searcher creates a root reference for you. This default root reference is either anonymous or propogates the thread's identity (depending on how you set things up). So the trick is to create the DirectoryEntry reference and supply a User Name/Password set of credentials when creating that DirectoryEntry.

    The only thing you must be careful of here is the problem of securely storing the credentials. One quick way of doing it is to store it in the web.config file (just like db connection strings) and use the config section protection mechanism to encrypt that section of the config file. You can hardcode the credentials to test out the code, but I wouldn't push code with passwords embedded in it to a production system :-)
    -Rob Teixeira
    • Marked as answer by Zhi-Xin Ye Monday, January 19, 2009 9:31 AM
    Wednesday, January 14, 2009 9:52 PM