First, you can leverage the out-of-the-box Site Directory template, coupled with a few settings in Central Admin to force users to select one or two categories, that can be a good solution, specially if you don't have too many sites and you can afford to have someone overseeing the directory. For a very large number of sites, that might not work. Also, there is chance someone will miscategorize sites and you'll likely need someone to approve all site listings.

Another way to do it is to leverage the out-of-the-box site membership feature you get with the profile services (or "my sites"). MOSS does a pretty good job of keeping track (via the Profile database and a timer job) of all the sites each user is a member of. There are a few issues there as well and this will not work if you have a multi-farm deployment since there is no synching of profile information between farms (unless you write code for that yourself). There's also the issue of the timer job that updates the profile database being unable to figure out you're a member of the site if you're not explicitly in the members list (as opposed to being in an active directory group that is in the member list).

A third way of finding this kind of information is using Search. This is likely the best option for very large implementations that include multiple farms and many thousands of sites. In a situation like that you will likely need to implement search properly anyway and you can just leverage that. You could even create a custom search results page to format the output in a more adequate way and you will only see a site if you have access to it. To put this in place, however, you need to provide a way to search only for sites. There's no property or search modifier to do that for you on the search box itself, but you can implement this using a special search scope.

Creating a scope that includes just sites is not really hard. All you need to do is go to the Search Settings page in the Shared Services Provider administration page and create a new scope with a corresponding rule. You can do something similar to the out-of-the-box scope for "People", with a rule based on the Content Class of the item. The Content Class for people, for instance, is "urn:content-class:SPSPeople".

The hard part is to find out what string to use in the content class for sites. The information is actually out there, but it's somewhat hidden in an MSDN article at http://msdn2.microsoft.com/en-gb/library/ms975759.aspx. The correct string for sites is “STS_Web” (strangely enough, it’s not “urn:content-class-STS_Web”, just “STS_Web”). With that info at hand and using the "People" scope as an example, you should be able to create a scope that includes only sites, nothing else.

For the record, here are all the different strings you can use with the ContentClass:

  • Search Query: urn:content-class:SPSSearchQuery
  • News Listing: urn:content-class:SPSListing:News
  • People: urn:content-class:SPSPeople
  • Category: urn:content-classes:SPSCategory
  • Listing: urn:content-classes:SPSListing
  • Person Listing: urn:content-classes:SPSPersonListing
  • Text Listing: urn:content-classes:SPSTextListing
  • Site Listing: urn:content-classes:SPSSiteListing
  • Site Registry Listing: urn:content-classes:SPSSiteRegistry
  • Site: STS_Web
  • List: STS_List
  • List Item: STS_ListItem
  • Events: STS_List_Events
  • Tasks: STS_List_Tasks
  • Announcements: STS_List_Announcements
  • Discussions: STS_List_DiscussionBoard
  • Contacts: STS_List_Contacts
  • Links: STS_List_Links
  • Document Library: STS_List_DocumentLibrary
  • Document Library Items: STS_ListItem_DocumentLibrary
  • Picture Library: STS_List_PictureLibrary
  • Picture Library Items: STS_ListItem_PictureLibrary