Search code examples
c#wcfwindows-7msmqwindows-server-2012-r2

MSMQ invalid signature errors in transacted dead letter queue


Let me first state that this question is awfully similar to the following post: MSMQ messages received but not delivered Windows 2008 R2. Still, the post is unclear about what resolved the problem.

My scenario:

I have two entities A and B both acting as services and clients to each other. I also have another entity C, which acts as a client to B.

  1. A sends a message to B, registering it's URI.
  2. Upon some event, C send a message to B.
  3. Having received a message from C, B sends a message to A.

All messages are sent on transacted queues. When I'm running the above scenario solely on localhost (Windows 7 professional), everything is fine: all messages are correctly sent and received.

Now the problem arises in the following setup where A and C are on my Windows 7 pro. machine and B is on a Windows Server 2012 R2.

For step 1 and 2, everything is sound: messages are sent and received. Now in 3, when B sends it's message to A, A never gets the message. MSMQ's events log tells me that B has indeed sent the message while A's last event is: "Message came over network".

When I check in the Transacted Dead Letter queue on B, I can now see that all my messages have the "invalid signature" error. From what I gathered, it seems that this error might be linked to authentification issues so here's what I've done in A's config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <appSettings>
    <!-- use appSetting to configure MSMQ queue name -->
    <add key="queueName" value=".\private$\MainOrchestrator/MainOrchestratorService" />
    <add key="ClientSettingsProvider.ServiceUri" value="" />
  </appSettings>
  <system.serviceModel>
    <services>
      <service name="MachineCommunication.Orchestrators.MainOrchestrator.MainService" behaviorConfiguration="DefaultBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:13000/" />
          </baseAddresses>
        </host>
        <!-- Define NetMsmqEndpoint -->
        <endpoint address="net.msmq://localhost/private/MainOrchestrator/MainOrchestratorService" binding="netMsmqBinding" bindingConfiguration="TransactedBinding" contract="MachineCommunication.Contracts.OrchestratorContracts.IOrchestratorService" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <client>
      <endpoint address="net.msmq://windowsserver2012address/private/Zeiss/ZeissAdapterService" binding="netMsmqBinding" bindingConfiguration="TransactedBinding" contract="IAdapterService" name="ZeissAdapter" />
    </client>
    <behaviors>
      <serviceBehaviors>
        <behavior name="DefaultBehavior">
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <netMsmqBinding>
        <binding name="TransactedBinding" deadLetterQueue="System" useActiveDirectory ="False">
          <security mode="None">
            <message clientCredentialType="None"/>            
            <transport msmqAuthenticationMode="None" msmqProtectionLevel="None"  />
          </security>          
        </binding>
      </netMsmqBinding>
    </bindings>
  </system.serviceModel>
</configuration>

I also create the queue as follows:

    MessageQueue queue;

    if (!MessageQueue.Exists(queueName))
    {
        queue = MessageQueue.Create(queueName, true);
        queue.Authenticate = false;

        queue.SetPermissions("ANONYMOUS LOGON",
            MessageQueueAccessRights.FullControl,
            AccessControlEntryType.Allow);
    }

Yet, still having the "invalid signature" issue. If anyone can shed some light on this,

many, many thanks in advance!


Solution

  • Found the solution. Most posts talking about the "invalid signature" error in the transacted dead letter queue explain in more or less details how it usually concerns a permission problem on the receiving end (in this case, the security configuration of A's queue). In my case, the problem lied on the sending end as well. Namely:

    If you're getting "The signature is invalid" errors, that means your channel is trying to send authenticated messages.

    (source)

    For the sake of completeness, here is my current security configuration for A:

          <netMsmqBinding>
            <binding name="TransactedBinding" deadLetterQueue="System" useActiveDirectory ="False">
              <security mode="None">
                <message clientCredentialType="None"/>            
                <transport msmqAuthenticationMode="None" msmqProtectionLevel="None"  />
              </security>          
            </binding>
          </netMsmqBinding>
    

    A's service endpoint refers to this binding using:

    <endpoint address="net.msmq://localhost/private/MainOrchestrator/MainOrchestratorService" binding="netMsmqBinding" bindingConfiguration="TransactedBinding" contract="MachineCommunication.Contracts.OrchestratorContracts.IOrchestratorService" />
    

    While this is all fine and dandy, it is not sufficient.

    On B's side, I was sending the messages to a with:

                NetMsmqBinding msmqCallbackBinding = new NetMsmqBinding();
                EndpointAddress epAddr = new EndpointAddress(client.clientUri);
                OrchestratorServiceClient orchestratorServiceClient = new OrchestratorServiceClient(msmqCallbackBinding, epAddr);                    
    
                using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
                {
                    sendAction(orchestratorServiceClient);
                    scope.Complete();
                }
                orchestratorServiceClient.Close();
    

    The problem lied in the NetMsmqBinding. By default, it seems that this binding tries to use authentication and this is why it failed. Replacing:

    NetMsmqBinding msmqCallbackBinding = new NetMsmqBinding();
    

    with:

    NetMsmqBinding msmqCallbackBinding = new NetMsmqBinding(NetMsmqSecurityMode.None);
    

    Fixed the issue.