Package

Source Code of DgcServerExposure$DgcServer

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* @test
* @bug 5099956
* @summary The server-side DGC implementation remote object should
* only be exported at a given endpoint while there are DGC-enabled
* remote objects also exported at that same endpoint, in order to
* minimize exposure to certain unmarshalling denial-of-service
* attacks (such as a "large object" attack), given that the
* server-side DGC implementation does not support access control.
* Also, when the server-side DGC implementation remote object is
* exported, it should ignore codebase annotations when unmarshalling
* arguments, in order to minimize exposure to unmarshallling
* denial-of-service attacks that involve downloading untrusted code.
*
* @library ../../../../../testlibrary
* @build DgcServerExposure ForeignUuid
* @build TestLibrary
* @run main/othervm/policy=security.policy DgcServerExposure
*/

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.net.URL;
import java.net.URLClassLoader;
import java.rmi.NoSuchObjectException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.ServerException;
import java.rmi.UnmarshalException;
import net.jini.export.Exporter;
import net.jini.id.Uuid;
import net.jini.id.UuidFactory;
import net.jini.jeri.BasicILFactory;
import net.jini.jeri.BasicInvocationHandler;
import net.jini.jeri.BasicJeriExporter;
import net.jini.jeri.BasicObjectEndpoint;
import net.jini.jeri.Endpoint;
import net.jini.jeri.InvocationLayerFactory;
import net.jini.jeri.ObjectEndpoint;
import net.jini.jeri.ServerEndpoint;
import net.jini.jeri.tcp.TcpEndpoint;
import net.jini.jeri.tcp.TcpServerEndpoint;

public class DgcServerExposure {

    private static final Uuid DGC_ID =
  UuidFactory.create("d32cd1bc-273c-11b2-8841-080020c9e4a1");

    private static final String foreignUuidClassName = "ForeignUuid";

    private static final int PORT_A = 2019;
    private static final int PORT_B = 2020;

    private static final InvocationLayerFactory ilf =
  new BasicILFactory(null, null,
         DgcServerExposure.class.getClassLoader());

    private static final Uuid clientID = UuidFactory.generate();
    private static long nextSequenceNum = Long.MIN_VALUE;

    public static void main(String[] args) throws Exception {
  System.err.println("\nRegression test for bug 5099956\n");

  if (System.getSecurityManager() == null) {
      System.setSecurityManager(new SecurityManager());
  }

  /*
   * Obtain a Uuid instance that will not be locally loadable
   * by the DGC server implementation.
   */
  URL codebase =
      TestLibrary.installClassInCodebase(foreignUuidClassName,
                 "codebase");
  ClassLoader foreignUuidLoader =
      URLClassLoader.newInstance(
    new URL[] { codebase },
    DgcServerExposure.class.getClassLoader());
  Class foreignUuidClass = Class.forName(foreignUuidClassName, false,
                 foreignUuidLoader);
  Uuid foreignUuid = (Uuid) foreignUuidClass.newInstance();

  /*
   * Establish two server endpoints and proxies for calling the
   * DGC servers at each of those endpoints.
   */
  ServerEndpoint seA = TcpServerEndpoint.getInstance(PORT_A);
  ServerEndpoint seB = TcpServerEndpoint.getInstance(PORT_B);

  DgcServer dgcA = makeDgcProxy(TcpEndpoint.getInstance("", PORT_A));
  DgcServer dgcB = makeDgcProxy(TcpEndpoint.getInstance("", PORT_B));

  /*
   * Export non-DGC-enabled remote object (A0) on endpoint A.
   *
   * - DGC call to A should fail.
   */
  Remote implA0 = new Remote() { };
  Exporter expA0 = new BasicJeriExporter(seA, ilf, false, false);
  expA0.export(implA0);
  System.err.println("\t{A0}");

  System.err.print("DGC call to A ");
  verifyFailure(dgcA);

  /*
   * Export DGC-enabled remote object (B1) on endpoint B.
   *
   * - DGC call to A should still fail.
   * - DGC call to B should succeed.
   * - DGC call to B with foreign UUID class should fail.
   */
  Remote implB1 = new Remote() { };
  Exporter expB1 = new BasicJeriExporter(seB, ilf, true, false);
  expB1.export(implB1);
  System.err.println("\t{A0}\t{B1}");

  System.err.print("DGC call to A ");
  verifyFailure(dgcA);
  System.err.print("DGC call to B ");
  verifySuccess(dgcB);
  System.err.print("DGC call to B with foreign UUID class ");
  verifyFailureWithUuid(dgcB, foreignUuid);

  /*
   * Export DGC-enabled remote object (A1) on endpoint A.
   *
   * - DGC call to A should now succeed.
   */
  Remote implA1 = new Remote() { };
  Exporter expA1 = new BasicJeriExporter(seA, ilf, true, false);
  expA1.export(implA1);
  System.err.println("\t{A0,A1}\t{B1}");

  System.err.print("DGC call to A ");
  verifySuccess(dgcA);

  /*
   * Unexport A1.
   *
   * - DGC call to A should fail again.
   * - DGC call to B should still succeed.
   */
  expA1.unexport(true);
  System.err.println("\t{A0}\t{B1}");

  System.err.print("DGC call to A ");
  verifyFailure(dgcA);
  System.err.print("DGC call to B ");
  verifySuccess(dgcB);

  /*
   * Export non-DGC-enabled remote object (B0) on endpoint B, to
   * maintain listening on B.  Then clear reference to B1,
   * letting it become garbage collected.
   *
   * - DGC call to B should now fail.
   */

  Remote implB0 = new Remote() { };
  Exporter expB0 = new BasicJeriExporter(seB, ilf, false, false);
  expB0.export(implB0);
  System.err.println("\t{A0}\t{B0,B1}");

  implB1 = null;
  System.gc();
  Thread.sleep(3000);
  System.err.println("\t{A0}\t{B0}");

  System.err.print("DGC call to B ");
  verifyFailure(dgcB);

  System.err.println("TEST PASSED");
    }

    private static void verifySuccess(DgcServer dgc) {
  try {
      dgc.dirty(clientID, nextSequenceNum++, new Uuid[] { });
      System.err.println("succeeds as expected");
  } catch (RemoteException e) {
      throw new RuntimeException("TEST FAILED: unexpected failure", e);
  }
    }

    private static void verifyFailure(DgcServer dgc) {
  try {
      dgc.dirty(clientID, nextSequenceNum++, new Uuid[] { });
      throw new RuntimeException("TEST FAILED: unexpected success");
  } catch (NoSuchObjectException e) {
      System.err.println(
    "throws NoSuchObjectException as expected");
  } catch (RemoteException e) {
      throw new RuntimeException("TEST FAILED: unexpected failure", e);
  }
    }

    private static void verifyFailureWithUuid(DgcServer dgc, Uuid uuid) {
  try {
      dgc.dirty(clientID, nextSequenceNum++, new Uuid[] { uuid });
      throw new RuntimeException("TEST FAILED: unexpected success");
  } catch (ServerException e) {
      Throwable cause = e.getCause();
      if (cause instanceof UnmarshalException &&
    cause.getCause() instanceof ClassNotFoundException)
      {
    System.err.println("throws ServerException as expected");
      } else {
    throw new RuntimeException("TEST FAILED: unexpected failure",
             e);
      }
  } catch (RemoteException e) {
      throw new RuntimeException("TEST FAILED: unexpected failure", e);
  }
    }

    private static DgcServer makeDgcProxy(Endpoint e) {
  ObjectEndpoint oe = new BasicObjectEndpoint(e, DGC_ID, false);
  InvocationHandler ih = new BasicInvocationHandler(oe, null);
  return (DgcServer)
      Proxy.newProxyInstance(DgcServer.class.getClassLoader(),
           new Class[] { DgcServer.class }, ih);
    }

    private interface DgcServer extends Remote {
  long dirty(Uuid clientID, long sequenceNum, Uuid[] ids)
      throws RemoteException;
  void clean(Uuid clientID, long sequenceNum, Uuid[] ids, boolean strong)
      throws RemoteException;
    }
}
TOP

Related Classes of DgcServerExposure$DgcServer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.