Remoting, events and custom encryption channel sinks



I have written an API which defines a standardized interface for various
types of hardware devices that can be used by .NET applications. The
interface supports both local and remote device services in order to access
e.g. a network printer as easily as a local printer.
On command completion, the remote device services fire events asynchronously
to the client application transporting customized result objects over the
wire.

The architecture is as usual:
- a server app hosts the remotable device service(s)
- the client app connects to a remote device service which is hosted by the
server app as server activated singleton instance
- the client app accesses functions on the remote device services by
transparent proxies
- the completion events of a device service send the serialized result
objects back to the client


Tcp channels are defined on both sides (client and server) using standard
tcp channel sinks. The asynchronous callbacks is done by multicast
delegates. Since .NET framework v1.1 needs full trust when deserializing
server side runtime types, the typeFilterLevel="Full" attribute is used.

Here how the server config looks like:

<configuration>
</appSettings>
<system.runtime.remoting>
<customErrors mode="on"/>
<application>
<service>
<activated type="... />
</service>

<channels>
<channel ref="tcp" port="8002">
<serverProviders>
<formatter ref = "binary" typeFilterLevel= "Full" />
</serverProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>


The client app instantiates a tcp channel with a given port number because
it wants to receive the async events from the server on a definite channel
port number. (During receiving of the incoming events the client app behaves
temporarely as a server and the remote device service behaves as the
client.)

So the client config file looks like this (also nothing unusual here):

<configuration>
</appSettings>
<system.runtime.remoting>
<application>
<client url="..." activated type="..." />

<channels>
<channel ref="tcp" port="8001">
<clientProviders>
<formatter
</clientProviders>

<serverProviders>
<formatter ref="binary" typeFilterLevel="Full" />
</serverProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>

As described above, because of typeFilterLevel="Full" both sides can manage
the runtime deserialization of custom types without any problems.


NOW THE PROBLEM:
I want to secure the remoting traffic so that the requests and the result
data cannot be spyed out by anyone. Using the wunderful sample encryption
channel sinks written by Stephen Toub at:
http://msdn,microsoft.com/msdnmag/issues/03/06/NETRemoting/default.aspx,
accessing the server from the client works fine. Not so does the other
direction: Getting back events from the device service fails when trying to
let the network communication happen through the custom channel sinks.

For firing events to all listeners my device services use the usual
mechanism:
....
Delegate[] clients = null;
MyCustomEventListenerDelegate client = null;
MySerializableEvent ev = new MySerializableEvent("someData");

clients = _mycustomListener.GetInvocationList();

for (int i = clients.Length; i > 0; i--)
{
client = (MyCustomEventListenerDelegate) clients[i - 1];

// This call works well when calling remote client code WITHOUT custom
encryption channel sinks!!
client(this, ev);
}
....

This works perfectly without using encryption sinks, otherwise the same code
fails.
I use the following extended configuration settings when including
encryption:

SERVER CONFIGURATION:

<configuration>
<customErrors mode="on"/>
<application>
<service>
<wellknown
mode ="Singleton"
type ="MyNamespace.MyDeviceServiceType, MyDeviceServiceAssembly"
objectUri ="MyDeviceServiceURI"
/>
</service>

<channels>
<channel ref="tcp" port="8002">
<clientProviders>
<formatter ref="binary" />
<provider
type="MyNamespace.SecureClientChannelSinkProvider,
MySecureClientChannelSinkProviderAssembly"
algorithm = "DES"
oaep = "false"
maxRetries = "1"
/>
</clientProviders>

<serverProviders>
<provider
type="MyNamespace.SecureServerChannelSinkProvider,
MySecureServerChannelSinkProviderAssembly"
algorithm="DES"
oaep="false"
requireSecurity="true"
securityExemptionList="127.0.0.1; 207.46.230.220"
connectionAgeLimit="120"
sweepFrequency="60"
/>
<formatter ref="binary" />
</serverProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>



CLIENT CONFIGURATION:

<configuration>
<system.runtime.remoting>
<customErrors mode="on"/>
<application>
<channels>
<channel ref="tcp" port="8001">
<clientProviders>
<formatter ref="binary" />
<provider
type="MyNamespace.SecureClientChannelSinkProvider,
MySecureClientChannelSinkProviderAssembly"
algorithm = "DES"
oaep = "false"
maxRetries = "1"
/>
</clientProviders>
<serverProviders>
<provider
type = "MyNamespace.SecureServerChannelSinkProvider,
MySecureServerChannelSinkProviderAssembly"
algorithm = "DES"
oaep = "false"
requireSecurity = "true"
securityExemptionList = "127.0.0.1; 207.46.230.220"
connectionAgeLimit = "120"
sweepFrequency = "60"
/>
<formatter ref="binary" typeFilterLevel="Full" />
</serverProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>


The important thing here is that both sink types (SecureClientChannelSink
and SecureServerChannelSink) have to be included on both sides because every
side acts as client and as server. Furthermore, because every side has
defined only one bidirectional tcp channel this code should work, but
unfortunately doesn't. I've tried to debug the sending process of the
delegate call, but when the server side delegate wants to call the remote
client code, it doesn't call any "SecureClientChannelSink" code at all.
Somewhere I've read that the .NET framework automatically uses a channel
when the server calls back client code through events or delegates. This
could mean that the .NET remoting infrastructure chooses another predefined
channel from machine.config when executing the call back mechanism without
using my encryption channel sinks... So the question is how to force the
delegate to use my custom channel sinks?

Many thanks in advance,

Egmont


.



Relevant Pages

  • RE: Problems with security requirements in Windows WorkGroups.
    ... "A remote side security requirement was not fulfilled during authentication. ... small chat application between a client and a server ... When I try to use the TCP channel I get the error (with NO inner exception ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Outlook -> remote exchange -> always wants a password
    ... I have my server set to use Integrated Windows authentication over SSL. ... almost certainly "break" your existing users if the client setup does not ... Close out of these configuration dialogs, ...
    (microsoft.public.windows.server.sbs)
  • Re: .Net Remoting TCP or HTTP?
    ... John's given a good description of why you would pick either the TCP or HTTP ... The reason is that, when the server needs to notify the client of the event, ... In the TCP case, this means using a bi-directional channel, so that requests ...
    (microsoft.public.dotnet.framework)
  • Re: .Net Remoting TCP or HTTP?
    ... John's given a good description of why you would pick either the TCP or HTTP ... The reason is that, when the server needs to notify the client of the event, ... In the TCP case, this means using a bi-directional channel, so that requests ...
    (microsoft.public.dotnet.framework.remoting)
  • Re: 70-294 next week
    ... to another DNS ... server for at least ... client, which then ... configuration on the client. ...
    (microsoft.public.cert.exam.mcse)