Prove it

I spent a little time at the weekend experimenting with secuing a remoting connection. A secure mode was added to remoting in .NET version 2, but I have not used it in the past. Like most exploratory scenarios, it was great to be able to use F# to explore the solution dynamically.
 
The first thing to do was to build an interface dll, which I wrote in C# and compiled into an assembly dll WorkerInterface.dll.

namespace WorkerInterface
{
 
public interface IWorker
 
{
   
void DoWork();
  }
}

It was then easy to write a server in the interactive F# console.

Import the interface definition

#I "C:UsersCliveDesktopWork";;
#r "WorkerInterface.dll";;

Define an implementation object. We’ll register this as a Singleton so we need the override on InitializeLifetimeService to prevent it timing out if no calls are made to it within the lease timeout interval. We print out the identity as this will be passed when we start using a secure connection later.

type MyImpl() =
  class
    inherit System.MarshalByRefObject() as base
    do printfn "New instance made"
    interface WorkerInterface.IWorker with
      member self.DoWork () =
        printfn "Method called %s " System.Threading.Thread.CurrentPrincipal.Identity.Name
    end
    override this.InitializeLifetimeService() = null
  end;;

We load a small amount of configuration from a file Config1.txt containing

<configuration>
  <system.runtime.remoting>
    <application>
      <channels>
        <channel ref="tcp" port="8080" />
      </channels>
    </application>
  </system.runtime.remoting>
</configuration>

System.Runtime.Remoting.RemotingConfiguration.Configure("C:UsersCliveDesktopWorkConfig1.txt", false);;

We can then make an instance of our implementation object which we can register with the remoting system.

let target = new MyImpl();;
System.Runtime.Remoting.RemotingServices.Marshal (target, "target.rem");;

In another F# interactive console we can exercise this server.

#I "C:UsersCliveDesktopWork";;
#r "WorkerInterface.dll";;
let obj = System.Activator.GetObject(typeof<WorkerInterface.IWorker>, "tcp://localhost:8080/target.rem");;
let typedObj = ((box obj) :?> WorkerInterface.IWorker);;
typedObj.DoWork();;

Now, suppose we want to encrypt and sign the message as it passes across the network. We may also want to identify the caller.

On the server side, we can turn this on by simply calling

  System.Runtime.Remoting.RemotingConfiguration.Configure("C:UsersCliveDesktopWorkConfig1.txt", true);;

passing the second argument as true instead of false.

At this point if we re-run the same client sequence as above, the code hangs while making the call to DoWork. This is apparently because the server is now trying to do the handshake for securing the channel and the client isn’t able to respond.

The obvious fix seemed to be to

System.Runtime.Remoting.RemotingConfiguration.Configure(… some config file…, true);;

with the true parameter telling the system to make things secure. What confused me initially was that the configuratioin file didn’t contain a system.runtime.remoting element which caused the Configure call to be ignored. Using a configuration file of the form,

<configuration>
 <system.runtime.remoting>
    <application>
      <channels>
        <channel ref="tcp"  />
      </channels>
    </application>
  </system.runtime.remoting>
</configuration>

was successful, and the server now displays.

Method called PHILIP-J-FRYClive

The identity of the caller has been passed and made available to the server code.

Using the interactive REPL, it is easy to navigate around the remoting structures to check that the underlying stream is indeed secure.

let getPrivateField (obj : System.Object) name =
  let flags = System.Reflection.BindingFlags.NonPublic ||| System.Reflection.BindingFlags.Instance
  let fieldInfo = obj.GetType().GetField(name, flags)
  fieldInfo.GetValue obj
let proxy = System.Runtime.Remoting.RemotingServices.GetRealProxy(typedObj);;
proxy.GetType().Name;;
let flags = System.Reflection.BindingFlags.NonPublic ||| System.Reflection.BindingFlags.Instance ||| System.Reflection.BindingFlags.FlattenHierarchy ||| System.Reflection.BindingFlags.GetProperty;;
proxy.GetType().GetProperty("IdentityObject", flags);;
let identity = it.GetValue(proxy, null);;
identity.GetType().GetProperty("ChannelSink", flags);;
let sink1 = it.GetValue(identity, null);;
sink1.GetType().GetProperty("NextChannelSink");;
let transport = it.GetValue(sink1, null);;
getPrivateField transport "_channel" ;;

I love the way that F# allows me to easily explore what is going on, without the need to use a debugger and gives me the ability to easily write code to aid the exploration.

Advertisements
This entry was posted in Computers and Internet. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s