tags:

views:

240

answers:

1

Indexing Service is set up on our file server to index a couple dozen folders (called "scopes" in the Indexing Service terminology), not all of which are accessible to all users. I have an ASP search script running under IIS with windows integrated authentication, which means that when a user logged onto the network uses the search page they will only see the results which they have permission to access. This is a good thing.

But how can I show the user a list of the scopes which they have access to? (In other words, a list of the folders which will be searched). The scopes can be enumerated programmatically using the CatAdm object, but this requires admin permissions which my ASP script doesn't have, and anyway it doesn't tell me whether the current user has access or not.

I've tried the clever trick of enabling the indexing of directories (the FilterDirectories registry setting) and then doing a query for only directories ("@Attrib ^a 0x10", to check for the directory flag in the file attributes), but of course this gives me subdirectories as well...I could run through the results and take just the top directories but that seems to be putting a lot of load on the server just to generate this simple list. Moreover, I've configured aliases so that Indexing Service returns network paths instead of local paths, but I seem to have encountered an Indexing Service bug because the alias is applied to everything except the top-level directories themselves.

Does anyone have any better suggestions?

A: 

So far this question has only had 7 views, and earnt me the "Tumbleweed" badge, but nevertheless I thought I'd follow up with an explanation of my final solution.

Using the CatAdm object really was the only option in the end, because that's the only way to work around the bug in Indexining Service related to aliases (mentioned in my original post).

One method (which is relatively easy in ASP.NET, and possible in ASP Classic with the use of a custom COM component of equivalent) would be to use impersonation: use a privileged account to read the list of scopes from the CatAdm object, then use the account of the authorized HTTP request to do a query on those scopes. The results will contain only the directories which that account has access to.

The problem is that only administrator accounts have permission to use the CatAdm object, and using an administrator account to serve HTTP requests is not good practice, from a security point of view.

So, although it adds to the administration burden, I decided to write a separate HTA script that must be run (on the server machine itself, not via HTTP) any time that directories are added or removed from the catalog. The script reads the list of scopes from the CatAdm object and writes it to a configuration file:

    Function makeConfig(catalogName)
        Set machine = CreateObject("Shell.LocalMachine")
        Set adm = CreateObject("Microsoft.ISAdm")
        Set cat = adm.GetCatalogByName(catalogName)

        Dim config
        config = "<%" & vbCrLf
        config = config & "' Automatically generated by " & document.location.pathname & " at " & Now & vbCrLf
        config = config & "' This file is indended for inclusion by the intranet search script." & vbCrLf
        config = config & "catalogMachine = """ & machine.MachineName & """"  & vbCrLf
        config = config & "catalogName = """ & catalogName & """"  & vbCrLf

        scopeFound = cat.FindFirstScope()
        While scopeFound
            Set scope = cat.GetScope()
            If Not scope.ExcludeScope Then
                ' Must be lowercase because query results are returned in lowercase
                dir = lcase(scope.Path)
                If scope.Alias <> "" Then
                    alias = scope.Alias
                Else
                    alias = scope.Path
                End If

                config = config & "dirs(""" & dir & """) = """ & alias & """" & vbCrLf
            End If
            scopeFound = cat.FindNextScope()
        Wend

        config = config & "%>" & vbCrLf
        makeConfig = config
    End Function

Then the search script itself just reads the configuration file and uses this to find the list of accessible directories. To work around the Indexing Service bug, it's necessary to map from the physical directory to the alias:

Set dirs = CreateObject("Scripting.Dictionary")
%><!--#include file="search_config.asp"--><%
catalogURI = "query://" & catalogMachine & "/" & catalogName

queryString = ""
For Each dir In dirs
  If queryString <> "" Then
    queryString = queryString & " or "
  End If
  queryString = queryString & "@Path = """ & dir & """"
Next

' But the @Path attribute is not indexed, and running queryString
' as is will return no results. Solution: limit search to only
' directories, i.e. items with the 0x10 flag set in @Attrib.
queryString = "@Attrib ^a 0x10 and (" & queryString & ")"

' No point asking for sorted query results, because we need
' to map the results from real paths to network aliases and
' sort again ourselves.
Set query = Server.CreateObject("ixsso.Query")
query.Catalog = catalogURI
query.Query = queryString
query.Columns = "path"
query.MaxRecords = dirs.Count
Set rs = query.CreateRecordSet("sequential")

i = 0
Do While Not rs.EOF
  ReDim Preserve accessibleAliases(i)
  accessibleAliases(i) = dirs(rs("path").Value)
  i = i + 1
  rs.MoveNext
Loop
rs.Close

BubbleSort accessibleAliases
Todd Owen