Reputation: 11
I am running a WCF service with a netMsmqBinding on IIS. It is configured to use 'Message' security with the 'Windows' client credential type, which uses kerberos to encrypt and sign the message. The service contract enforces ProtectionLevel.EncryptAndSign. It might be important to note that transactions are being used from client to service.
When the service is operational, the communication works flawlessly. However, to test the durability of delayed messages or when the service is unreachable, I temporarily disabled the application pool of the service in IIS. Then I send a message from the client. It leaves the outgoing queue on the client machine and it is transported to the private queue on the server. The .NET MSMQ Listener picks up the messages and tries to call the WCF service method, but that fails as expected. After about 10 minutes I reenable the application pool. In the service trace log, the following exception is logged:
System.ServiceModel.Security.MessageSecurityException:
"Message security verification failed."
System.IdentityModel.Tokens.SecurityTokenException:
"The AcceptSecurityContext failed."
System.ComponentModel.Win32Exception:
"The clocks on the client and server machines are skewed"
I also tried the same scenario by taking the Message Queuing service offline on the server. The result is the same.
My guess is that the client obtains the kerberos ticket to encrypt the message, but because the message is decrypted (at least) 10 minutes later by the WCF service, it detects a clock skew. Of course I manually verified the clocks on both the client and the server but they are the same.
Client configuration:
<bindings>
...
<netMsmqBinding>
<binding>
<security mode="Message">
<message clientCredentialType="Windows" />
</security>
</binding>
</netMsmqBinding>
</bindings>
<client>
...
<endpoint address="net.msmq://host/private/service/service.svc"
binding="netMsmqBinding"
contract="Namespace.Contract" />
</client>
Server configuration:
<bindings>
...
<netMsmqBinding>
<binding receiveErrorHandling="Reject">
<security mode="Message">
<message clientCredentialType="Windows" />
</security>
</binding>
</netMsmqBinding>
</bindings>
<serviceActivations>
...
<add relativeAddress="service.svc"
service="Namespace.Contract"
factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory"/>
</serviceActivations>
<services>
...
<service name="Namespace.Contract">
<endpoint address="net.msmq://localhost/private/service/service.svc"
binding="netMsmqBinding"
contract="Namespace.IContract" />
</service>
</services>
How is this supposed to work? What am I missing?
Edit:
This page does state the fact that "The problem with using the Kerberos protocol for queued communication is that the tickets that contain client identity that the Key Distribution Center (KDC) distributes are relatively short-lived.", but it does not really elaborate when it can be useful.
The beauty about kerberos message security is that it works nearly out of the box, someone should have considered this situation, right?
Edit 2:
I verified the time on both servers and the skew is about 0.1 second for both the client (DC01 is the domain controller):
C:\>w32tm /stripchart /computer:DC01 /samples:5
Tracking DC01 [10.1.1.2:123].
Collecting 5 samples.
The current time is 04-11-2015 16:49:17.
16:49:17 d:+00.0000000s o:-00.1020864s [ * ]
16:49:19 d:+00.0000000s o:-00.1020897s [ * ]
16:49:21 d:+00.0000000s o:-00.1020896s [ * ]
16:49:23 d:+00.0000000s o:-00.1020952s [ * ]
16:49:25 d:+00.0000000s o:-00.1021011s [ * ]
and the server:
C:\>w32tm /stripchart /computer:DC01 /samples:5
Tracking DC01 [10.1.1.2:123].
Collecting 5 samples.
The current time is 04-11-2015 16:49:17.
16:49:17 d:+00.0000000s o:-00.1171919s [ * ]
16:49:19 d:+00.0000000s o:-00.1360460s [ * ]
16:49:21 d:+00.0000000s o:-00.1237094s [ * ]
16:49:23 d:+00.0000000s o:-00.1269640s [ * ]
16:49:25 d:+00.0000000s o:-00.1302236s [ * ]
Upvotes: 1
Views: 377
Reputation: 4687
Hmmmm... sounds vaguely like something I blogged about. 45 seconds seems to be the maximum delay.
Upvotes: 0