Return-Path: Delivered-To: apmail-incubator-river-dev-archive@minotaur.apache.org Received: (qmail 49393 invoked from network); 6 Feb 2011 09:00:05 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 6 Feb 2011 09:00:05 -0000 Received: (qmail 5696 invoked by uid 500); 6 Feb 2011 09:00:05 -0000 Delivered-To: apmail-incubator-river-dev-archive@incubator.apache.org Received: (qmail 5566 invoked by uid 500); 6 Feb 2011 09:00:02 -0000 Mailing-List: contact river-dev-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: river-dev@incubator.apache.org Delivered-To: mailing list river-dev@incubator.apache.org Received: (qmail 5556 invoked by uid 99); 6 Feb 2011 09:00:00 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 06 Feb 2011 09:00:00 +0000 X-ASF-Spam-Status: No, hits=0.7 required=5.0 tests=RCVD_IN_DNSWL_NONE,SPF_NEUTRAL X-Spam-Check-By: apache.org Received-SPF: neutral (nike.apache.org: local policy) Received: from [61.9.168.143] (HELO nskntmtas03p.mx.bigpond.com) (61.9.168.143) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 06 Feb 2011 08:59:50 +0000 Received: from nskntotgx02p.mx.bigpond.com ([61.9.223.241]) by nskntmtas03p.mx.bigpond.com with ESMTP id <20110206085926.TFSK24865.nskntmtas03p.mx.bigpond.com@nskntotgx02p.mx.bigpond.com> for ; Sun, 6 Feb 2011 08:59:26 +0000 Received: from [10.1.1.2] (really [61.9.223.241]) by nskntotgx02p.mx.bigpond.com with ESMTP id <20110206085925.HTRU4790.nskntotgx02p.mx.bigpond.com@[10.1.1.2]> for ; Sun, 6 Feb 2011 08:59:25 +0000 Message-ID: <4D4E6171.6090903@zeus.net.au> Date: Sun, 06 Feb 2011 18:53:05 +1000 From: Peter Firmstone User-Agent: Thunderbird 2.0.0.14 (X11/20080531) MIME-Version: 1.0 To: river-dev@incubator.apache.org Subject: Re: The internet - Proxy Isolation - Denial of Service Attack. References: <4D4D2D00.4050203@zeus.net.au> In-Reply-To: <4D4D2D00.4050203@zeus.net.au> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-RPD-ScanID: Class unknown; VirusThreatLevel unknown, RefID str=0001.0A150203.4D4E62EE.0041,ss=1,fgs=0 X-Virus-Checked: Checked by ClamAV on apache.org Notice the code below also encapsulates the codebase download too, so denials of service using large codebases, InputStream's, deserialization etc are encapsulated. This is fine for a smart proxy that implements a known service interface, but what about ServiceUI? Any thoughts? Cheers, Peter. Peter Firmstone wrote: > The following class, isolates a proxy on it's own thread and using > reflection, isolates it completely from the rest of the executing > environment, by passing method calls as tasks. > > Forgive the tab formatting. > > Cheers, > > Peter. > > /* > * 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. > */ > > package org.apache.river.impl.security.dos; > > import java.io.IOException; > import java.lang.reflect.InvocationHandler; > import java.lang.reflect.Method; > import java.util.Collection; > import java.util.concurrent.Callable; > import java.util.concurrent.ExecutionException; > import java.util.concurrent.ExecutorService; > import java.util.concurrent.Executors; > import java.util.concurrent.ThreadFactory; > import java.util.concurrent.TimeUnit; > import java.util.concurrent.TimeoutException; > import net.jini.io.MarshalledInstance; > > /** > * A preliminary experiment into Isolating a Smart Proxy. > * > * I think I'll investigate creating a Permission for additional threads > * for improved performance and also creating an event model so clients > * don't need to wait for remote method returns. I'll create a new > interface > * for this, that can be implemented by services directly too. > * > * Alternative, only maintain this data structure for as long as it takes > * to verify proxy trust, then return proxy to the client or have the > client > * thread call the smart proxy via the reflection proxy directly. > * > * REMIND: Investigate subclass method returns, this would be simple, > if the > * smart proxy is confined to it's own ClassLoader, we just check the > class > * of the object returned isn't from that ClassLoader, unless the smart > proxy > * has a ServiceAPISubclassPermission or something like that. > * > * @author Peter Firmstone > */ > public class ProxyIsolate implements InvocationHandler { > private volatile Object smartProxy; > private volatile ExecutorService proxyExecutor; > private volatile Throwable thrown; > private final long timeout; > private final TimeUnit unit; > @SuppressWarnings("unchecked") > public ProxyIsolate(MarshalledInstance proxy, > ClassLoader defaultLoader, > boolean verifyCodebaseIntegrity, > ClassLoader verifierLoader, > Collection context, > long timeout, > TimeUnit timeUnit > ) throws TimeoutException, InterruptedException, > ExecutionException{ > this.timeout = timeout; > unit = timeUnit; > thrown = null; > proxyExecutor = Executors.newSingleThreadExecutor(new Factory(this)); > UnmarshallProxyTask task = > new UnmarshallProxyTask(proxy, defaultLoader, > verifyCodebaseIntegrity, verifierLoader, context); > smartProxy = proxyExecutor.submit(task).get(timeout, timeUnit); > } > private Object taskInvoke(Object proxy, Method method, Object[] > args) throws > Exception { > String methodName = method.getName(); > if (method.getDeclaringClass() == Object.class) { > // Handle the Object public methods. > if (methodName.equals("hashCode")) { > return new Integer(System.identityHashCode(proxy)); } > else if (methodName.equals("equals")) { > return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE); > } else if (methodName.equals("toString")) { > return proxy.getClass().getName() + '@' + > Integer.toHexString(proxy.hashCode()); > } > } > return method.invoke(smartProxy, args); } > @SuppressWarnings("unchecked") > public Object invoke(Object proxy, Method method, Object[] args) > throws Throwable { > if (isTerminated()) throw new IOException(thrown); > Callable task = new MethodInvocationTask(this, proxy, method, args); > return proxyExecutor.submit(task).get(timeout, unit); > } > private void terminate(Throwable e){ > thrown = e; > smartProxy = null; > proxyExecutor.shutdown(); } > private boolean isTerminated(){ > if (smartProxy == null) return true; > return false; > } > private static class Factory implements ThreadFactory{ > private static final ThreadGroup tg = new > ThreadGroup("IsolatedProxy"); > { > tg.setDaemon(true); > tg.setMaxPriority(4); > } > private final ProxyIsolate proxy; > Factory(ProxyIsolate spi){ > proxy = spi; > } > > public Thread newThread(Runnable r) { > Thread t = new Thread(tg, r); > t.setUncaughtExceptionHandler(new ExceptionHandler(proxy)); > return t; > } } > private static class ExceptionHandler implements > Thread.UncaughtExceptionHandler{ > private final ProxyIsolate proxy; > ExceptionHandler(ProxyIsolate spi){ > proxy = spi; > } > > public void uncaughtException(Thread t, Throwable e) { > // For all other Exceptions we let the ExecutorService handle it. > if ( e instanceof Error){ > // Do we want to take different actions based on the error? > proxy.terminate(e); > } > } > } > private static class UnmarshallProxyTask implements Callable{ > private final MarshalledInstance mi; > private final ClassLoader defaultLoader; > private final boolean verifyCodebaseIntegrity; > private final ClassLoader verifierLoader; > private final Collection context; > UnmarshallProxyTask(MarshalledInstance proxy, > ClassLoader defaultLoader, > boolean verifyCodebaseIntegrity, > ClassLoader verifierLoader, > Collection context) > { > mi = proxy; > this.defaultLoader = defaultLoader; > this.verifyCodebaseIntegrity = verifyCodebaseIntegrity; > this.verifierLoader = verifierLoader; > this.context = context; > } > public Object call() throws Exception { > return mi.get(defaultLoader, verifyCodebaseIntegrity, > verifierLoader, context); > } > } > private static class MethodInvocationTask implements Callable { > private final ProxyIsolate smartProxy; > private final Object proxy; > private final Method method; > private final Object[] args; > MethodInvocationTask(ProxyIsolate target, Object proxy, Method > method, Object[] args){ > smartProxy = target; > this.proxy = proxy; > this.method = method; > this.args = args; } > public Object call() throws Exception { > return smartProxy.taskInvoke(proxy, method, args); > } > } > > } > >