Friday, March 27, 2015

Exchange 2013 and RMS on Windows 2012 R2 getting UnsupportedCryptographicSetException error

Well, I never really considered myself an RMS guy, but I guess this month has changed things some.  After my last article, I was running through a test plan, when I came to find that the Test-IRMConfiguration was failing on one server (the entire time of this project, I had only really focused on the Exchange servers in the same datacenter.  The exact failure seen below is identical to the error you would expect to see on an older OS, or an unpatched Exchange 2010 server.  It also was documented here.  We did use Cryptographic Mode 2, but since we are on Windows 2012 R2 and Exchange 2013, the error was not expected here.  Also, the permissions that the error tells you to set are already in place.  Keep in mind that I already had two Exchange 2013 servers working correctly, just this other one didn't.


Acquiring Rights Account Certificate (RAC) and Client Licensor Certificate (CLC) ...
    - FAIL: Failed to acquire a Rights Account Certificate (RAC) and/or a Client Licensor Certificate (CLC).
This failure may cause features such as Transport Decryption, Transport Protection Rules, Journal Report Decryption, IRM in Outlook Web App, IRM in Exchange ActiveSync, and IRM Search to not work. Make sure that the Exchange Servers Group is granted "Read" and "Read & Execute" rights on the ServerCertification.asmx and Publish.asmx pipelines on your AD RMS server. For details, see "Set Permissions on the AD RMS Certification Pipeline" at  http://go.microsoft.com/fwlink/?LinkId=186951.

----------------------------------------
Microsoft.Exchange.Security.RightsManagement.RightsManagementException: Failed to acquire server box RAC from

---> System.Web.Services.
Protocols.SoapException: System.Web.Services.Protocols.SoapException: Exception of type 'System.Web.Services.
Protocols.SoapException' was thrown. ---> Microsoft.DigitalRightsManagement.Cryptography.UnsupportedCryptographicSetException: Exception of type 'Microsoft.DigitalRightsManagement.Cryptography.UnsupportedCryptographicSetException' was thrown.
   --- End of inner exception stack trace ---
   at Microsoft.DigitalRightsManagement.Certification.BaseCertificationWebService.Certify(CAType caType, CertifyParams requestParameters)
   at Microsoft.DigitalRightsManagement.Certification.ServerCertificationWebService.Certify(CertifyParams requestParams)
   at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
   at System.Web.Services.Protocols.SoapHttpClientProtocol.EndInvoke(IAsyncResult asyncResult)
   at Microsoft.Exchange.Net.WsAsyncProxyWrapper.EndInvoke(IAsyncResult result)
   at Microsoft.Exchange.Security.RightsManagement.SOAP.ServerCertification.ServerCertificationWS.EndCertify(IAsyncResult asyncResult)
   at Microsoft.Exchange.Security.RightsManagement.ServerCertificationWSManager.EndAcquireRac(IAsyncResult asyncResult)

Exchange server was 2013 and patched on a Windows 2012 R2 server



Resolution:
This issue was because the environment had an RMS server in the past that had been decommissioned.  The Exchange server that was failing to use RMS was doing so because it already had machine certificates.  The fix was to backup these cache files, and reboot the Exchange server, then the command passed and it rebuilt the cached files using the new RMS instance.  Of course, the old instance was Type 1 Cryptographic mode, hence the mismatch error.




  1. On the impacted Exchange server, go to c:\ProgramData\Microsoft\DRM\Server (Server is a hidden folder, so you need to specify it)
  2. You will see SID's like below in there.  I just moved both into a new subfolder for now.  You can see an example of the content of these folders below as well.
  3. Reboot the Exchange server
  4. Re-test the Test-IRMConfiguration


Tuesday, March 24, 2015

ADRMS, SQL mirroring, and named instances

First and foremost, I need to thank my PSS colleagues for their assistance on this case. It was open for quite some time, but Samesh Panicker and Kaustubh Dwivedi were critical to my success in this configuration. Here's the scenario:
  • Two ADRMS servers running on Windows 2012 R2
  • Two SQL servers, SQL 2012 on Windows 2012 R2 with a SQL express witness
    • Since we colocated with another SQL instance, I had to use named instances (more on this soon)
  • An F5 Hardware load balancer (HLB) publishing an internal and external VIP using split brain DNS to resolve rms.domain.com to the correct VIP


The article that I followed was from the Technet Wiki here:
http://social.technet.microsoft.com/wiki/contents/articles/14977.test-lab-guide-configuring-ad-rms-with-sql-mirroring-in-windows-server-2012.aspx

This is required reading for the rest of the post, as I am only going to highlight key differences from that guide.


Step 3d 
There are a few things on using setspn. First, most people are not familiar with it. Even those who are, use it infrequently. I am OK running setspn.exe, but you need to know how to check and then delete any mistakes. I tend to use ADSIedit here. You are adding Service Principal Names (SPNs) to the SQL service account. So in ADSIiedt, you drill down to that account (not the SQL server computer objects) to set, edit, or delete SPNs.

Keep in mind, his example shows:
Setspn –A MSSQLsvc/[sql1 fqdn] [domain]\SQLSVC
Setspn –A MSSQLsvc/[sql2 fqdn] [domain]\SQLSVC
Setspn –A MSSQLsvc/[sql1] [domain]\SQLSVC
Setspn –A MSSQLsvc/[sql2] [domain]\SQLSVC

A few changes and clarifications here.
  • MSSQLSvc is a static field, that isn't your account name (his example using SQLSVC makes this confusing IMO)
  • If you are using a named instance for SQL, you need to specify it.
This is done as shown below.



So to correct the above paste from the wiki (needed only if specifying an instance name)


Setspn –A MSSQLsvc/[sql1 fqdn:INSTANCE] [domain]\ADRMSSQLSVC
Setspn –A MSSQLsvc/[sql2 fqdn:INSTANCE] [domain]\ADRMSSQLSVC
Setspn –A MSSQLsvc/[sql1:INSTANCE] [domain]\ADRMSSQLSVC
Setspn –A MSSQLsvc/[sql2:INSTANCE] [domain]\ADRMSSQLSVC

If you are running more than a single instance of SQL on a server or servers in my case, you cannot use the same mirroring port if another instance is using it. TCP/5022 is the default port - if another SQL instance is already using mirroring on that port, you will need to pick a new port. Be sure to do a netstat -ano and ensure its not in use first, then follow this guide to change your mirror port: http://www.macaalay.com/2012/10/10/altering-mirroring-endpoints-ports-on-sql-server/  

Step 10
First off, PSS recommends you not really edit SQL using transact. It's totally acceptable if you are strong in SQL, but they really prefer you use RMSConfigEditor.exe from the RMS toolkit . And yes that is from 2006 and doesn't say anything about 2012 or 2012 R2, but it still works.

Second, and I see Kaustubh has already updated the wiki, but the Logging Database SHOULD NOT have the "data source=" like the CertificationUserKeyStorageConnectionString and the DirectoryServicesCacheDatabase . When we specified it with that connection string, logging/reporting functions did not work in the RMS Admin console, and RMS was broken if the database was hosted on the SQL02 server.

Another thing to note, as it’s a simple mistake to make, but your Database= string, the [cluster] will always be host_domain_com, and NOT host.domain.com. If you are working on issues with RMS late at night, or after many hours at it, this can be pretty painful to mistake, so do check it!

Monday, March 09, 2015

Quickly implementing Cisco CDA registry permissions required

Recently was working with a colleague on our Cisco team to implement Cisco's Context Directory Agent (CDA) product in order to provide user to IP address mapping so that Cisco Cloud Web Security could correctly identify users based on their IP.

The tasks to configure this on the Microsoft side are fairly straightforward, but there are registry setting permissions that cannot be implemented via GPO because GPO's are run by SYSTEM, which doesn't have access to these particular keys.

So first off, the Cisco article on implementation:
http://www.cisco.com/c/en/us/td/docs/security/ibf/cda_10/Install_Config_guide/cda10/cda_install.html

Here's the registry specific settings, which need to be performed on ANY DOMAIN CONTROLLER in a site where users will be using CDA!

From that article:
For Windows 2008 R2,Windows 2012, and Windows 2012 R2, the Domain Admin group does not have full control on certain registry keys in the Windows operating system by default. In order to get the CDA to work, Active Directory admin must give the Active Directory user Full Control permissions on the following registry keys:
  • HKEY_CLASSES_ROOT\CLSID\{76A64158-CB41-11D1-8B02-00600806D9B6}
  • HKLM\Software\Classes\Wow6432Node\CLSID\{76A64158-CB41-11D1-8B02-00600806D9B6}
Now, when they say "the Active Directory User" they mean the service account that CDA is using.  So you need to add a reg permission to two keys on every DC.

Now, this customer had less than 10 domain controllers, so I did this in a more manual way, but hopefully someone else can find this and have the problem of 200+ domain controllers and script this properly by focusing on the Domain Controllers OU and implementing (or better yet, finding a way to address via GPO somehow)

I chose to use SetACL.exe, which is NOT a Microsoft tool, but is a quite effective and great tool.  Using this, and either using the \\computername method, or running locally on each DC, you can implement these changes using the below command.  Note - you need to take ownership with your account in order to set permissions.  I highlighted the sections that you will need to configure specific to your environment in bold.

SetACL.exe -on "hklm\Software\Classes\Wow6432Node\CLSID\{76A64158-CB41-11D1-8B02-00600806D9B6}" -ot reg -actn setowner -ownr "n:AdminAccount"
SetACL.exe -on "hklm\Software\Classes\Wow6432Node\CLSID\{76A64158-CB41-11D1-8B02-00600806D9B6}" -ot reg -actn ace -ace "n:domain.com\CDAServiceAccount;p:full"
SetACL.exe -on "HKEY_CLASSES_ROOT\CLSID\{76A64158-CB41-11D1-8B02-00600806D9B6}" -ot reg -actn setowner -ownr "n:
AdminAccount"
SetACL.exe -on "HKEY_CLASSES_ROOT\CLSID\{76A64158-CB41-11D1-8B02-00600806D9B6}" -ot reg -actn ace -ace "n:domain.com\
CDAServiceAccount;p:full"

If anyone runs into this situation and ultimately ends up automating the solution feel free to post in the comment section below for others.  Should be easy enough to get domain controllers into an array to for-each through.