Clearing up MSMQ certificates from Active Directory

Some people have found a problem where Active Directory contains too many MSMQ certificates for a particular user account, usually if that's the one they use for installing all their MSMQ machines.

As you know, MSMQ uses certificates for authentication and encryption of messages.

MSMQ generates a certificate for each machine on the first login by the user. The private part of this certificate is stored locally in the secure cert store. The public part of the certificate is stored in Active Directory as an attribute of the user object. Since we need a certificate per machine, this attribute will have as many certificates as the number of machines on which the user previously logged in. The digest is a hash of an individual certificate, and lets MSMQ quickly identify the user for a given certificate.

MSMQ stores all the certificates in a single binary stream (BLOB), and it may appear as a single entity but in fact it contains many individual certificates.
The digests are stored as multi-valued attributes, and you will see multiple entries if there are multiple digests. Typically, there are as many certificates as there are digests.

On the sender, if a message is authenticated, MSMQ signs the message with the private part of the certificate and provides the identity of the sender in the message along with the certificate. On the receiving side, MSMQ looks at the incoming message, picks out the certificate, generates the digest, and looks up the user object that contains this digest. It then matches the user’s identity in the message with the one found in AD, and verifies the signature of the message before finally deciding that the message is indeed authentic or not.

There are two attributes, mSMQDigests and mSMGSignCertificates.

An array of digests of the corresponding certificates in attribute mSMQ-Sign-Certificates. They are used for mapping a digest into a certificate.

This attribute contains a number of certificates. A user can generate a certificate per computer. For each certificate we also keep a digest.

It is possible for a domain account to be used to log on to so many different machines (about 820 seems to be the magic number) that the blob gets too big and exceeds the JET limitation for non-linked multi valued attributes. Once you hit the limit you'll start seeing errors - 0x80072024 / ERROR_DS_ADMIN_LIMIT_EXCEEDED.

If you are in this situation then there is no programmable solution exposed through MSMQ.

There are, though, some workarounds with varying levels of "recommended".

Note - if you delete these certificates and digests, MSMQ will no longer find these digests/certificates/users in the AD and can no longer verify the authenticity of messages sent from these accounts. Queues that are marked as requiring authentication will not be able to accept incoming messages.

The slow and laborious but supported workarounds:

1)  in AD Users and Computers, find the User Object
    - right-click, bring up Properties
    - select the "Message Queuing User Certificates" tab
    - highlight the first certificate row
    - press Remove
    - repeat for all certificates.
An administrator can use this method to clear out certificates for many users, during the one login session.

2) when logged on as the affected user
    - Open Computer Management, Services and Applications, Message Queuing
    - Click Properties
    - In the Message Queuing Properties dialog box, click the User Certificate tab
    - under User certificates, click Remove.
    - In the Personal Certificates dialog box, click the applicable user certificate, and then click Remove. 
I recommend that, as far as possible, you use one of these methods to maintain MSMQ User Certificates.

The "quick and dirty, use at your own risk" workaround:

3) use Windows' LDFIDE command line tool. LDIFDE reads in an input file and makes changes to AD according to the instructions in the file. You need to create an LDIF input file using the correct LDIF syntax, to delete the msMQDigests and msMQDigests attributes for the affected users. LDIF files follow the standard syntax described in RFC 2849. The syntax as used for Microsoft Active Directory is exactly the same as used for any LDAP directory, such as Sun One Directory, OpenLDAP and Novell eDirectory (ie, it isn't some weird Microsoft-proprietary thing)
For example, to clear out all MSMQ Certificates for user "TestUser" in the "BigDomain.Org" domain, create a plain text file:
1) DelCerts.ldf
dn: CN=TestUser,CN=Users,DC=BigDomain,DC=org
changetype: modify
delete: mSMQSignCertificates

dn: CN=TestUser,CN=Users,DC=BigDomain,DC=org
changetype: modify
delete: mSMQDigests
Note especially the line with the hyphen "-"; this is required and must be followed by one blank line before the end of the file.
This file is then used as input to LDIFDE, like this:
C:\>ldifde -i -f DelCerts.ldf
Connecting to ""
Logging in as current user using SSPI
Importing directory from file "input.ldf"
Loading entries..
2 entry modified successfully.
The command has completed successfully
You could potentially create one file for ALL user accounts you want to clean up but it's probably safer to begin with doing one account at a time. As a batch-style command-line tool, it could potentially make many changes before you have the chance to pause it.
For your environment, you will need to change the Distinguished Name (DN) to the correct value for your users.

In AD, if an Object's attribute has no value, then there is no instance of that attribute assigned to the Object. So, a user who has never logged in to a MSMQ machine has no mSMQSignCertificates or mSMQDigests at all. The next time they log in to an MSMQ machine, then an instance of the attribute will be created on the user Object, and populated with the right value.

CAUTION: This procedure has not been formally tested and is not supported by Microsoft. You should make a full backup of all your AD data before you try this procedure and be ready to recover if necessary.

[[Thanks to Uday Hegde, Yoel Arnon]]