package timingexp;

import java.io.*;
import java.rmi.*;
import java.rmi.server.*;

// ssh
import ssh.*;
import rmi.*;

// Snowflake
import sdsi.*;
import sdsi.sexp.*;
import proof.*;
import Tools.*;

/**
 * RMI over Snowflake.
 */
public class TestRMICallSf
	extends TestRMICallSsh {

	/**
	 * Create an RMI-over-Snowflake object.
	 */
	public TestRMICallSf(SSHContext context, SDSIPrincipal serverIssuer)
		throws RemoteException {
		super(context);
		initAuthorization(serverIssuer);
	}

	/**
	 * The principal that controls this service.
	 */
	SDSIPrincipal serverIssuer=null;

	/**
	 * The tag required to be able to manipulate this service.
	 */
	Tag requestTag;

	void initAuthorization(SDSIPrincipal serverIssuer) {
		try {
			SexpList testTag
				= (new SexpList()).append("application").append("RMITest");
			SexpList sl = (new SexpList()).append("tag").append(testTag);
			this.requestTag = new Tag(sl);
			this.serverIssuer = serverIssuer;
		} catch (SexpParseException ex) {
			ex.printStackTrace();
		}
	}

	public Object requestFile(String path)
		throws RemoteException {
		checkAuth();
		return super.requestFile(path);
	}

	/**
	 * @throws the unchecked SfNeedAuthorizationException when
	 * sufficient proof of authorization has not been presented.
	 */
	void checkAuth() {
		if (serverIssuer==null) {
			throw new RuntimeException("Server unconfigured");
		}

		ssh.RSA.RSAKey k = SSHSocket.whoCalledMe();
		// wow this is going to be insanely slow.
		// Huh, I guess not -- it turns out to only be 2-3 ms;
		// apparently smashing the BigInteger refs around and
		// stripping the long one out into a SexpString just isn't
		// all that slow.
		SDSIRSAPublicKey subject = new SDSIRSAPublicKey(k);

		try {
			Proof proof = OneLineCacheRecipient.getCachedProof(subject);
			if (proof==null) {
				throw new InvalidProofException("no proof found");
			}
			proof.verify(serverIssuer, subject, requestTag);
			return;
		} catch (InvalidProofException ex) {
//			System.err.println(getClass()+": Need auth that "
//				+Prover2.staticGetName(subject)
//				+" => "
//				+Prover2.staticGetName(serverIssuer));
			throw new SfNeedAuthorizationException(serverIssuer,
				subject, requestTag, OneLineCacheRecipient.getRecipient(),
				ex.toString());
		}
	}
}
