Chapter 5: Securing .NET Remoting

THIS CHAPTER SHOWS YOU HOW to leverage IIS' features when it comes to hosting your components in a secured environment. In this chapter you learn how to enable either basic HTTP sign-on or the more secure Windows-integrated authentication scheme, which is based on a challenge/response protocol. You also see how to enable encrypted access by using standard SSL certificates at the server side.

Deployment for Authenticated Use

A general problem of .NET Remoting is that the framework does not incorporate a standard means of authentication. Instead, Microsoft opened the interfaces so that any authentication (and encryption) variant can be used by implementing custom sinks and sink providers. The effort to implement these sinks may be reasonable when developing large-scale distributed applications that have to integrate with already installed third-party sign-on solutions.

For most other applications, you can use IIS to authenticate requests against Windows user accounts. This functionality is not tailored to remoting, but applies to all IIS applications, including static HTML pages and ASP.NET Web applications.

The security properties can be specified in the IIS snap-in to the MMC. You can see a "locked-down" version of the previous server in Figure 5-1.

click to expand
Figure 5-1: Authentication is necessary when accessing the remote objects.

Caution 

The Basic Authentication scheme, which is usable for remoting components, is not at all secure. Using a TCP/IP packet sniffer, one can easily capture the authentication tokens and resend them with their own requests to "impersonate" the original user. For really secure applications, encryption using SSL is highly recommended, and may even be a necessity.

When using authentication within IIS, a change in the client code is necessary to send usernames and passwords to your server. Before running the following example, you have to create a new local user called DummyRemotingUser with the password 12345 on your system.

To transfer the logon information to the server, you have to set properties on the channel sink. Unfortunately, there is no direct way to specify a valid username/password combination for a given hostname (but I'll show you how to do this using a custom sink in Chapter 9). In the meantime, you have to call the static method ChannelServices.GetChannelSinkProperties(), which takes the proxy to the remote object as a parameter. This function returns an IDictionary that allows you to set extended properties including username and password.

 IDictionary props = ChannelServices.GetChannelSinkProperties(mgr); props["username"] = "dummyremotinguser"; props["password"] = "12345"; 

You should also extend the client to contain code to catch possible exceptions. These can occur due to misconfigurations on the server side or when passing an incorrect username/password combination. The complete source code for an authenticated client is shown in Listing 5-1.

Listing 5-1: Client That Uses IIS' Built-In Authentication Methods

start example
 using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Collections; using System.Runtime.Remoting.Services; using General; // from General.DLL using Server; // from server.cs namespace Client {    class Client    {       static void Main(string[] args)       {          try          {             String filename = "client.exe.config";             RemotingConfiguration.Configure(filename);             CustomerManager mgr = new CustomerManager();             Console.WriteLine("Client.Main(): Reference to CustomerManager " +                            " acquired");            IDictionary props = ChannelServices.GetChannelSinkProperties(mgr);            props["username"] = "dummyremotinguser";            props["password"] = "12345";             Customer cust = mgr.getCustomer(4711);             int age = cust.getAge();             Console.WriteLine("Client.Main(): Customer {0} {1} is {2} " +                               "years old.",                cust.FirstName,                cust.LastName,                age);          }          catch (Exception e)          {             Console.WriteLine("EX: {0}",e.Message);          }          Console.ReadLine();       }    } } 
end example

This client now connects to the server and authenticates the user against the specified Windows user account on the server machine. You can see in Figure 5-2 what happens when you change the password for DummyRemotingUser.

click to expand
Figure 5-2: Incorrect username/password combination

Checking Roles

The approach shown in the preceding section does not yet increase security that much. Every user registered on your system or your domain will be able to access the server. What you probably want to do is only allow certain users to use your service or even assign different privileges to different users.

Using the IPrincipal interface from System.Security.Principal, you can verify the group membership of a given user. To get access to a thread's current principal, you can call System.Threading.Thread.CurrentPrincipal, as IIS sets this property when using authenticated calls. The IPrincipal's method IsInRole() allows you to check the membership of the current user in a specified Windows group.

Tip 

Be sure to pass not only the name of the group but also the name of your machine or domain, as in IsInRole(@"YOURMACHINE\ThisGroup") or IsInRole(@"YOURDOMAIN\ThisGroup").You can get the name of the current computer from Environment.MachineName.

In Listing 5-2, I show you how to extend the server to check if the remote user is in the group RemotingUsers.

Listing 5-2: Checking the Membership in Windows Groups When Hosting in IIS

start example
 using System; using General; using System.Security.Principal; namespace Server {    class CustomerManager: MarshalByRefObject    {       public CustomerManager()       {          Console.WriteLine("CustomerManager.constructor: Object created");       }       public Customer getCustomer(int id)       {          String machinename = Environment.MachineName;         IPrincipal principal =                System.Threading.Thread.CurrentPrincipal;         if (! principal.IsInRole(machinename + @"\RemotingUsers"))         {             throw new UnauthorizedAccessException(                          "The user is not in group RemotingUsers");         }          Console.WriteLine("CustomerManager.getCustomer): Called");          Customer tmp = new Customer();          tmp.FirstName = "John";          tmp.LastName = "Doe";          tmp.DateOfBirth = new DateTime(1970,7,4);          Console.WriteLine("CustomerManager.getCustomer(): Returning " +             "Customer-Object");          return tmp;       }    } } 
end example

Note 

You can create a group and assign users to it using the MMC (access this by right-clicking My Computer and selecting Manage, System Tools Local Users and Groups).

You can use the same client as in the earlier example with this server. Depending on the group membership of the user, you will see the output in Figure 5-3 when DummyRemotingUser is a member of RemotingUsers, or Figure 5-4 when DummyRemotingUser is not a member of this group.

click to expand
Figure 5-3: The user is in the correct group.

click to expand
Figure 5-4: The user is not a member of the required group.

Note 

Updates to group membership or users' passwords are not reflected online in IIS.You might have to either wait a little or restart IIS before such changes will take effect.

Securing the Sign-On Process

In the preceding examples, I used the so-called HTTP Basic Authentication. This enables a great deal of interoperability between various Web servers and proxies. Unfortunately, this type of authentication allows a playback attack, which means that someone who uses a device to monitor all network traffic can later incorporate the transferred username/password combination in his or her own requests.

When both the client and the server are based on Windows XP, 2000, or NT, you can use the Windows NT challenge/response authentication. This is a nonstandard mechanism that unfortunately does not work with all HTTP proxies. However, if it is supported by the proxies of your users, it nevertheless provides considerably higher security against playback attacks.

In this authentication scheme, the server passes a random value to the client, and this value is incorporated in its response. A playback of the password, which has been captured by watching the network packets, is therefore not possible, simply because the random value will be different.

You can switch to this authentication scheme using Internet Services Manager MMC, as shown in Figure 5-5. Neither the client's code nor the server's code has to be changed after this switch.

click to expand
Figure 5-5: Enabling Windows authentication

Note 

You can also enable both Basic and Windows authentication at the same time. The remoting framework (as well as standard Internet Explorer) will choose the most secure method that has been announced by the server.

Enabling Single Sign-On

When your user is authenticated against the same Windows domain in which your server is located, you finally can use integrated security. This will log your users onto the server without further need of specifying usernames or passwords.

The HTTP channel has a property called useDefaultCredentials. When this property is set to true via the configuration file and no username or password is specified within the ChannelSink's properties, the credentials of the currently logged-on user will be passed to the server. Because Windows 2000 can't get to a user's cleartext password, this scheme is only possible when using Windows authentication on your Web server.

When you want to switch to this authentication scheme, you just have to remove all calls to the channel sink's properties, which set the username or password, and instead include the following configuration file:

 <configuration>   <system.runtime.remoting>     <application>       <channels>          <channel ref="http" useDefaultCredentials="true" />       </channels>       <client>         <wellknown type="Server.CustomerManager, Client"             url="http://localhost:8080/MyAuthServer/CustomerManager.soap" />       </client>     </application>   </system.runtime.remoting> </configuration> 




Advanced  .NET Remoting C# Edition
Advanced .NET Remoting (C# Edition)
ISBN: 1590590252
EAN: 2147483647
Year: 2002
Pages: 91
Authors: Ingo Rammer

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net