Getting a Referral From Exchange 2007

One of my customers reported that using the MAPI download, they were unable to get a referral from Exchange 2007, even after following the instructions in Jason Johnston's article. The same code worked if they were targeting an Exchange 2003 machine, and Outlook's MAPI had no problems getting a referral from Exchange 2007.

A little bit about how we connect to the DC Exchange's MAPI (this description does NOT apply to Outlook's MAPI, which has different logic, and leaves out a few details not relevant to the discussion, such as how we react when offline):

  1. We read in various settings from the pbGlobalProfileSectionGuid profile section, including PR_PROFILE_HOME_SERVER, PR_PROFILE_CONFIG_FLAGS, PR_PROFILE_CONNECT_FLAGS, and PR_PROFILE_UI_STATE.
  2. Now we figure out where to send our address book calls. First, we look for the "DS Server" key - if we find it, that's the server we bind to for address book lookups - if we fail to bind here, then we fail overall (hence the cautions against ever setting this key)
  3. Next, we read in various settings from the MUIDEMSAB profile section (see Jason's article), including PR_PROFILE_HOME_SERVER, PR_PROFILE_AUTH_PACKAGE, PR_PROFILE_ABP_ALLOW_RECONNECT and PR_PROFILE_SERVER_VERSION
  4. If PR_PROFILE_HOME_SERVER was set on the MUIDEMSAB section, we attempt to bind to the server specified. If we succeed, we're done. If we fail, we continue to the next step.
  5. We ask the Exchange server for a referral. If that succeeds, and we can bind to the referred server, we write the referred server name to PR_PROFILE_HOME_SERVER in the MUIDEMSAB section, and we're done.
  6. If the referral request fails, we try to bind directly to the Exchange server specified in PR_HOME_SERVER on the pbGlobalProfileSectionGuid section. The Exchange server will proxy any of our address book requests on to a GC.
  7. If we binding directly to the Exchange server fails, we try to ask for a referral one more time. If that fails, we fail overall.

We're focused on the referral step. The referral request is a Remote Procedure Call (RPC), so we have to set up for the RPC, select one of the available RPC bindings, set our authentication mechanism, and finally make the call. Given default settings, this means we'll be using the default authentication mechanism for RPC, RPC_C_AUTHN_WINNT. This is where we run in to trouble.

During the development of Exchange 2007, a few of the RPC interfaces were moved around. This created the need to consolidate how authentication was handled among the various interfaces. RPC_C_AUTHN_WINNT was cut as an authentication mechanism for the RPC interface which handles referrals, leaving RPC_C_AUTHN_GSS_NEGOTIATE as the preferred authentication mechanism. For the most part, this change had little effect. Outlook did not use RPC_C_AUTHN_WINNT as an authentication mechanism for the referral RPC, and since a failure to get a referral defaults to binding to the Exchange server, most clients didn't see a noticeable impact.

Given all the settings we read in, including the tantalizingly named PR_PROFILE_AUTH_PACKAGE, I wondered if there was any way we could work around this and get Exchange's MAPI to ask for a referral. Investigation of our source confirmed that PR_PROFILE_AUTH_PACKAGE did take an RPC authentication mechanism constant as it's value, so we could set it to RPC_C_AUTHN_GSS_NEGOTIATE (this article discusses this as well).Testing showed that didn't work though. The address book code was convinced it didn't need special authentication, so it wouldn't set the authentication mechanism I had specified.

More digging led to PR_PROFILE_CONNECT_FLAGS. If the CONNECT_NO_RPC_ENCRYPTION flag was set in this property, we'd assume we didn't need special authentication. So I tried removing this flag. Of course, this didn't work either. In fact, although I could remove the CONNECT_NO_RPC_ENCRYPTION flag, every time I tried to connect, it got set back again!

Even more digging. Basically, the if EDK_PROFILEUISTATE_ENCRYPTNETWORK flag wasn't set in PR_PROFILE_UI_STATE, we'd add CONNECT_NO_RPC_ENCRYPTION back to PR_PROFILE_CONNECT_FLAGS. Guess what? Setting the EDK_PROFILEUISTATE_ENCRYPTNETWORK flag didn't work either! But I was getting much closer: the error changed.

Previously, the RPC call had been failing with RPC_S_SERVER_UNAVAILABLE. This was because the authentication mechanism was valid, but the RPC interface we were trying to call to hadn't registered for that authentication mechanism. After I made all my settings, when we called RpcBindingSetAuthInfo we got RPC_S_UNKNOWN_AUTHN_SERVICE back. I had been testing everything locally on my Exchange 2007 server, so all RPC calls to the server used local RPC. Since RPC_C_AUTHN_GSS_NEGOTIATE isn't a valid authentication mechanism for local RPC, the RPC layer wouldn't let us use it. This was excellent news. It meant I had succeeded in forcing Exchange's MAPI to attempt a different authentication method!

I knew the customer always ran their MAPI code remotely anyway, so I tested my settings from a MAPI client on a different machine. Whereas without my settings we were always binding directly to the Exchange server for address book lookups, with the new settings, we asked for and got a referral, then bound to the GC!

Here's a summary of the settings you'll want to make on your MAPI profiles if you want to get GC referral and reconnect working against Exchange 2007. These settings will also work when connecting to Exchange 2003, though only the properties from Jason's article are strictly necessary:

In the MUIDEMSAB profile section (dca740c8c042101ab4b908002b2fe182):

  • Set PR_PROFILE_ABP_ALLOW_RECONNECT (0x66390003) to 1 per Jason's article

In the global profile section (13DBB0C8AA05101A9BB000AA002FC45A):

  • Set PR_PROFILE_UI_STATE (0x66060003) to EDK_PROFILEUISTATE_ENCRYPTNETWORK (0x4000)
  • Remove the CONNECT_NO_RPC_ENCRYPTION (0x2) flag from PR_PROFILE_CONNECT_FLAGS (0x66040003)
  • Set PR_PROFILE_AUTH_PACKAGE (0x66190003) to RPC_C_AUTHN_GSS_NEGOTIATE (9)
  • Set PR_PROFILE_SERVER_VERSION (0x661B0003) to 3000 or higher per Jason's article

I tested all of these settings using MFCMAPI, following the outline of the steps I gave here.

BTW - Global Catalog servers still lie on shutdown, so you'll also want to enable the EMSAB_UserAuth_Credentials key if that's a concern. That code was incorporated into the MAPI Download a long time ago.