Java RMI Client access denied

javarmi

I have a small Java RMI Server and Client program I'm writing. I have spent some time trying to figure out the error messages without success.

The Client generates the following error:

Trying to connect to: 127.0.0.1:3232
ERROR!!!: StockClient: main: Could not connect to the server: java.rmi.UnmarshalException: Error unmarshaling return header; nested
exception is:
java.rmi.UnmarshalException: Error unmarshaling return header; nested exception is:
java.io.EOFException
java.io.EOFException
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:209)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:359)
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
at StockClient.StockClient.main(StockClient.java:44)
Caused by: java.io.EOFException
at java.io.DataInputStream.readByte(DataInputStream.java:250)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:195)
… 3 more

With the server the following error only when the client attempts to connect.

this address=localhost/127.0.0.1,port=3232
Exception in thread "RMI TCP Connection(idle)" java.security.AccessControlException: access denied
(java.net.SocketPermission 127.0.0.1:62586 accept,resolve)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:374)
at java.security.AccessController.checkPermission(AccessController.java:549)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.SecurityManager.checkAccept(SecurityManager.java:1157)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.checkAcceptPermission(TCPTransport.java:636)
at sun.rmi.transport.tcp.TCPTransport.checkAcceptPermission(TCPTransport.java:275)
at sun.rmi.transport.Transport$1.run(Transport.java:158)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:680)

Because of the server error I'm fairly sure its a security or registry error, security policy for the server is:

grant {
permission java.security.AllPermission;
};

and being run with the following argument

-Djava.security.policy=client.policy

I've tried everything I can find but seem to keep going around in circles.

relevant methods:

Server:

 public static void main(String[] args)
    {//main(...) starts
        // set up the data structures and data

        //add users
        //Users hard coded as this is an example proof on concept program
        //Names and passwords not hashed for simplicity
        User alpha = new User("Alpha", "AlphaPass");
        User omega = new User("Omega", "OmegaPass");
        users.add(alpha);
        users.add(omega);

        //startup the RMI server
        try
        {
            System.setSecurityManager(new RMISecurityManager());
            StockServer server = new StockServer();
            StockServerInterface inter = (StockServerInterface)
UnicastRemoteObject.exportObject (server,0);

            // create the registry and bind the name and object.
            registry = LocateRegistry.createRegistry(thisPort);
            registry.rebind("StockServer", inter);
        }
        catch (Exception e)
        {
            System.out.println("Unable to create StockServer: " + e);
            e.printStackTrace();
            System.exit(1);
        }
    }//main(...) ends


    /**
     * Constructor for StockServer
     *
     * @throws RemoteException
     */
    public StockServer() throws RemoteException
    {

        //try to get the host machine's IP address
        try
        {
            // get the address of this host.
            thisAddress = (InetAddress.getLocalHost()).toString();
        } catch (Exception e)
        {
            throw new RemoteException("can't get inet address. " + e);
        }

        //Set the port
        thisPort = 3232;

        //Print out the server address and port
        System.out.println("this address=" + thisAddress + ",port=" + thisPort);
    }

Client:

private static StockServerInterface stockServer;
static public void main(String args[])
{
    Registry registry;
    //get the server address from the args
    String serverAddress = args[0];

    //get the server port from the args
    String serverPort = args[1];

    //Let the user know we are about to try to connect
    System.out.println("Trying to connect to: " + serverAddress + ":" + serverPort);
    try
    {
        // get the registry
        registry = LocateRegistry.getRegistry(
                serverAddress,
                (new Integer(serverPort)).intValue());
        // look up the remote object
        stockServer = (StockServerInterface) (registry.lookup("StockServer"));


        //Authenticate the user
        authenticate();

        //setup the hashset
        HashSet<Stock> hashStockSet = null;

        //setup the hashset of desired stocks
        try
        {
            hashStockSet = getHashSet();
        } catch (IOException e)
        {
            e.printStackTrace();
            System.exit(1);
        } catch (ClassNotFoundException e)
        {
            e.printStackTrace();
            System.exit(1);
        }
        //bit of a heavy handed infinte loop so we continue to get the loop
        while(true)
        {
            //Run the ticker
            ticker(hashStockSet);
        }

        // call the remote method


    }
    catch (RemoteException e)
    {
        System.out.println("ERROR!!!: StockClient: main: Could not connect to the server: "+e);
        e.printStackTrace();
    }
    catch (NotBoundException e)
    {
        System.out.println("ERROR!!!: StockClient: main: Could not connect to the server: "+e);
        e.printStackTrace();
    }

Best Answer

You don't need a SecurityManager in an RMI server unless the client is relying on the codebase feature to supply the server with classes. Either remove it, or debug the .policy file. Clearly the one you've written isn't being loaded.

Run your server with -Djava.security.debug=access,failure and you will see where all the security domains are getting their configurations from, and the domain that is failing at the point where the exception is thrown.