All Permissions
4.3 Methods of the Security Manager
4.3.2 Methods Relating to Network Access
Network access in Java is always accomplished by opening a network socket, whether directly through the Socket class or indirectly through another class like the URL class. An untrusted class can only (by default) open a socket to the machine from which it was actually downloaded; typically, this is the location given by the CODEBASE tag in the HTML for the browser page containing the applet or −− in the absence of such a tag
−− the web server for the page. In either case, the machine in question is a web server, so we'll use that terminology in this discussion. Untrusted classes loaded from the classpath cannot, by default, open any sockets.
This restriction on untrusted classes is designed to prevent two types of attack. The first attack concerns a rogue applet using your machine for malicious purposes by connecting to a third machine over the network.
The canonical description of this attack is an applet that connects to the mail server on someone else's machine and sends people on that machine offensive email from your address. There are more severe attacks possible with this technique, however −− such an applet could use a connection from your machine to break into a third computer, and auditors on that third computer will think the break−in attempts are coming from you, which can cause you all sorts of legal problems.
The second sort of attack concerns network information on your local network that you might not want to be broadcast to the world at large. Typically, computers at corporations or campuses sit behind a firewall so that users on the Internet cannot access those computers (see Figure 4−2). The firewall allows only certain types of traffic through (e.g., HTTP traffic) so that users on the local network can access the Internet, but users on the Internet cannot glean any information about the local network.
Figure 4−2. A typical firewall configuration
Now consider what happens if an applet downloaded onto a machine on the local network can connect to other machines on the local network. This allows the applet to gather all sorts of information about the local network topology and network services and to send that information (via HTTP, so that it will pass through
the firewall) back out onto the Internet. Such an opportunity for corporate spying would be very tempting to would−be hackers. Worse, if the applet had access to arbitrary network services, it could break into the local HR database and steal employee data, or it could break into a network file server and steal corporate
documents. Hence, applets (and untrusted classes in general) are prevented from arbitrary network access.
Network sockets can be logically divided into two classes: client sockets and server sockets. A client socket is responsible for initiating a conversation with an existing server socket; server sockets sit idle waiting for these requests to come from client sockets. Untrusted classes are by default restricted from creating server sockets.[2]
Normally, this is not a problem: since an applet can only talk to its web server, it could only answer requests from that machine −− and the applet can already open a connection to that machine at will. There's no algorithmic or logistic reason why an operation between the applet and the web server cannot always start with the applet as the client.
[2] Technically, untrusted classes by default can create a server socket, since the default policy file allows all classes to perform the listen action. Once created, however, the server socket must accept a connection on the socket, and that action is by default denied.
The security manager uses the following methods to check network access:
public void checkConnect(String host, int port)
public void checkConnect(String host, int port, Object context)
Check if the program can open a client socket to the given port on the given host. This succeeds if the current protection domain has a socket permission with a name that matches the host and port and an action of connect.
public void checkListen(int port)
Check if the program can create a server socket that is listening on the given port. The protection domain must have a socket permission where the host is localhost, the port range includes the given port, and the action is listen.
public void checkAccept(String host, int port)
Check if the program can accept (on an existing server socket) a client connection that originated from the given host and port. The protection domain must have a socket permission where the host and port match the parameters to this method and an action of accept.
public void checkMulticast(InetAddress addr)
public void checkMulticast(InetAddress addr, byte ttl)
Check if the program can create a multicast socket at the given multicast address (optionally with the given time−to−live value). This succeeds if the current protection domain has a socket permission with a host that matches the given address, a port range of all ports, and an action list of connect and accept.
public void checkSetFactory( )
Check if the program can change the default socket implementation. When the Socket class is used to create a socket, it gets a new socket from the socket factory, which typically supplies a standard TCP−based socket. However, a program could install a socket factory so that the sockets it uses all have different semantics, such as sockets that send tracing information when they write data. The
current protection domain must carry a runtime permission with the name setFactory.
The instances where these methods are used and the rationale for such uses are shown in Table 4−2.
Table 4−2. Security Manager Methods to Protect Network Access
Method Called By
Rationale
checkConnect( )
DatagramSocket.send( ) DatagramSocket.receive( ) (Deprecated)
MulticastSocket.send( ) Socket( )
Test if the untrusted class can create a client−side connection.
checkConnect( )
DatagramSocket.getLocalAddress( ) InetAddress.getHostName( )
InetAddress.getLocalHost( ) InetAddress.getAllByName( )
Test if the untrusted class can see any hosts on the local network.
checkListen( )
DatagramSocket( ) MulticastSocket( ) ServerSocket( )
Test if the untrusted class can create a server−side socket.
checkMulticast( )
DatagramSocket.send( ) DatagramSocket.receive( ) MulticastSocket.send( ) MulticastSocket.receive( ) MulticastSocket.joinGroup( ) MulticastSocket.leaveGroup( )
Test if the untrusted class can operate on a multicast socket.
checkAccept( )
ServerSocket.accept( ) DatagramSocket.receive( )
Test if the untrusted class can accept a server connection.
checkSetFactory( )
ServerSocket.setSocketFactory( ) Socket.setSocketFactory( )
URL.setURLStreamHandlerFactory( )
URLConnection.setContentHandlerFactory( ) RMI.setSocketFactory( )
Test if the untrusted class can alter the manner in which all sockets are created.
checkSetFactory( )
HttpURLConnection.setFollowRedirects( )
Test if the untrusted class can change redirection behavior.
Some notes are in order. As in the case with file access, these methods sometimes check operations that are logically different from a programming view but are essentially the same thing from a system view. Hence, the checkConnect( ) method not only checks the opening of a socket but also the retrieval of hostname or address information (on the theory that to know the name of a host, you need to be able to open a socket to that host). This last test may seem somewhat odd −− under what circumstances, you might wonder, should an untrusted class not be able to know the name or address of the machine on which it is running? Recall that we want to prevent the outside world from knowing our network topology; this includes the name and address of the user's machine as well.[3]
[3] On the other hand, there's a good chance the outside web server already has that
information, since our browser sent along a hostname and other information when it retrieved the file to begin with. If our request passed through a firewall or proxy server, there's a chance that some of this information was prevented from passing to the outside web server, but that's not necessarily the case either.
The checkSetFactory( ) method of the security manager class is responsible for arbitrating the use of several low−level aspects of Java's network classes. Most of the tests made by this method have to do with whether or not the untrusted class is allowed to create some variety of socket factory. Socket factories are classes that are responsible for creating sockets that implement a particular interface while having a nonstandard feature. For instance, you could use a socket factory to provide sockets that always perform encryption. Predictably, untrusted classes cannot change the socket factory in use.
This method is also used to determine whether the Java program will automatically follow redirect messages when opening a URL. When a Java program opens a URL, the server to which it is connected may send back a redirect response (an HTTP response code of 3xx). Often, browsers follow these redirects transparently to the user; in Java, the programmer has the ability to determine if the redirection should automatically be followed or not. An untrusted class is not able to change whether redirection is on or off. The
HttpURLConnection class that uses this method is abstract, so the actual behavior of this class may be overridden in a particular implementation.