Working with Sockets


The .NET Framework provides access to an impressive array of socket-oriented communication methodologies—everything from the typical Transmission Control Protocol/Internet Protocol (TCP/IP) communication to the Infrared Data Association (IrDA) connection used for laptops and other equipment. You can use the various classes to create both clients and listeners. In short, the System.Net.Sockets namespace contains a class for most needs. If you don’t see what you need, third party vendors such as Dart (http://www.dart.com/dotnet/sslsockets_faq.asp) supply socket-based add-on products you can use.

Note

A complete discussion of sockets and a description of how they work under Windows are outside the scope of this book. You can find a number of good Windows Sockets (WinSock) tutorials, including the documentation with MSDN. A number of online sites such as Windows Sockets: A Quick and Dirty Primer (http://world.std.com/~jimf/papers/sockets/winsock.html) and Windows Sockets Programming (http://www.snible.org/winsock/) provide good general information. The .NET Framework removes a lot of the complexity from working with sockets, so it also pays to know the .NET side of things. You’ll find a good selection of TCP/IP articles on the .NET 247 site at http://www.dotnet247.com/247reference/System/Net/Sockets/TcpClient.aspx. Another good article that shows how to use sockets is “Using .NET Sockets” at http://www.ondotnet.com/pub/a/dotnet/2002/10/21/sockets.htm .

A good understanding of the WinSock interface is important if you want to create a secure .NET application with the .Net.Sockets.Sockets class. In most cases, the sockets implementation provided by .NET merely marshals the requests to the underlying WinSock implementation (normally found in WinSock.DLL). Any flaws in the standard WinSock implementation provided by Microsoft also affect your .NET application. In addition, you have the added burden of the .NET layer to consider, so the number of potential security issues is higher for a .NET application than they are for an equivalent native application. Fortunately, the .NET Framework also provides classes that can help you maintain better control over the application environment.

The following sections describe several security measures you can use when working with sockets. Don’t assume that you only use sockets with Internet applications—the LAN relies on them as well and you might find that you actually use sockets more often in a LAN environment.

Using the SocketPermission Class

One of the advantages of using the .NET Framework to develop applications from a security standpoint is that it contains a permission for most activities. The application can’t do much if it lacks the required permissions—it can’t even execute. With this in mind, the .NET Framework includes a special permission for working with sockets. The SocketPermission class doesn’t grant other rights, just the right to work with sockets.

Before we get into the permission, however, let’s look at some typical code. Listing 8.1 shows how to define code that makes a basic connection to the LocalHost connection (available on every computer) using the Telnet service. The SocketPermission entry in Listing 8.1 grants permission to use the socket. The source code also includes an example of how to deny this permission. Although the second example doesn’t appear in the listing, I’ll tell you about the differences in the code discussion. You’ll find this example in the \Chapter 08\C#\SocketPerm and \Chapter 08\VB\SocketPerm folders of the source code located on the Sybex Web site.

Listing 8.1 Using the SocketPermission Class

start example
private void btnAllow_Click(object sender, System.EventArgs e) {    SocketPermission  SP;            // Containt the permission object.    Socket            LocalConnect;  // A local connection.    IPHostEntry       HostList;      // A list of addresses.    IPAddress         LocalHost;     // The address of the localhost.    IPEndPoint        LocalHostEnd;  // The localhost endpoint.    Byte[]            DataBuffer;    // Holds received data.    Char[]            ConvertBuffer; // Data converstion buffer.    String            DataString;    // Human readable string.    Int32             Counter;       // Loop counter.    // Define the permission.    SP = new SocketPermission(NetworkAccess.Connect,                              TransportType.All,                              "LocalHost",                              23);    // Allow the access.    SP.Assert();       // Define the socket.    LocalConnect = new Socket(AddressFamily.InterNetwork,                              SocketType.Stream,                              ProtocolType.Tcp);    // Get the host addresses.    HostList = Dns.Resolve("LocalHost");       // Create the connection.    LocalHost = new IPAddress(HostList.AddressList[0].Address);    LocalHostEnd = new IPEndPoint(LocalHost, 23);    // Open the connection.    try    {       LocalConnect.Connect(LocalHostEnd);    }    catch (SocketException SockExc)    {       // Display a socket error and exit.       MessageBox.Show("Socket Error\r\n" + SockExc.Message,                       "Socket Exception",                       MessageBoxButtons.OK,                       MessageBoxIcon.Error);       return;    }    catch (SecurityException SE)    {       // Display a security error and exit.       MessageBox.Show("Secuirty Error\r\n" + SE.Message,                       "Secuirty Exception",                       MessageBoxButtons.OK,                       MessageBoxIcon.Error);       return;    }    // Display the connected status.    if (LocalConnect.Connected)       MessageBox.Show("Connected", "Connection Status",                       MessageBoxButtons.OK,                       MessageBoxIcon.Information);    else    {       MessageBox.Show("Connection Failed", "Connection Status",                       MessageBoxButtons.OK,                       MessageBoxIcon.Information);       return;    }    // Telnet will send some initial options. Clear these options.    DataBuffer = new Byte[LocalConnect.Available];    LocalConnect.Receive(DataBuffer);    // Load the Are You There? command and send it.    DataBuffer = new Byte[2];    DataBuffer[0] = 255;    DataBuffer[1] = 246;    LocalConnect.Send(DataBuffer);    LocalConnect.Poll(1000, SelectMode.SelectRead);    // Read the answer to the question.    DataBuffer = new Byte[LocalConnect.Available];    LocalConnect.Receive(DataBuffer);    // Convert it to a string.    ConvertBuffer = new Char[DataBuffer.Length];    for (Counter = 0; Counter < DataBuffer.Length; Counter++)       ConvertBuffer[Counter] = Convert.ToChar(DataBuffer[Counter]);    DataString = new String(ConvertBuffer);    // Display the result.    MessageBox.Show("Are you there?" + DataString, "Query Result",                    MessageBoxButtons.OK, MessageBoxIcon.Information);    // Close the connection.    LocalConnect.Close(); }
end example

The code begins by declaring and defining a SocketPermission object. Unlike many of the other permissions discussed in the book, this permission is very specific. You must provide input that determines how the program uses sockets. The first argument determines whether the program will act as a client or server. Selecting the NetworkAccess.Connect value means the permission acts on behalf of the client. On the other hand, selecting the NetworkAccess.Access value lets the code listen for incoming requests and act as a server. The second argument defines the method of communication. The example uses TransportType.All, but you could also select a specific transport methodology such as TCP or User Datagram Protocol (UDP). The permission is also specific to a particular host. In this case, the code makes a connection to LocalHost (third argument) on port 23 (fourth argument). The specific nature of this input means you’ll likely define multiple permissions and combine them to provide a permission list.

Once the code creates the SocketPermission object, it uses the Assert() or Deny() method to allow or deny access. However, you’ll notice that nothing happens right away. Follow the code with the debugger and you’ll notice the code can create the Socket object, resolve the LocalHost address using the Dns.Resolve() method, and even create the connection by defining an IPAddress and IPEndPoint object. None of these actions actually involves using the sockets, so there’s no security breach. However, the security breach does occur when the code executes the LocalConnect.Connect() method. Notice that the example code catches both SocketException and SecurityException errors. Proper security and good coding practice require that you handle both. If the LocalConnect.Connect() method fails for either reason, there’s a possibility of unauthorized access.

The example program relies on the Telnet service. If the program fails with a socket error, it’s usually an indicator that the Telnet service is stopped—you need to verify that Windows has started the Telnet service. The Services snap-in appears in Figure 8.1. Right-click the Telnet service shown in the figure and choose Start from the context menu. Many machines have this service set to Manual so it doesn’t start automatically for security reasons. Telnet does offer a security opening that many crackers have used to gain entrance in the past, so setting this service to Manual if you don’t need it is always a good idea.

click to expand
Figure 8.1: Make sure you start the Telnet service before you run the program.

The program code continues by testing the connected state of the code and then sending and receiving some information. It’s important to consider the effect of flag options when you work with the Send() or Receive() methods. For example, sending a message with the SocketFlags .DontRoute flag means that you can determine precisely where a message goes without worrying that the server will route it elsewhere. Some exploits depend on the router’s sending a message to another location, such as the cracker’s client or server. Likewise, including the SocketFlags .OutOfBand flag can open your client up to unexpected data. A number of exploits make use of out-of-band (OOB) data. The server sends and the client receives OOB data independently of normal data (the data sent by your application). The cracker can use this extra channel to send damaging code. To see the effects of one of these exploits, read the Wired article at http://www.wired.com/news/technology/0,1282,3809,00.html. Of course, OOB does have a legitimate use—it enables your application to handle error (or emergency) messages.

The “Are you there?” command is an easy way to test a Telnet connection. In this case, the program displays an answer of [Yes] when successful. It’s not within the scope of this book to tell you about all of the Telnet commands and options. You can learn more about these features in Microsoft Knowledge Base article Q231866. This source is unfortunately incomplete. Look at the Rexx Sockets to Telnet Session site (http://w3.hethmon.com/os2isp/1998/Aug/Msgs/l2w03532.html) for a list of some commands and options that Microsoft doesn’t document. You should also view the original standard, RFC854, at http://www.faqs.org/rfcs/rfc854.html.

Warning

Some developers make the mistake of thinking that a secure desktop, a secure wire, and a secure server equate to a secure computing environment. Unfortunately, even the large companies are still making this assumption. For example, consider the recent InfoWorld article where the Windows Media Player required a patch so it inspects incoming data more carefully (http://www.infoworld.com/article/03/05/07/HNmediapatch_1.html). You must verify and validate every part of the communication, including the data. A cracker has no rules about how a virus gets onto your system—any hole will do.

Using the Secure Socket Layer (SSL) Protocol

Many developers associate SSL with the Internet. Web servers use this protocol when you type HTTPS in the URL rather than HyperText Transfer Protocol (HTTP). Depending on how the network administrator sets up the Web server, using this special protocol designation automatically creates a secure connection. However, don’t assume that this protocol is only for use on an Internet connection. Although the use of HyperText Transfer Protocol Secure (HTTPS) sockets will cost you some application performance, using it on a local intranet is also helpful. Local connections should be just as secure as those you use on the Internet.

In addition to the obvious Web connections, SSL is also an option for more traditional communication. For example, SSL is one of the options that you can choose when setting security up for a message queue. The Message.AuthenticationProviderType property relies on the CryptographicProviderType enumeration, which includes SSL as one of the options you can choose.

Unfortunately, SSL support is far from universal in the .NET Framework. For example, you can’t use SSL with the NetworkCredential class explained in the “Using the System.Net .NetworkCredential and System.Net.CredentialCache Class” section of the chapter. For the most part, SSL is limited to Internet communication or communication that could occur over the Internet. The point to remember is that an intranet, which is an internal network, can use SSL too, making this particular protocol quite versatile. (An intranet uses most of the same technologies and processes as the Internet; however, the functionality differs in that an intranet is private to a company and not exposed to the public.)

Using the System.Net. NetworkCredential and System.Net. CredentialCache Classes

The System.Net.NetworkCredential class let’s you store security information about a user in a compact form and use the resulting object to access resources locally and on a network. You can use the resulting object for basic, digest, Windows NT LAN Manager (NTLM), and Kerberos authentication. This object contains a single credential, which means that you need one object for each unique network object that you want to access. Of course, if the user has a single password for all network resources, then you only need one credential. In addition to the username and password, a credential can also include the user’s domain.

The System.Net.CredentialCache class works with the NetworkCredential class to store multiple credentials in one object. Each credential is associated with a particular resource using a Uniform Resource Identifier (URI). The Microsoft examples tend to associate this class with Internet resources. However, a URI can also include local drives, network drives, or any other resource that you can identify with a URI. Listing 8.2 shows an example of how to use the CredentialCache and NetworkCredential classes together. You’ll find this example in the \Chapter 08\C#\Credential and \Chapter 08\VB\Credential folders of the source code located on the Sybex Web site.

Listing 8.2 Using the CredentialCache and NetworkCredential Classes

start example
private void btnTest_Click(object sender, System.EventArgs e) {    NetworkCredential OneCred;    // A single credential.    CredentialCache   CredCache;  // A group of credentials.    WebRequest        WebReq;     // The access request.    WebResponse       RespData;   // Response data.    Stream            DataStream; // The file data.    StreamReader      SR;         // The I/O stream.    // Clear the output.    txtOutput.Text = "";    // Create the network credential.    OneCred = new NetworkCredential(txtUsername.Text, txtPassword.Text);    // Create the credential cache.    CredCache = new CredentialCache();    // Add the credential.    CredCache.Add(new Uri(txtURI.Text), "Basic", OneCred);    CredCache.Add(new Uri(txtURI.Text), "Digest", OneCred);    CredCache.Add(new Uri(txtURI.Text), "NTLM", OneCred);    CredCache.Add(new Uri(txtURI.Text), "Kerberos", OneCred);    // Make the request.    WebReq = WebRequest.Create(txtURI.Text);    WebReq.Credentials = CredCache;    // Get the response.    RespData = WebReq.GetResponse();    // Get the data.    DataStream = RespData.GetResponseStream();    SR = new StreamReader(DataStream);    txtOutput.Text = SR.ReadToEnd(); }
end example

This example program is interesting because it lets you retrieve the text content of any URI. It works equally well with the text file on your local drive as it will with a Web site. Of course, the program can’t access resources that the WebRequest class can’t access. In addition, it doesn’t work particularly well with binary files. The program doesn’t crash, but the output is understandably less than readable.

One of the secrets of this program is that it lets you enter a username and password for the resource. This information doesn’t have to be the same as your normal name and password—it can be specific to that resource. The example creates the NetworkCredential object using the username and password as input. The constructor for this class also accepts input such as a domain name. The example doesn’t provide this functionality.

After the code constructs a CredentialCache object named CredCache, it uses the CredCache .Add() method to add the credential to the cache. The cache makes the credential URI specific and requires a specific authentication method. The example shows how to add multiple authentication methods to the cache for the same URI and credential. The WebRequest object will evaluate the credentials in order, so you should place them in order of preference. The order in the example is basic, digest, NTLM, and finally Kerberos.

When you access a secured site, the code will fail at the WebReq.GetResponse() method. This call is the first time that the code actually accesses the resource. Consequently, you’ll want to surround this call and the remaining data handling statements in a try...catch statement for error handling purposes. The example doesn’t include this code for the sake of clarity.




.Net Development Security Solutions
.NET Development Security Solutions
ISBN: 0782142664
EAN: 2147483647
Year: 2003
Pages: 168

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