1

I am currently using .NET remoting (C#) to copy a file from a client application to a server application (which then does some processing on it). I can authenticate which user account connects to the server and sends the file, but was wondering if there's a way to also authenticate the COMPUTER that the client application is running on (in other words, for this particular project, we care as much about WHICH COMPUTER the data is being sent from as who is sending it).

IAuthorizeRemotingConnection seems to give only an IPEndPoint for the computer, which isn't really helpful for authenticating it since it's just an IP address.

(I should also mention that this program is guaranteed to be run in a domain environment only.)

Suggestions are appreciated! Thanks!

Edit: For clarification, we are authenticating the computer account for the ultimate purpose of verifying that it is a member of a particular security group in the active directory. We wish our server to reject data unless it is sent from one of the computers defined in this group (though any user can send it through those computers).

  • http://stackoverflow.com/questions/671876/whats-a-good-way-to-uniquely-identify-a-computer – Nick Oct 28 '14 at 15:26
  • If all of the computers are in the same Windows domain you should be able to use the SID. http://msdn.microsoft.com/en-us/library/windows/desktop/aa379571%28v=vs.85%29.aspx – RenniePet Oct 28 '14 at 15:35
  • @Nick He doesn't need to uniquely identify a computer – Nick Hill Oct 28 '14 at 15:35
  • @RenniePet SIDs cannot be used for authentication – Nick Hill Oct 28 '14 at 15:52
  • Well, there is something called a "computer domain SID" that is guaranteed to be unique for every computer in a Windows domain. http://blogs.msdn.com/b/aaron_margosis/archive/2009/11/05/machine-sids-and-domain-sids.aspx – RenniePet Oct 28 '14 at 16:07
  • Here are some more links related to using the computer's domain SID to check its computer account in the AD. Which is what you want, if I understand right. http://blogs.technet.com/b/heyscriptingguy/archive/2013/05/25/weekend-scripter-use-powershell-to-find-computers-sids-in-ad-ds.aspx http://technet.microsoft.com/en-us/sysinternals/bb897417.aspx In other words, use PsGetSid.exe to get the computer's SID, and use the Get-ADComputer cmdlet to verify the computer is who it claims to be according to its computer name, and that that computer's account in the AD is what you want. – RenniePet Oct 28 '14 at 16:58
  • @RenniePet It's easy to find a computer account by either its name or SID. But neither computer name, nor SID can be trusted when received from a client, unlike they are "signed" by a trusted authority, such as Active Directory. – Nick Hill Oct 28 '14 at 17:23
  • 2
    I think that if the call is authenticated as a user account, it is not authenticated as the machine account. The computer account is used when the calling process is running as NETWORK SERVICE or LOCAL SYSTEM. It can't authenticate as the computer and a user at the same time. I could be wrong, but that's how I always thought it worked... – Mike Goodwin Nov 03 '14 at 21:39
  • 1
    If you were using WCF with WS-Trust, I think you could get a security token that contained a token for the computer account AND the user account by using "ActAs" to embed one token inside the other and using a service running as NETWORK SERVICE on the client machine I've never used .Net remoting, but my guess is it won't support this behaviour. – Mike Goodwin Nov 03 '14 at 21:43
  • 2
    Alternatively, if you have access to a public key infrastructure such as Active Directory Certificate Services, maybe you could authenticate the computer using a certificate. For example, using the computer certificates private key to sign the requests. You would have to ensure that users on the clients did not have access to the computer certificate (e.g. not local admins) – Mike Goodwin Nov 03 '14 at 21:49

4 Answers4

0

I'm not an advance programmer but....

Could you not use:

http://msdn.microsoft.com/en-us/library/ms143998.aspx

To reverse lookup the IP to get the DNS name of the computer then use:

http://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.aspx

To confirm that computer name exists in the AD...

Or is that too simple and not secure enough?

Gavzooka
  • 57
  • 1
  • 9
0

The computer name is just a convenience, it is not a securable object. So Remoting makes no effort to easily retrieve it. Not a real problem of course, you can simply expose a remoted property that you can assign in client code. But do keep in mind that if you implement a scheme like this then you'll also need to close loopholes that allows a user to spoof the computer name. Changing it is easy, locking it down is murky. A site like serverfault.com or security.stackexchange.com are the best place to follow up on that.

Assign it in the client code with the value of SystemInformation.ComputerName or Dns.GetHostName(). On the server side you probably want to use System.DirectoryServices to discover facts, it isn't very clear what you are going to do with it.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Neither computer name, nor SID can be trusted when received from a client, unlike they are "signed" by a trusted authority, such as Active Directory. – Nick Hill Oct 28 '14 at 17:25
  • Of course, I didn't hide that detail. If trust is important then do *not* use the computer identity if a security review cannot guarantee that the machine can be locked down well enough. Use the web sites I mentioned to follow up. – Hans Passant Oct 28 '14 at 17:36
  • Well. How does Active Directory authenticate a computer then? – Nick Hill Oct 28 '14 at 17:37
  • okay. It seems AD is authenticating computers using machine passwords: [Machine Account Password Process](http://blogs.technet.com/b/askds/archive/2009/02/15/test2.aspx). That doesn't help a lot, though. – Nick Hill Oct 28 '14 at 17:50
0

From the website:-http://www.developer.com/net/net/article.php/3522466/Improved-NET-Remoting-Part-2-Secure-TCP.htm

Create a Server to Expose the Remotable Object via TCP To create a server object that will act as a listener to accepts remote object requests, you create an instance of the channel and then register it for use by clients on a specific port. You can register the service as WellKnownObjectMode.SingleCall, which results in a new instance of the object for each client, or as WellKnownObjectMode.Singleton, which results in one instance of the object used for all clients.

For this example, create a server listener. Because the service needs to be bound to an available port, choose a port that you know to be unused on your computer. (The example code uses 8080.) To see a list of the used ports on your computer, open a command prompt and issue the command "netstat -a". It may produce a long list, so make sure the command prompt buffer sizes are set to allow scrolling. Compile the class to make sure you have everything correct.

using System;
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

namespace CodeGuru.RemotingSample
{
   /// <remarks>
   /// Sample server to demonstrate the use of secure .NET Remoting.
   /// </remarks>
   public class SampleRemotingServer
   {
      public static void Main() 
      {
         // Set up the configuration parameters through a dictionary
         IDictionary properties = new Hashtable();
         properties.Add("port", 8080);
         properties.Add("secure", true);
         properties.Add("impersonate", true);

         // Create an instance of a channel
         TcpServerChannel serverChannel =
            new TcpServerChannel(properties, null);
         ChannelServices.RegisterChannel(serverChannel);

         // Register as an available service with the name HelloWorld
         RemotingConfiguration.RegisterWellKnownServiceType(
            typeof(SampleObject),
            "HelloWorld.rem", 
            WellKnownObjectMode.Singleton );

         Console.WriteLine("Listening on {0}",
                           serverChannel.GetChannelUri());
         Console.WriteLine("Press the enter key to exit...");
         Console.ReadLine();
      }
   }
}

Add a reference in your project to System.Runtime.Remoting; otherwise, the TcpChannel and other related classes will not be found. In addition, add a reference to the project containing the SampleObject. Otherwise, the code will not compile because it won't know how to find a reference to SampleObject.

To secure the communication programmatically, you need to configure the server connection. Notice how the example code passes parameter information in through a Dictionary. You can configure a number of additional parameters (Find more parameters in the VS 2005 Beta Docs on MSDN.) The parameters you will use on the server side for this example are as follows:

port: Specifies the port number on which the channel will listen. secure: Indicates whether or not the channel is to be secured. (When secured, the channel can require user credentials, as well as encrypt and sign the communication. If the TcpServerChannel is secure, the TcpClientChannel must also be secure. Otherwise, no connection is made.) impersonate: Indicates whether or not the server should impersonate the client.

SemperFi
  • 2,358
  • 6
  • 31
  • 51
  • This tells how to use remoting with security enabled, but doesn't answer the question. – David Forrester Nov 04 '14 at 13:36
  • Thanks for your answer, but it doesn't answer the original question. Also, it's a good practice to provide a link to the original article: http://www.developer.com/net/net/article.php/3522466/Improved-NET-Remoting-Part-2-Secure-TCP.htm – Nick Hill Nov 04 '14 at 13:38
  • I will remember next time i post – SemperFi Nov 04 '14 at 13:53
-1

You can't really authenticate the "computer". A computer is made up of different pieces of hardware. The best you can do is verify some hardware in the computer is allowed to work with your app.

According to this website Windows checks 10 different pieces of hardware for WPA. If you wrote the client application have it pull information from some combination of hardware in the computer and pass it to your server for authentication.

Nick
  • 3,217
  • 5
  • 30
  • 42
  • Every domain-joined computer has a computer account in AD. That's what we need to get for a remote computer using .NET Remoting – Nick Hill Oct 28 '14 at 16:07