@@ -0,0 +1,3499 @@
+package hudson.remoting;%0A%0Aimport org.junit.After;%0Aimport org.junit.Before;%0Aimport org.junit.Test;%0A%0Aimport java.io.IOException;%0Aimport java.io.ObjectInputStream;%0Aimport java.io.PrintWriter;%0Aimport java.io.Serializable;%0Aimport java.io.StringWriter;%0Aimport java.util.HashSet;%0Aimport java.util.Set;%0A%0Aimport static org.junit.Assert.*;%0A%0A/**%0A * @author Kohsuke Kawaguchi%0A */%0Apublic class ClassFilterTest implements Serializable %7B%0A%0A    /**%0A     * North can defend itself from south but not the other way around.%0A     */%0A    private transient InProcessRunner runner = new InProcessRunner() %7B%0A        @Override%0A        protected ChannelBuilder configureNorth() %7B%0A            return super.configureNorth()%0A                    .withClassFilter(new TestFilter());%0A        %7D%0A    %7D;%0A%0A    private transient Channel north, south;%0A%0A    private static class TestFilter extends ClassFilter %7B%0A        @Override%0A        protected boolean isBlacklisted(String name) %7B%0A            if (name.contains(%22Security218%22))%0A                return true;%0A            return false;%0A        %7D%0A    %7D%0A%0A    /**%0A     * Set up a channel pair where french side is well protected by british side is not.%0A     */%0A    @Before%0A    public void setUp() throws Exception %7B%0A        north = runner.start();%0A        south = runner.south;%0A        ATTACKS.clear();%0A    %7D%0A%0A    @After%0A    public void tearDown() throws Exception %7B%0A        runner.stop(north);%0A    %7D%0A%0A    @Test%0A    public void successful_defense() throws Exception %7B%0A        try %7B%0A            final Security218 a = new Security218(%22napoleon%22);%0A            south.call(new CallableBase%3CVoid, IOException%3E() %7B%0A                @Override%0A                public Void call() throws IOException %7B%0A                    a.toString();   // this will ensure 'a' gets sent over%0A                    return null;%0A                %7D%0A            %7D);%0A            fail(%22Expected call to fail%22);%0A        %7D catch (IOException e) %7B%0A            StringWriter sw = new StringWriter();%0A            PrintWriter pw = new PrintWriter(sw);%0A            e.printStackTrace(pw);%0A%0A            assertTrue(sw.toString(), sw.toString().contains(%22Rejected: %22+Security218.class.getName()));%0A            assertTrue(ATTACKS.toString(), ATTACKS.isEmpty());%0A            assertFalse(ATTACKS.contains(%22napoleon%3Enorth%22));%0A        %7D%0A    %7D%0A%0A    /**%0A     * Control case for %7B@link #successful_defense()%7D that proves that we are testing the right thing.%0A     */%0A    @Test%0A    public void successful_attack() throws Exception %7B%0A        final Security218 a = new Security218(%22caesar%22);%0A        north.call(new CallableBase%3CVoid, IOException%3E() %7B%0A            @Override%0A            public Void call() throws IOException %7B%0A                a.toString();   // this will ensure 'a' gets sent over%0A                return null;%0A            %7D%0A        %7D);%0A        assertTrue(ATTACKS.contains(%22caesar%3Esouth%22));%0A    %7D%0A%0A    /**%0A     * An attack payload that leaves a trace on the receiver side if it gets read from the stream.%0A     */%0A    static class Security218 implements Serializable %7B%0A        private final String attack;%0A%0A        public Security218(String attack) %7B%0A            this.attack = attack;%0A        %7D%0A%0A        private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException %7B%0A            ois.defaultReadObject();%0A            ATTACKS.add(attack+%22%3E%22+Channel.current().getName());%0A        %7D%0A    %7D%0A%0A    /**%0A     * Successful attacks will leave a trace here.%0A     */%0A    static Set%3CString%3E ATTACKS = new HashSet%3CString%3E();%0A%7D

Test case for UserRequest layer object serialization.