Recently, I needed to secure a C# client that talked to a Java server using XML Web Services over HTTP. The basic requirement was that the server must authenticate the client using a secure protocol. That is, simply sending a user name, or a user name plus a cleartext password would not do.
The client runs on Windows, and the server runs on Linux. Both the client and the server live in the same corporate intranet. The client belongs to a Windows domain with Kerberos authentication, and the server belongs to a MIT Kerberos realm, with mutual trust between the domain and the realm.
Web Services and Kerberos
Kerberos looked like the authentication protocol of choice, since both the client and the server understand it. We just needed to marry Kerberos and Web Services.
I found that the industry standard for passing user credentials between Web Services is the OASIS WS-Security. Passing Kerberos credentials is defined in the Kerberos token profile. Moreover, Microsoft kindly provides the Web Service Enhancements (WSE) library that implements WS-Security for Windows.
WSE ↔ UNIX Interoperability Limitation
I was able to successfully transmit Kerberos credentials from a WSE client to a WSE server when both the client and the server run on Windows. However, I ran into interesting issues when I tried to talk to a UNIX server. After a couple of days of research, I arrived at the following conclusion:
A WSE client can interoperate with a Kerberized UNIX web server, but only if the encryption type of the server key is RC4.
My client just refused to work with the UNIX server. It opened a connection to the server, and then choked with the following exception, without sending out a single byte of data: "System.ArgumentException: WSE2351: Incorrect size for key material, expected 16 bytes" (stack trace).
This seemed a little strange. What key material? Why 16 bytes? What was the supplied size? Where does this key material come from? I started to investigate this issue and found some interesting answers.
When a "Kerberized" Web Service client makes a SOAP call to a "Kerberized" web server using the OASIS WS-Security standard, there are several cryptographic actions involved. Each of these actions may use a different encryption algorithm and key size.
- The client obtains a Kerberos ticket from the TGT. This involves at least three cryptographic actions:
- The TGT encrypts the client-readable portion of the ticket-granting message.
- The TGT encrypts the server-readable portion of the ticket-granting message.
- The TGT creates a session key that both the client and the server should be able to use.
- The client signs the SOAP request before sending it to the server.
- The client encrypts the body of the SOAP request. This step is optional.
Choices Available at Each Step
TGT Encrypts Client Data
If the client is Windows XP, the only practical choice for this step is the 128-bit RC4 algorithm. According to Microsoft, Windows XP supports only RC4-128 and DES-56 for Kerberos ticket encryption. AES support has been added only in Windows Vista. When forced to choose between RC4-128 and DES-56, the TGT will choose RC4-128, since it is a stronger algorithm.
TGT Encrypts Server Data
The TGT follows the algorithm specified in the server's keytab. Practical choices for a UNIX server are DES-56, AES-128, AES-256, and RC4-128.
TGT Chooses a Session Key
The session key should be usable by both the client and the server. The TGT knows what algorithms are supported by the client, but it does not know for sure what algorithms are supported by the server, since the TGT and the server don't talk directly. The TGT deduces the set of algorithms supported by the server from the set of keytabs issued for that server. In addition, the TGT always assumes that the server supports DES-56 as the least-common denominator.
Possible situations are outlined in the table below:
||Session Key Size
|AES-128 or anything else
In other words, the session key will be 56 bit, unless the server's keytab is RC4.
Note that the TGT does not encrypt anything with the session key. Therefore, strictly speaking, the session key is not directly associated with any particular algorithm. E.g., the TGT may create a 128-bit session key with RC4 in mind, but the client may use it for AES encryption, or for a SHA1 message digest.
Client Signs SOAP Message
WSE uses the HMAC-SHA1 hash function to sign the message. HMAC-SHA1 can accept any key size up to 512 bits. Thus, it will work with both 56-bit and 128-bit session keys.
Client Encrypts SOAP Message
The algorithm used for this purpose is specified in the application configuration file. E.g., if we want to use AES-192, the corresponding configuration settings will look as follows:
Out of the box, WSE supports the following algorithms: "TripleDES", "AES128", "AES192", and "AES256". AES-128 is the default. Note that single-pass DES with 56-bit key is not supported. The support may probably be introduced by creating a class derived from
Microsoft.Web.Services3.Security.Cryptography.SymmetricKeyAlgorithm and registering it via the
microsoft.web.services3/security/criptography/keyAlgorithm element, as described in MSDN.
As far as I understand, WSE does not have a way to know whether the server supports a given encryption algorithm or not. By default, it will just encrypt the message using AES-128, hoping the server understands that.
Limitations of WSE
Limited interoperability of WSE with UNIX stems from several factors:
- Limited choice of encryption algorithms in the Kerberos subsystem of Windows. The session key will be 56 bit, unless the UNIX server has an RC4 keytab.
- WSE does not support 56-bit encryption keys.
- There is a significant inconsistency in cryptography support between the Kerberos subsystem of Windows and WSE. The Kerberos subsystem supports DES-56 and RC4, but not AES. WSE supports AES, but not DES-56 or RC4. The only key size that can possibly work for both is 128 bit; when Kerberos uses 128-bit RC4, WSE uses 128-bit AES.
- WSE tries to instantiate a full-fledged encryption object even if message body encryption is not requested. This will fail unless the session key is 128 bit and the encryption algorithm is AES-128.
As a result of all these limitations, the only combination that actually works is when the UNIX server uses an RC4 key, and WSE uses AES-128 encryption.
I can only speculate here, but it appears that interoperability with non-Windows clients was not a high priority when developing WSE, or probably not a priority at all. Maybe this decision was influenced by the lack of readily available web servers that support the WS-Security Kerberos token profile. To the best of my knowledge, a requirement for the server's keytab to be RC4 is not specified anywhere in the documentation.
Also, some relatively simple steps could greatly reduce the severity of the problem. For example, the removal of eager instantiation of the encryption object would reduce the problem significantly at very low cost. If WSE supported 56-bit DES encryption, or if the Windows Kerberos subsystem supported AES, this would improve interoperability even further. Granted, DES-56 is not considered secure anymore, but one may argue that insecure encryption is better than a cryptic exception and failed connection.
The sets of encryption algorithms supported by the Windows Kerberos subsystem and by WSE do not intersect. This fact is very peculiar by itself, and probably points to the lack of strategic vision in this area.
Fortunately, one working combination does exist, so WSE can talk to UNIX servers. Things are getting even further with Windows Vista, so at least we are moving in the right direction.
If you like this article and find it useful, visit my Programming Info and Tools page for more information.