airavata-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ami...@apache.org
Subject svn commit: r1512378 [4/5] - in /airavata/sandbox/gsissh: ./ .idea/ .idea/copyright/ .idea/scopes/ jglobus-repo/ jglobus-repo/repository/ jglobus-repo/repository/org/ jglobus-repo/repository/org/jglobus/ jglobus-repo/repository/org/jglobus/axisg/ jglob...
Date Fri, 09 Aug 2013 16:24:10 GMT
Added: airavata/sandbox/gsissh/src/main/java/edu/illinois/ncsa/BCGSS/BCGSSContextImpl.java
URL: http://svn.apache.org/viewvc/airavata/sandbox/gsissh/src/main/java/edu/illinois/ncsa/BCGSS/BCGSSContextImpl.java?rev=1512378&view=auto
==============================================================================
--- airavata/sandbox/gsissh/src/main/java/edu/illinois/ncsa/BCGSS/BCGSSContextImpl.java (added)
+++ airavata/sandbox/gsissh/src/main/java/edu/illinois/ncsa/BCGSS/BCGSSContextImpl.java Fri Aug  9 16:24:07 2013
@@ -0,0 +1,1426 @@
+package edu.illinois.ncsa.BCGSS;
+
+import org.bouncycastle.jce.provider.X509CertificateObject;
+import org.globus.gsi.*;
+import org.globus.gsi.bc.*;
+import org.globus.gsi.gssapi.*;
+import org.globus.gsi.util.*;
+import org.gridforum.jgss.*;
+import org.ietf.jgss.*;
+import org.ietf.jgss.Oid;
+import sun.reflect.generics.reflectiveObjects.NotImplementedException;
+
+import java.io.*;
+import java.security.*;
+import java.security.cert.*;
+import java.security.cert.Certificate;
+import java.util.*;
+
+public class BCGSSContextImpl implements ExtendedGSSContext {
+    /**
+     * Used to distinguish between a token created by
+     * <code>wrap</code> with {@link GSSConstants#GSI_BIG
+     * GSSConstants.GSI_BIG}
+     * QoP and a regular token created by <code>wrap</code>.
+     */
+    public static final int GSI_WRAP = 26;
+    /**
+     * SSL3_RT_GSSAPI_OPENSSL
+     */
+
+    private static final int GSI_SEQUENCE_SIZE = 8;
+
+    private static final int GSI_MESSAGE_DIGEST_PADDING = 12;
+
+    private static final byte[] SSLHANDSHAKE_PAD_1 = {0x36};
+
+    private static final String[] NO_ENCRYPTION = {"SSL_RSA_WITH_NULL_MD5"};
+
+    private static final String[] ENABLED_PROTOCOLS = {"TLSv1", "SSLv3"};
+
+    private static final byte[] DELEGATION_TOKEN =
+            new byte[]{GSIConstants.DELEGATION_CHAR};
+
+    /**
+     * Handshake state
+     */
+    protected int state = HANDSHAKE;
+
+    /* handshake states */
+    private static final int
+            HANDSHAKE = 0,
+            CLIENT_START_DEL = 2,
+            CLIENT_END_DEL = 3,
+            SERVER_START_DEL = 4,
+            SERVER_END_DEL = 5;
+
+    /**
+     * Delegation state
+     */
+    protected int delegationState = DELEGATION_START;
+
+    /* delegation states */
+    private static final int
+            DELEGATION_START = 0,
+            DELEGATION_SIGN_CERT = 1,
+            DELEGATION_COMPLETE_CRED = 2;
+
+    /**
+     * Delegation finished indicator
+     */
+    protected boolean delegationFinished = false;
+
+    // gss context state variables
+    protected boolean credentialDelegation = false;
+    protected boolean anonymity = false;
+    protected boolean encryption = false;
+    protected boolean established = false;
+
+    /**
+     * The name of the context initiator
+     */
+    protected GSSName sourceName = null;
+
+    /**
+     * The name of the context acceptor
+     */
+    protected GSSName targetName = null;
+
+    // these can be set via setOption
+    protected GSIConstants.DelegationType delegationType =
+            GSIConstants.DelegationType.LIMITED;
+    protected Integer gssMode = GSIConstants.MODE_GSI;
+    protected Boolean checkContextExpiration = Boolean.FALSE;
+    protected Boolean rejectLimitedProxy = Boolean.FALSE;
+    protected Boolean requireClientAuth = Boolean.TRUE;
+    protected Boolean acceptNoClientCerts = Boolean.FALSE;
+    protected Boolean requireAuthzWithDelegation = Boolean.TRUE;
+
+    // *** implementation-specific variables ***
+
+    /**
+     * Credential of this context. Might be anonymous
+     */
+    protected GlobusGSSCredentialImpl ctxCred;
+
+    /**
+     * Expected target name. Used for authorization in initiator
+     */
+    protected GSSName expectedTargetName = null;
+
+    /**
+     * Context expiration date.
+     */
+    protected Date goodUntil = null;
+
+    protected boolean conn = false;
+
+    protected BouncyCastleCertProcessingFactory certFactory;
+
+    protected Map proxyPolicyHandlers;
+
+    /**
+     * Limited peer credentials
+     */
+    protected Boolean peerLimited = null;
+
+    private TlsHandlerUtil tlsHU = null;
+    private GlobusTlsClient tlsClient = null;
+    private GlobusTlsCipherFactory cipherFactory = null;
+
+    /**
+     *
+     * @param target
+     * @param cred
+     * @throws org.ietf.jgss.GSSException
+     */
+    public BCGSSContextImpl(GSSName target, GlobusGSSCredentialImpl cred)
+            throws GSSException {
+        if (cred == null) {
+            throw new GSSException(GSSException.NO_CRED);
+        }
+
+        this.expectedTargetName = target;
+        this.ctxCred = cred;
+    }
+
+    /**
+     *
+     * @throws org.globus.gsi.gssapi.GlobusGSSException
+     */
+    private void init() throws GlobusGSSException {
+        this.certFactory = BouncyCastleCertProcessingFactory.getDefault();
+        this.state = HANDSHAKE;
+
+
+        try {
+            this.cipherFactory = new GlobusTlsCipherFactory();
+            this.tlsClient =
+                    new GlobusTlsClient(this.ctxCred.getX509Credential(),
+                                        this.cipherFactory);
+        } catch (Exception e) {
+            throw new GlobusGSSException(GSSException.FAILURE, e);
+        }
+
+        // TODO: set enabled cipher suites in client?
+        // TODO: enable null encryption ciphers on user request?
+
+        /*
+       TlsProtocolVersion[] tlsVersion =
+            new TlsProtocolVersion[] {TlsProtocolVersion.TLSv10,
+                                      TlsProtocolVersion.SSLv3};
+                                      */
+            //new TlsProtocolVersion[] {TlsProtocolVersion.TLSv10};
+            //new TlsProtocolVersion[] {TlsProtocolVersion.SSLv3};
+
+       //this.tlsHU = new TlsHandlerUtil(this.tlsClient, tlsVersion);
+        this.tlsHU = new TlsHandlerUtil(this.tlsClient);
+    }
+
+    /**
+     *
+     * @param cert
+     * @return
+     * @throws GSSException
+     */
+    private X509Certificate bcConvert(X509Certificate cert)
+            throws GSSException {
+        if (!(cert instanceof X509CertificateObject)) {
+            try {
+                return CertificateLoadUtil.loadCertificate(new ByteArrayInputStream(cert.getEncoded()));
+            } catch (Exception e) {
+                throw new GlobusGSSException(GSSException.FAILURE, e);
+            }
+        } else {
+            return cert;
+        }
+    }
+
+    private void handshakeFinished()
+            throws IOException {
+        //TODO: enable encryption depending on cipher suite decided in handshake
+        this.encryption = true;
+        //System.out.println("encryption alg: " + cs);
+    }
+
+    /**
+     *
+     */
+    private void setDone() {
+        this.established = true;
+    }
+
+    /**
+     *
+     * @param date
+     */
+    private void setGoodUntil(Date date) {
+        if (this.goodUntil == null) {
+            this.goodUntil = date;
+        } else if (date.before(this.goodUntil)) {
+            this.goodUntil = date;
+        }
+    }
+
+    /**
+     *
+     * @throws GSSException
+     */
+    protected void checkContext()
+            throws GSSException {
+        if (!this.conn || !isEstablished()) {
+            throw new GSSException(GSSException.NO_CONTEXT);
+        }
+
+        if (this.checkContextExpiration && getLifetime() <= 0) {
+            throw new GSSException(GSSException.CONTEXT_EXPIRED);
+        }
+    }
+
+    /**
+     *
+     * @param value
+     * @throws GSSException
+     */
+    protected void setGssMode(Object value)
+            throws GSSException {
+        if (!(value instanceof Integer)) {
+            throw new GlobusGSSException(GSSException.FAILURE,
+                    GlobusGSSException.BAD_OPTION_TYPE,
+                    "badType",
+                    new Object[]{"GSS mode", Integer.class});
+        }
+        Integer v = (Integer) value;
+        if (v.equals(GSIConstants.MODE_GSI) ||
+                v.equals(GSIConstants.MODE_SSL)) {
+            this.gssMode = v;
+        } else {
+            throw new GlobusGSSException(GSSException.FAILURE,
+                    GlobusGSSException.BAD_OPTION,
+                    "badGssMode");
+        }
+    }
+
+    /**
+     *
+     * @param value
+     * @throws GSSException
+     */
+    protected void setDelegationType(Object value)
+            throws GSSException {
+        GSIConstants.DelegationType v;
+        if (value instanceof GSIConstants.DelegationType)
+            v = (GSIConstants.DelegationType) value;
+        else if (value instanceof Integer) {
+            v = GSIConstants.DelegationType.get(((Integer) value).intValue());
+        } else {
+            throw new GlobusGSSException(GSSException.FAILURE,
+                    GlobusGSSException.BAD_OPTION_TYPE,
+                    "badType",
+                    new Object[]{"delegation type",
+                            GSIConstants.DelegationType.class});
+        }
+        if (v == GSIConstants.DelegationType.FULL ||
+                v == GSIConstants.DelegationType.LIMITED) {
+            this.delegationType = v;
+        } else {
+            throw new GlobusGSSException(GSSException.FAILURE,
+                    GlobusGSSException.BAD_OPTION,
+                    "badDelegType");
+        }
+    }
+
+    /**
+     *
+     * @param value
+     * @throws GSSException
+     */
+    protected void setCheckContextExpired(Object value)
+            throws GSSException {
+        if (!(value instanceof Boolean)) {
+            throw new GlobusGSSException(GSSException.FAILURE,
+                    GlobusGSSException.BAD_OPTION_TYPE,
+                    "badType",
+                    new Object[]{"check context expired", Boolean.class});
+        }
+        this.checkContextExpiration = (Boolean) value;
+    }
+
+    /**
+     *
+     * @param value
+     * @throws GSSException
+     */
+    protected void setRejectLimitedProxy(Object value)
+            throws GSSException {
+        if (!(value instanceof Boolean)) {
+            throw new GlobusGSSException(GSSException.FAILURE,
+                    GlobusGSSException.BAD_OPTION_TYPE,
+                    "badType",
+                    new Object[]{"reject limited proxy", Boolean.class});
+        }
+        this.rejectLimitedProxy = (Boolean) value;
+    }
+
+    /**
+     *
+     * @param value
+     * @throws GSSException
+     */
+    protected void setRequireClientAuth(Object value)
+            throws GSSException {
+        if (!(value instanceof Boolean)) {
+            throw new GlobusGSSException(GSSException.FAILURE,
+                    GlobusGSSException.BAD_OPTION_TYPE,
+                    "badType",
+                    new Object[]{"require client auth", Boolean.class});
+        }
+        this.requireClientAuth = (Boolean) value;
+    }
+
+    /**
+     *
+     * @param value
+     * @throws GSSException
+     */
+    protected void setRequireAuthzWithDelegation(Object value)
+            throws GSSException {
+
+        if (!(value instanceof Boolean)) {
+            throw new GlobusGSSException(GSSException.FAILURE,
+                    GlobusGSSException.BAD_OPTION_TYPE,
+                    "badType",
+                    new Object[]{"require authz with delehation",
+                            Boolean.class});
+        }
+        this.requireAuthzWithDelegation = (Boolean) value;
+    }
+
+    /**
+     *
+     * @param value
+     * @throws GSSException
+     */
+    protected void setAcceptNoClientCerts(Object value)
+            throws GSSException {
+        if (!(value instanceof Boolean)) {
+            throw new GlobusGSSException(GSSException.FAILURE,
+                    GlobusGSSException.BAD_OPTION_TYPE,
+                    "badType",
+                    new Object[]{"accept no client certs", Boolean.class});
+        }
+        this.acceptNoClientCerts = (Boolean) value;
+    }
+
+    /**
+     *
+     * @param value
+     * @throws GSSException
+     */
+    protected void setProxyPolicyHandlers(Object value)
+            throws GSSException {
+        if (!(value instanceof Map)) {
+            throw new GlobusGSSException(GSSException.FAILURE,
+                    GlobusGSSException.BAD_OPTION_TYPE,
+                    "badType",
+                    new Object[]{"Proxy policy handlers",
+                            Map.class});
+        }
+        this.proxyPolicyHandlers = (Map) value;
+    }
+
+    /////////////////////////////////////////////////////////////////////
+    /////////////////////////////////////////////////////////////////////
+    /////////////////////////////////////////////////////////////////////
+
+    // Methods below are part of the (Extended)GSSContext implementation
+
+    /////////////////////////////////////////////////////////////////////
+    /////////////////////////////////////////////////////////////////////
+    /////////////////////////////////////////////////////////////////////
+
+    /**
+     *
+     * @param option
+     *        option type.
+     * @param value
+     *        option value.
+     * @throws GSSException
+     */
+    public void setOption(Oid option, Object value) throws GSSException {
+        if (option == null) {
+            throw new GlobusGSSException(GSSException.FAILURE,
+                    GlobusGSSException.BAD_ARGUMENT,
+                    "nullOption");
+        }
+        if (value == null) {
+            throw new GlobusGSSException(GSSException.FAILURE,
+                    GlobusGSSException.BAD_ARGUMENT,
+                    "nullOptionValue");
+        }
+
+        if (option.equals(GSSConstants.GSS_MODE)) {
+            setGssMode(value);
+        } else if (option.equals(GSSConstants.DELEGATION_TYPE)) {
+            setDelegationType(value);
+        } else if (option.equals(GSSConstants.CHECK_CONTEXT_EXPIRATION)) {
+            setCheckContextExpired(value);
+        } else if (option.equals(GSSConstants.REJECT_LIMITED_PROXY)) {
+            setRejectLimitedProxy(value);
+        } else if (option.equals(GSSConstants.REQUIRE_CLIENT_AUTH)) {
+            setRequireClientAuth(value);
+        } else if (option.equals(GSSConstants.TRUSTED_CERTIFICATES)) {
+            // setTrustedCertificates(value);
+            throw new GSSException(GSSException.UNAVAILABLE);
+        } else if (option.equals(GSSConstants.PROXY_POLICY_HANDLERS)) {
+            setProxyPolicyHandlers(value);
+        } else if (option.equals(GSSConstants.ACCEPT_NO_CLIENT_CERTS)) {
+            setAcceptNoClientCerts(value);
+        } else if (option.equals(GSSConstants
+                .AUTHZ_REQUIRED_WITH_DELEGATION)) {
+            setRequireAuthzWithDelegation(value);
+        } else {
+            throw new GlobusGSSException(GSSException.FAILURE,
+                    GlobusGSSException.UNKNOWN_OPTION,
+                    "unknownOption",
+                    new Object[]{option});
+        }
+    }
+
+    /**
+     *
+     * @param option
+     * @return
+     * @throws GSSException
+     */
+    public Object getOption(Oid option) throws GSSException {
+        if (option == null) {
+            throw new GlobusGSSException(GSSException.FAILURE,
+                    GlobusGSSException.BAD_ARGUMENT,
+                    "nullOption");
+        }
+
+        if (option.equals(GSSConstants.GSS_MODE)) {
+            return this.gssMode;
+        } else if (option.equals(GSSConstants.DELEGATION_TYPE)) {
+            return this.delegationType;
+        } else if (option.equals(GSSConstants.CHECK_CONTEXT_EXPIRATION)) {
+            return this.checkContextExpiration;
+        } else if (option.equals(GSSConstants.REJECT_LIMITED_PROXY)) {
+            return this.rejectLimitedProxy;
+        } else if (option.equals(GSSConstants.REQUIRE_CLIENT_AUTH)) {
+            return this.requireClientAuth;
+        } else if (option.equals(GSSConstants.TRUSTED_CERTIFICATES)) {
+            // return this.tc;
+            throw new GSSException(GSSException.UNAVAILABLE);
+        } else if (option.equals(GSSConstants.PROXY_POLICY_HANDLERS)) {
+            // return this.proxyPolicyHandlers;
+            throw new GSSException(GSSException.UNAVAILABLE);
+        } else if (option.equals(GSSConstants.ACCEPT_NO_CLIENT_CERTS)) {
+            return this.acceptNoClientCerts;
+        }
+
+        return null;
+    }
+
+    /**
+     * Initiate the delegation of a credential.
+     *
+     * This function drives the initiating side of the credential
+     * delegation process. It is expected to be called in tandem with the
+     * {@link #acceptDelegation(int, byte[], int, int) acceptDelegation}
+     * function.
+     * <BR>
+     * The behavior of this function can be modified by
+     * {@link GSSConstants#DELEGATION_TYPE GSSConstants.DELEGATION_TYPE}
+     * and
+     * {@link GSSConstants#GSS_MODE GSSConstants.GSS_MODE} context
+     * options.
+     * The {@link GSSConstants#DELEGATION_TYPE GSSConstants.DELEGATION_TYPE}
+     * option controls delegation type to be performed. The
+     * {@link GSSConstants#GSS_MODE GSSConstants.GSS_MODE}
+     * option if set to
+     * {@link org.globus.gsi.GSIConstants#MODE_SSL GSIConstants.MODE_SSL}
+     * results in tokens that are not wrapped.
+     *
+     * @param credential
+     *        The credential to be delegated. May be null
+     *        in which case the credential associated with the security
+     *        context is used.
+     * @param mechanism
+     *        The desired security mechanism. May be null.
+     * @param lifetime
+     *        The requested period of validity (seconds) of the delegated
+     *        credential.
+     * @return A token that should be passed to <code>acceptDelegation</code> if
+     *         <code>isDelegationFinished</code> returns false. May be null.
+     * @exception GSSException containing the following major error codes:
+     *            <code>GSSException.FAILURE</code>
+     */
+    public byte[] initDelegation(GSSCredential credential, Oid mechanism,
+                                 int lifetime, byte[] buf, int off, int len)
+            throws GSSException {
+        //TODO: implement this
+        return new byte[0];
+    }
+
+    /*
+     *  acceptDelegation unimplemented
+     */
+    public byte[] acceptDelegation(int i, byte[] bytes, int i1, int i2)
+            throws GSSException {
+        throw new GSSException(GSSException.UNAVAILABLE);
+    }
+
+    /*
+        getDelegatedCredential unimplemented (would be set by acceptDelegation)
+     */
+    public GSSCredential getDelegatedCredential() {
+        return null;
+    }
+
+    /**
+     *
+     * @return
+     */
+    public boolean isDelegationFinished() {
+        return this.delegationFinished;
+    }
+
+    /**
+     * Retrieves arbitrary data about this context.
+     * Currently supported oid: <UL>
+     * <LI>
+     * {@link GSSConstants#X509_CERT_CHAIN GSSConstants.X509_CERT_CHAIN}
+     * returns certificate chain of the peer (<code>X509Certificate[]</code>).
+     * </LI>
+     * </UL>
+     *
+     * @param oid the oid of the information desired.
+     * @return the information desired. Might be null.
+     * @exception GSSException containing the following major error codes:
+     *            <code>GSSException.FAILURE</code>
+     */
+    public Object inquireByOid(Oid oid) throws GSSException {
+        if (oid == null) {
+            throw new GlobusGSSException(GSSException.FAILURE,
+                    GlobusGSSException.BAD_ARGUMENT,
+                    "nullOption");
+        }
+
+        if (oid.equals(GSSConstants.X509_CERT_CHAIN)) {
+            if (isEstablished()) {
+                // converting certs is slower but keeping converted certs
+                // takes lots of memory.
+                try {
+                    Certificate[] peerCerts;
+                    //TODO:  used to get this from
+                    //  SSLEngine.getSession().getPeerCertificates()
+                    peerCerts = null;
+                    if (peerCerts != null && peerCerts.length > 0) {
+                        return (X509Certificate[]) peerCerts;
+                    } else {
+                        return null;
+                    }
+                } catch (Exception e) {
+                    throw new GlobusGSSException(
+                            GSSException.DEFECTIVE_CREDENTIAL,
+                            e
+                    );
+                }
+            }
+        } else if (oid.equals(GSSConstants.RECEIVED_LIMITED_PROXY)) {
+            return this.peerLimited;
+        }
+
+        return null;
+    }
+
+    public void setBannedCiphers(String[] strings) {
+        //To change body of implemented methods use File | Settings | File Templates.
+        throw new NotImplementedException();
+    }
+
+    /**
+     * This function drives the initiating side of the context establishment
+     * process. It is expected to be called in tandem with the
+     * {@link #acceptSecContext(byte[], int, int) acceptSecContext} function.
+     * <BR>
+     * The behavior of context establishment process can be modified by
+     * {@link GSSConstants#GSS_MODE GSSConstants.GSS_MODE},
+     * {@link GSSConstants#DELEGATION_TYPE GSSConstants.DELEGATION_TYPE}, and
+     * {@link GSSConstants#REJECT_LIMITED_PROXY GSSConstants.REJECT_LIMITED_PROXY}
+     * context options. If the {@link GSSConstants#GSS_MODE GSSConstants.GSS_MODE}
+     * option is set to
+     * {@link org.globus.gsi.GSIConstants#MODE_SSL GSIConstants.MODE_SSL}
+     * the context establishment process will be compatible with regular SSL
+     * (no credential delegation support). If the option is set to
+     * {@link org.globus.gsi.GSIConstants#MODE_GSI GSIConstants.GSS_MODE_GSI}
+     * credential delegation during context establishment process will performed.
+     * The delegation type to be performed can be set using the
+     * {@link GSSConstants#DELEGATION_TYPE GSSConstants.DELEGATION_TYPE}
+     * context option. If the {@link GSSConstants#REJECT_LIMITED_PROXY
+     * GSSConstants.REJECT_LIMITED_PROXY} option is enabled,
+     * a peer presenting limited proxy credential will be automatically
+     * rejected and the context establishment process will be aborted.
+     *
+     * @return a byte[] containing the token to be sent to the peer.
+     *         null indicates that no token is generated (needs more data).
+     */
+    public byte[] initSecContext(byte[] inBuff, int off, int len)
+            throws GSSException {
+
+        if (!this.conn) {
+            //System.out.println("enter initializing in initSecContext");
+            if (this.credentialDelegation) {
+                if (this.gssMode.equals(GSIConstants.MODE_SSL)) {
+                    throw new GlobusGSSException(GSSException.FAILURE,
+                            GlobusGSSException.BAD_ARGUMENT,
+                            "initCtx00");
+                }
+                if (this.anonymity) {
+                    throw new GlobusGSSException(GSSException.FAILURE,
+                            GlobusGSSException.BAD_ARGUMENT,
+                            "initCtx01");
+                }
+            }
+
+            if (this.anonymity || this.ctxCred.getName().isAnonymous()) {
+                this.anonymity = true;
+            } else {
+                this.anonymity = false;
+
+                if (ctxCred.getUsage() != GSSCredential.INITIATE_ONLY &&
+                    ctxCred.getUsage() != GSSCredential.INITIATE_AND_ACCEPT) {
+                    throw new GlobusGSSException(
+                            GSSException.DEFECTIVE_CREDENTIAL,
+                            GlobusGSSException.UNKNOWN,
+                            "badCredUsage");
+                }
+            }
+
+            init();
+
+            this.conn = true;
+        }
+
+        // Unless explicitly disabled, check if delegation is
+        // requested and expected target is null
+        if (!Boolean.FALSE.equals(this.requireAuthzWithDelegation)) {
+
+            if (this.expectedTargetName == null &&
+                    this.credentialDelegation) {
+                throw new GlobusGSSException(GSSException.FAILURE,
+                        GlobusGSSException.BAD_ARGUMENT,
+                        "initCtx02");
+            }
+        }
+
+        byte[] returnToken = null;
+
+        switch (state) {
+            case HANDSHAKE:
+                try {
+                    returnToken = this.tlsHU.nextHandshakeToken(inBuff);
+
+                    if (this.tlsHU.isHandshakeFinished()) {
+                        //System.out.println("initSecContext handshake finished");
+                        handshakeFinished(); // just enable encryption
+
+                        Certificate[] chain = this.tlsClient.getPeerCerts();
+                        if (!(chain instanceof X509Certificate[])) {
+                            throw new Exception(
+                               "Certificate chain not of type X509Certificate");
+                        }
+
+                        for (X509Certificate cert : (X509Certificate[]) chain) {
+                            setGoodUntil(cert.getNotAfter());
+                        }
+
+                        String identity = BouncyCastleUtil.getIdentity(
+                                bcConvert(
+                                        BouncyCastleUtil.getIdentityCertificate(
+                                                (X509Certificate[]) chain)));
+                        this.targetName =
+                                new GlobusGSSName(CertificateUtil.toGlobusID(
+                                        identity, false));
+
+                        this.peerLimited = ProxyCertificateUtil.isLimitedProxy(
+                                BouncyCastleUtil.getCertificateType(
+                                        (X509Certificate) chain[0]));
+
+                        // initiator
+                        if (this.anonymity) {
+                            this.sourceName = new GlobusGSSName();
+                        } else {
+                            for (X509Certificate cert :
+                                    ctxCred.getCertificateChain()) {
+                                setGoodUntil(cert.getNotAfter());
+                            }
+                            this.sourceName = this.ctxCred.getName();
+                        }
+
+                        // mutual authentication test
+                        if (this.expectedTargetName != null &&
+                           !this.expectedTargetName.equals(this.targetName)) {
+                            throw new GlobusGSSException(
+                                    GSSException.UNAUTHORIZED,
+                                    GlobusGSSException.BAD_NAME,
+                                    "authFailed00",
+                                    new Object[]{this.expectedTargetName,
+                                            this.targetName});
+                        }
+
+                        if (this.gssMode.equals(GSIConstants.MODE_GSI)) {
+                            this.state = CLIENT_START_DEL;
+                            // if there is a token to return then break
+                            // otherwise we fall through to delegation
+                            if (returnToken != null && returnToken.length > 0) {
+                                break;
+                            }
+                        } else {
+                            setDone();
+                            break;
+                        }
+
+                    } else { // handshake not complete yet
+                        break;
+                    }
+                } catch (IOException e) {
+                    throw new GlobusGSSException(GSSException.FAILURE, e);
+                } catch (Exception e) {
+                    throw new GlobusGSSException(GSSException.FAILURE, e);
+                }
+
+            case CLIENT_START_DEL:
+
+                // sanity check - might be invalid state
+                if (this.state != CLIENT_START_DEL ||
+                        (returnToken != null && returnToken.length > 0) ) {
+                    throw new GSSException(GSSException.FAILURE);
+                }
+
+                try {
+                    String deleg;
+
+                    if (getCredDelegState()) {
+                        deleg = Character.toString(
+                                GSIConstants.DELEGATION_CHAR);
+                        this.state = CLIENT_END_DEL;
+                    } else {
+                        deleg = Character.toString('0');
+                        setDone();
+                    }
+
+                    // TODO: Force ASCII encoding?
+                    byte[] a = deleg.getBytes();
+                    // SSL wrap the delegation token
+                    returnToken = this.tlsHU.wrap(a);
+                } catch (Exception e) {
+                    throw new GlobusGSSException(GSSException.FAILURE, e);
+                }
+
+                break;
+
+            case CLIENT_END_DEL:
+
+                if (inBuff == null || inBuff.length == 0) {
+                    throw new GSSException(GSSException.DEFECTIVE_TOKEN);
+                }
+
+                try {
+                    // SSL unwrap the token on the inBuff (it's a CSR)
+                    byte[] certReq = this.tlsHU.unwrap(inBuff);
+
+                    if (certReq.length == 0) break;
+
+                    X509Certificate[] chain =
+                            this.ctxCred.getCertificateChain();
+
+                    X509Certificate cert = this.certFactory.createCertificate(
+                            new ByteArrayInputStream(certReq),
+                            chain[0],
+                            this.ctxCred.getPrivateKey(),
+                            -1,
+                            BouncyCastleCertProcessingFactory.decideProxyType(
+                                    chain[0], this.delegationType));
+
+                    byte[] enc = cert.getEncoded();
+                    // SSL wrap the encoded cert and return that buffer
+                    returnToken = this.tlsHU.wrap(enc);
+                    setDone();
+                } catch (GeneralSecurityException e) {
+                    throw new GlobusGSSException(GSSException.FAILURE, e);
+                } catch (IOException e) {
+                    throw new GlobusGSSException(GSSException.FAILURE, e);
+                }
+
+                break;
+
+            default:
+                throw new GSSException(GSSException.FAILURE);
+        }
+
+        //TODO: Why is there a check for CLIENT_START_DEL?
+        if (returnToken != null && returnToken.length > 0 ||
+            this.state == CLIENT_START_DEL) {
+            return returnToken;
+        } else
+            return null;
+    }
+
+    /**
+     * It works just like
+     * {@link #initSecContext(byte[], int, int) initSecContext} method.
+     * It reads one SSL token from input stream, calls
+     * {@link #initSecContext(byte[], int, int) acceptSecContext} method and
+     * writes the output token to the output stream (if any)
+     * SSL token is not read on the initial call.
+     */
+    public int initSecContext(InputStream in, OutputStream out)
+            throws GSSException {
+        byte[] inToken = null;
+        try {
+            if (!this.conn) {
+                inToken = new byte[0];
+            } else {
+                inToken = SSLUtil.readSslMessage(in);
+            }
+            byte[] outToken = initSecContext(inToken, 0, inToken.length);
+            if (outToken != null) {
+                out.write(outToken);
+                return outToken.length;
+            } else {
+                return 0;
+            }
+        } catch (IOException e) {
+            throw new GlobusGSSException(GSSException.FAILURE, e);
+        }
+    }
+
+    /*
+        acceptSecContext not implemented
+     */
+    public byte[] acceptSecContext(byte[] bytes, int i, int i1)
+            throws GSSException {
+        throw new GSSException(GSSException.UNAVAILABLE);
+    }
+
+    /*
+        acceptSecContext not implemented
+     */
+    public void acceptSecContext(InputStream in, OutputStream out)
+            throws GSSException {
+        throw new GSSException(GSSException.UNAVAILABLE);
+    }
+
+    /**
+     *
+     * @return
+     */
+    public boolean isEstablished() {
+        return this.established;
+    }
+
+    /**
+     *
+     * @throws GSSException
+     */
+    public void dispose() throws GSSException {
+        // does nothing
+    }
+
+    /*
+        getWrapSizeLimit unimplemented
+     */
+    public int getWrapSizeLimit(int i, boolean b, int i1) throws GSSException {
+        throw new GSSException(GSSException.UNAVAILABLE);
+    }
+
+
+    /**
+     * Wraps a message for integrity and protection.
+     * Returns a GSI-wrapped token when privacy is not requested and
+     * QOP requested is set to
+     * {@link GSSConstants#GSI_BIG GSSConstants.GSI_BIG}. Otherwise
+     * a regular SSL-wrapped token is returned.
+     */
+    public byte[] wrap(byte[] inBuf, int off, int len, MessageProp prop)
+            throws GSSException {
+        checkContext();
+
+        byte[] token = null;
+        boolean doGSIWrap = false;
+
+        if (prop != null) {
+            if (prop.getQOP() != 0 && prop.getQOP() != GSSConstants.GSI_BIG) {
+                throw new GSSException(GSSException.BAD_QOP);
+            }
+            doGSIWrap = (!prop.getPrivacy() &&
+                    prop.getQOP() == GSSConstants.GSI_BIG);
+        }
+
+        if (doGSIWrap) {
+            throw new GSSException(GSSException.UNAVAILABLE);
+        } else {
+            try {
+                token = this.tlsHU.wrap(inBuf, off, len);
+            } catch (IOException e) {
+                throw new GlobusGSSException(GSSException.FAILURE, e);
+            }
+
+            if (prop != null) {
+                prop.setPrivacy(this.encryption);
+                prop.setQOP(0);
+            }
+        }
+
+        return token;
+    }
+
+    /*
+        wrap(InputStream, OutputStream) unimplemented
+     */
+    public void wrap(InputStream in, OutputStream out, MessageProp msgProp)
+            throws GSSException {
+        throw new GSSException(GSSException.UNAVAILABLE);
+    }
+
+    /**
+     * Unwraps a token generated by <code>wrap</code> method on the other side
+     * of the context.  The input token can either be a regular SSL-wrapped
+     * token or GSI-wrapped token. Upon return from the method the
+     * <code>MessageProp</code> object will contain the applied QOP and privacy
+     * state of the message. In case of GSI-wrapped token the applied QOP will
+     * be set to {@link GSSConstants#GSI_BIG GSSConstants.GSI_BIG}
+     */
+    public byte[] unwrap(byte[] inBuf, int off, int len, MessageProp prop)
+            throws GSSException {
+        checkContext();
+
+        byte[] token = null;
+
+        /*
+         * see if the token is a straight SSL packet or
+         * one of ours made by wrap using get_mic
+         */
+        if (inBuf[off] == GSI_WRAP &&
+                inBuf[off + 1] == 3 &&
+                inBuf[off + 2] == 0) {
+            throw new GSSException(GSSException.UNAVAILABLE);
+        } else {
+            try {
+                token = this.tlsHU.unwrap(inBuf, off, len);
+            } catch (IOException e) {
+                throw new GlobusGSSException(GSSException.FAILURE, e);
+            }
+
+            if (prop != null) {
+                prop.setPrivacy(this.encryption);
+                prop.setQOP(0);
+            }
+        }
+
+        return token;
+    }
+
+    /*
+        unwrap(InputStream, OutputStream) unimplemented
+     */
+    public void unwrap(InputStream in, OutputStream out, MessageProp msgProp)
+            throws GSSException {
+        throw new GSSException(GSSException.UNAVAILABLE);
+    }
+
+    /**
+     *
+     * @param inBuf
+     * @param off
+     * @param len
+     * @param prop
+     * @return
+     * @throws GSSException
+     */
+    public byte[] getMIC(byte[] inBuf, int off, int len, MessageProp prop)
+            throws GSSException {
+        checkContext();
+
+        if (prop != null && (prop.getQOP() != 0 || prop.getPrivacy())) {
+            throw new GSSException(GSSException.BAD_QOP);
+        }
+
+        long sequence = this.cipherFactory.getTlsBlockCipher().getWriteMac()
+                .getSequenceNumber();
+
+        int md_size = this.cipherFactory.getDigest().getDigestSize();
+
+        byte[] mic = new byte[GSI_MESSAGE_DIGEST_PADDING + md_size];
+
+        System.arraycopy(toBytes(sequence), 0, mic, 0, GSI_SEQUENCE_SIZE);
+        System.arraycopy(toBytes(len, 4), 0, mic, GSI_SEQUENCE_SIZE, 4);
+
+        this.cipherFactory.getTlsBlockCipher().getWriteMac().incSequence();
+
+        int pad_ct = (48 / md_size) * md_size;
+
+        try {
+            MessageDigest md = MessageDigest.getInstance(
+                    this.cipherFactory.getDigest().getAlgorithmName());
+
+            md.update(this.cipherFactory.getTlsBlockCipher().getWriteMac()
+                    .getMACSecret());
+            for (int i = 0; i < pad_ct; i++) {
+                md.update(SSLHANDSHAKE_PAD_1);
+            }
+            md.update(mic, 0, GSI_MESSAGE_DIGEST_PADDING);
+            md.update(inBuf, off, len);
+
+            byte[] digest = md.digest();
+
+            System.arraycopy(digest, 0, mic, GSI_MESSAGE_DIGEST_PADDING, digest.length);
+        } catch (NoSuchAlgorithmException e) {
+            throw new GlobusGSSException(GSSException.FAILURE, e);
+        }
+
+        if (prop != null) {
+            prop.setPrivacy(false);
+            prop.setQOP(0);
+        }
+
+        return mic;
+    }
+
+    /*
+        getMIC(InputStream, OutputStream) unimplemented
+     */
+    public void getMIC(InputStream in, OutputStream out, MessageProp msgProp)
+            throws GSSException {
+        throw new GSSException(GSSException.UNAVAILABLE);
+    }
+
+    /**
+     *
+     * @param inTok
+     * @param tokOff
+     * @param tokLen
+     * @param inMsg
+     * @param msgOff
+     * @param msgLen
+     * @param prop
+     * @throws GSSException
+     */
+    public void verifyMIC(byte[] inTok, int tokOff, int tokLen,
+                          byte[] inMsg, int msgOff, int msgLen,
+                          MessageProp prop) throws GSSException {
+                checkContext();
+
+        String digestAlg = this.cipherFactory.getDigest().getAlgorithmName();
+        int md_size = this.cipherFactory.getDigest().getDigestSize();
+
+        if (tokLen != (GSI_MESSAGE_DIGEST_PADDING + md_size)) {
+            throw new GlobusGSSException(GSSException.DEFECTIVE_TOKEN,
+                                         GlobusGSSException.TOKEN_FAIL,
+                                         "tokenFail00",
+                                         new Object[] {new Integer(tokLen),
+                                                       new Integer(GSI_MESSAGE_DIGEST_PADDING +
+                                                                   md_size)});
+        }
+
+        int bufLen = SSLUtil.toInt(inTok, tokOff + GSI_SEQUENCE_SIZE);
+        if (bufLen != msgLen) {
+            throw new GlobusGSSException(GSSException.DEFECTIVE_TOKEN,
+                                         GlobusGSSException.TOKEN_FAIL,
+                                         "tokenFail01",
+                                         new Object[] {new Integer(msgLen), new Integer(bufLen)});
+        }
+
+        int pad_ct = (48 / md_size) * md_size;
+
+        byte [] digest = null;
+
+        try {
+            MessageDigest md =
+                MessageDigest.getInstance(digestAlg);
+
+            md.update(this.cipherFactory.getTlsBlockCipher().getReadMac()
+                    .getMACSecret());
+            for(int i=0;i<pad_ct;i++) {
+                md.update(SSLHANDSHAKE_PAD_1);
+            }
+            md.update(inTok, tokOff, GSI_MESSAGE_DIGEST_PADDING);
+            md.update(inMsg, msgOff, msgLen);
+
+            digest = md.digest();
+        } catch (NoSuchAlgorithmException e) {
+            throw new GlobusGSSException(GSSException.FAILURE, e);
+        }
+
+        byte [] token = new byte[tokLen-GSI_MESSAGE_DIGEST_PADDING];
+        System.arraycopy(inTok, tokOff+GSI_MESSAGE_DIGEST_PADDING, token, 0, token.length);
+
+        if (!Arrays.equals(digest, token)) {
+            throw new GlobusGSSException(GSSException.BAD_MIC,
+                                         GlobusGSSException.BAD_MIC,
+                                         "tokenFail02");
+        }
+
+        long tokSeq = SSLUtil.toLong(inTok, tokOff);
+        long readSeq = this.cipherFactory.getTlsBlockCipher().getReadMac()
+                .getSequenceNumber();
+        long seqTest = tokSeq - readSeq;
+
+        if (seqTest > 0) {
+            // gap token
+            throw new GSSException(GSSException.GAP_TOKEN);
+        } else if (seqTest < 0) {
+            // old token
+            throw new GSSException(GSSException.OLD_TOKEN);
+        } else {
+            this.cipherFactory.getTlsBlockCipher().getReadMac().incSequence();
+        }
+
+        if (prop != null) {
+            prop.setPrivacy(false);
+            prop.setQOP(0);
+        }
+    }
+
+    /*
+        verifyMIC(InputStream, InputStream) unimplemented
+    */
+    public void verifyMIC(InputStream tokStream, InputStream msgStream,
+                          MessageProp msgProp) throws GSSException {
+        throw new GSSException(GSSException.UNAVAILABLE);
+    }
+
+    /*
+        export not implemented
+     */
+    public byte[] export() throws GSSException {
+        throw new GSSException(GSSException.UNAVAILABLE);
+    }
+
+    /**
+     *
+     * @param state
+     * @throws GSSException
+     */
+    public void requestMutualAuth(boolean state) throws GSSException {
+        if (!state) {
+            throw new GlobusGSSException(GSSException.FAILURE,
+                    GlobusGSSException.BAD_OPTION,
+                    "mutualAuthOn");
+        }
+    }
+
+    /**
+     *
+     * @param state
+     * @throws GSSException
+     */
+    public void requestReplayDet(boolean state) throws GSSException {
+        if (!state) {
+            throw new GlobusGSSException(GSSException.FAILURE,
+                    GlobusGSSException.BAD_OPTION,
+                    "replayDet");
+        }
+    }
+
+    /**
+     *
+     * @param state
+     * @throws GSSException
+     */
+    public void requestSequenceDet(boolean state) throws GSSException {
+        if (!state) {
+            throw new GlobusGSSException(GSSException.FAILURE,
+                    GlobusGSSException.BAD_OPTION,
+                    "seqDet");
+        }
+    }
+
+    /**
+     *
+     * @param state
+     * @throws GSSException
+     */
+    public void requestCredDeleg(boolean state) throws GSSException {
+        this.credentialDelegation = state;
+    }
+
+    /**
+     *
+     * @param state
+     * @throws GSSException
+     */
+    public void requestAnonymity(boolean state) throws GSSException {
+        this.anonymity = state;
+    }
+
+    /**
+     *
+     * @param state
+     * @throws GSSException
+     */
+    public void requestConf(boolean state) throws GSSException {
+        //TODO: unencrypted not possible
+        this.encryption = true;
+    }
+
+    /**
+     *
+     * @param state
+     * @throws GSSException
+     */
+    public void requestInteg(boolean state) throws GSSException {
+        if (!state) {
+            throw new GlobusGSSException(GSSException.FAILURE,
+                    GlobusGSSException.BAD_OPTION,
+                    "integOn");
+        }
+    }
+
+    /**
+     *
+     * @param lifetime
+     * @throws GSSException
+     */
+    public void requestLifetime(int lifetime) throws GSSException {
+        if (lifetime == GSSContext.INDEFINITE_LIFETIME) {
+            throw new GlobusGSSException(GSSException.FAILURE,
+                    GlobusGSSException.UNKNOWN,
+                    "badLifetime00");
+        }
+
+        if (lifetime != GSSContext.DEFAULT_LIFETIME) {
+            Calendar calendar = Calendar.getInstance();
+            calendar.add(Calendar.SECOND, lifetime);
+            setGoodUntil(calendar.getTime());
+        }
+    }
+
+    /*
+        setChannelBinding unimplemented
+     */
+    public void setChannelBinding(ChannelBinding cb) throws GSSException {
+        throw new GSSException(GSSException.UNAVAILABLE);
+    }
+
+    /**
+     *
+     * @return
+     */
+    public boolean getCredDelegState() {
+        return this.credentialDelegation;
+    }
+
+    /**
+     *
+     * @return
+     */
+    public boolean getMutualAuthState() {
+        return true;  // always on with gsi
+    }
+
+    /**
+     *
+     * @return
+     */
+    public boolean getReplayDetState() {
+        return true;  // always on with ssl
+    }
+
+    /**
+     *
+     * @return
+     */
+    public boolean getSequenceDetState() {
+        return true;  // always on with ssl
+    }
+
+    /**
+     *
+     * @return
+     */
+    public boolean getAnonymityState() {
+        return this.anonymity;
+    }
+
+    /*
+        isTransferable unimplemented
+     */
+    public boolean isTransferable() throws GSSException {
+        throw new GSSException(GSSException.UNAVAILABLE);
+    }
+
+    /**
+     *
+     * @return
+     */
+    public boolean isProtReady() {
+        return isEstablished();
+    }
+
+    /**
+     *
+     * @return
+     */
+    public boolean getConfState() {
+        return this.encryption;
+    }
+
+    public boolean getIntegState() {
+        return true;  // always on with ssl
+    }
+
+    /**
+     *
+     * @return
+     */
+    public int getLifetime() {
+        if (goodUntil != null) {
+            return (int) ((goodUntil.getTime() - System.currentTimeMillis())
+                    / 1000);
+        } else {
+            return -1;
+        }
+    }
+
+    /**
+     *
+     * @return
+     * @throws GSSException
+     */
+    public GSSName getSrcName() throws GSSException {
+        return this.sourceName;
+    }
+
+    /**
+     *
+     * @return
+     * @throws GSSException
+     */
+    public GSSName getTargName() throws GSSException {
+        return this.targetName;
+    }
+
+    /**
+     *
+     * @return
+     * @throws GSSException
+     */
+    public Oid getMech() throws GSSException {
+        return GSSConstants.MECH_OID;
+    }
+
+    /*
+        getDelegCred unimplemented (would have been set by acceptSecContext
+     */
+    public GSSCredential getDelegCred() throws GSSException {
+        throw new GSSException(GSSException.UNAVAILABLE);
+    }
+
+    /**
+     *
+     * @return
+     * @throws GSSException
+     */
+    public boolean isInitiator() throws GSSException {
+        return true;  // acceptor side currently isn't implemented
+    }
+
+    /**
+     *
+     * @param val
+     * @return
+     */
+    public static byte[] toBytes(long val){
+        return toBytes(val,8);
+    }
+
+    /**
+     *
+     * @param val
+     * @return
+     */
+    public static byte[] toBytes(short val){
+        return toBytes((long)val,2);
+    }
+
+    /**
+     *
+     * @param val
+     * @param bytes
+     * @return
+     */
+    public static byte[] toBytes(long val,int bytes){
+        byte[] retval=new byte[bytes];
+
+        while(bytes-->0){
+            retval[bytes]=(byte)(val & 0xff);
+            val>>=8;
+        }
+
+        return retval;
+    }
+}

Added: airavata/sandbox/gsissh/src/main/java/edu/illinois/ncsa/BCGSS/CircularByteBuffer.java
URL: http://svn.apache.org/viewvc/airavata/sandbox/gsissh/src/main/java/edu/illinois/ncsa/BCGSS/CircularByteBuffer.java?rev=1512378&view=auto
==============================================================================
--- airavata/sandbox/gsissh/src/main/java/edu/illinois/ncsa/BCGSS/CircularByteBuffer.java (added)
+++ airavata/sandbox/gsissh/src/main/java/edu/illinois/ncsa/BCGSS/CircularByteBuffer.java Fri Aug  9 16:24:07 2013
@@ -0,0 +1,806 @@
+package edu.illinois.ncsa.BCGSS;
+/*
+ * Circular Byte Buffer
+ * Copyright (C) 2002 Stephen Ostermiller
+ * http://ostermiller.org/contact.pl?regarding=Java+Utilities
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * See COPYING.TXT for details.
+ */
+
+
+import java.io.*;
+import java.nio.*;
+
+/**
+ * Implements the Circular Buffer producer/consumer model for bytes.
+ * More information about this class is available from <a target="_top" href=
+ * "http://ostermiller.org/utils/CircularByteBuffer.html">ostermiller.org</a>.
+ * <p>
+ * Using this class is a simpler alternative to using a PipedInputStream
+ * and a PipedOutputStream. PipedInputStreams and PipedOutputStreams don't support the
+ * mark operation, don't allow you to control buffer sizes that they use,
+ * and have a more complicated API that requires instantiating two
+ * classes and connecting them.
+ * <p>
+ * This class is thread safe.
+ *
+ * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
+ * @since ostermillerutils 1.00.00
+ */
+public class CircularByteBuffer {
+
+	/**
+	 * The default size for a circular byte buffer.
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	private final static int DEFAULT_SIZE = 1024;
+
+	/**
+	 * A buffer that will grow as things are added.
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	public final static int INFINITE_SIZE = -1;
+
+	/**
+	 * The circular buffer.
+	 * <p>
+	 * The actual capacity of the buffer is one less than the actual length
+	 * of the buffer so that an empty and a full buffer can be
+	 * distinguished.  An empty buffer will have the markPostion and the
+	 * writePosition equal to each other.  A full buffer will have
+	 * the writePosition one less than the markPostion.
+	 * <p>
+	 * There are three important indexes into the buffer:
+	 * The readPosition, the writePosition, and the markPosition.
+	 * If the InputStream has never been marked, the readPosition and
+	 * the markPosition should always be the same.  The bytes
+	 * available to be read go from the readPosition to the writePosition,
+	 * wrapping around the end of the buffer.  The space available for writing
+	 * goes from the write position to one less than the markPosition,
+	 * wrapping around the end of the buffer.  The bytes that have
+	 * been saved to support a reset() of the InputStream go from markPosition
+	 * to readPosition, wrapping around the end of the buffer.
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	protected byte[] buffer;
+	/**
+	 * Index of the first byte available to be read.
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	protected volatile int readPosition = 0;
+	/**
+	 * Index of the first byte available to be written.
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	protected volatile int writePosition = 0;
+	/**
+	 * Index of the first saved byte. (To support stream marking.)
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	protected volatile int markPosition = 0;
+	/**
+	 * Number of bytes that have to be saved
+	 * to support mark() and reset() on the InputStream.
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	protected volatile int markSize = 0;
+	/**
+	 * If this buffer is infinite (should resize itself when full)
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	protected volatile boolean infinite = false;
+	/**
+	 * True if a write to a full buffer should block until the buffer
+	 * has room, false if the write method should throw an IOException
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	protected boolean blockingWrite = true;
+	/**
+	 * The InputStream that can empty this buffer.
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	protected InputStream in = new CircularByteBufferInputStream();
+	/**
+	 * true if the close() method has been called on the InputStream
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	protected boolean inputStreamClosed = false;
+	/**
+	 * The OutputStream that can fill this buffer.
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	protected OutputStream out = new CircularByteBufferOutputStream();
+	/**
+	 * true if the close() method has been called on the OutputStream
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	protected boolean outputStreamClosed = false;
+
+	/**
+	 * Make this buffer ready for reuse.  The contents of the buffer
+	 * will be cleared and the streams associated with this buffer
+	 * will be reopened if they had been closed.
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	public void clear(){
+		synchronized (this){
+			readPosition = 0;
+			writePosition = 0;
+			markPosition = 0;
+			outputStreamClosed = false;
+			inputStreamClosed = false;
+		}
+	}
+
+	/**
+	 * Retrieve a OutputStream that can be used to fill
+	 * this buffer.
+	 * <p>
+	 * Write methods may throw a BufferOverflowException if
+	 * the buffer is not large enough.  A large enough buffer
+	 * size must be chosen so that this does not happen or
+	 * the caller must be prepared to catch the exception and
+	 * try again once part of the buffer has been consumed.
+	 *
+	 *
+	 * @return the producer for this buffer.
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	public OutputStream getOutputStream(){
+		return out;
+	}
+
+	/**
+	 * Retrieve a InputStream that can be used to empty
+	 * this buffer.
+	 * <p>
+	 * This InputStream supports marks at the expense
+	 * of the buffer size.
+	 *
+	 * @return the consumer for this buffer.
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	public InputStream getInputStream(){
+		return in;
+	}
+
+	/**
+	 * Get number of bytes that are available to be read.
+	 * <p>
+	 * Note that the number of bytes available plus
+	 * the number of bytes free may not add up to the
+	 * capacity of this buffer, as the buffer may reserve some
+	 * space for other purposes.
+	 *
+	 * @return the size in bytes of this buffer
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	public int getAvailable(){
+		synchronized (this){
+			return available();
+		}
+	}
+
+	/**
+	 * Get the number of bytes this buffer has free for
+	 * writing.
+	 * <p>
+	 * Note that the number of bytes available plus
+	 * the number of bytes free may not add up to the
+	 * capacity of this buffer, as the buffer may reserve some
+	 * space for other purposes.
+	 *
+	 * @return the available space in bytes of this buffer
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	public int getSpaceLeft(){
+		synchronized (this){
+			return spaceLeft();
+		}
+	}
+
+	/**
+	 * Get the capacity of this buffer.
+	 * <p>
+	 * Note that the number of bytes available plus
+	 * the number of bytes free may not add up to the
+	 * capacity of this buffer, as the buffer may reserve some
+	 * space for other purposes.
+	 *
+	 * @return the size in bytes of this buffer
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	public int getSize(){
+		synchronized (this){
+			return buffer.length;
+		}
+	}
+
+	/**
+	 * double the size of the buffer
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	private void resize(){
+		byte[] newBuffer = new byte[buffer.length * 2];
+		int marked = marked();
+		int available = available();
+		if (markPosition <= writePosition){
+			// any space between the mark and
+			// the first write needs to be saved.
+			// In this case it is all in one piece.
+			int length = writePosition - markPosition;
+			System.arraycopy(buffer, markPosition, newBuffer, 0, length);
+		} else {
+			int length1 = buffer.length - markPosition;
+			System.arraycopy(buffer, markPosition, newBuffer, 0, length1);
+			int length2 = writePosition;
+			System.arraycopy(buffer, 0, newBuffer, length1, length2);
+		}
+		buffer = newBuffer;
+		markPosition = 0;
+		readPosition = marked;
+		writePosition = marked + available;
+	}
+
+	/**
+	 * Space available in the buffer which can be written.
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	private int spaceLeft(){
+		if (writePosition < markPosition){
+			// any space between the first write and
+			// the mark except one byte is available.
+			// In this case it is all in one piece.
+			return (markPosition - writePosition - 1);
+		}
+		// space at the beginning and end.
+		return ((buffer.length - 1) - (writePosition - markPosition));
+	}
+
+	/**
+	 * Bytes available for reading.
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	private int available(){
+		if (readPosition <= writePosition){
+			// any space between the first read and
+			// the first write is available.  In this case i
+			// is all in one piece.
+			return (writePosition - readPosition);
+		}
+		// space at the beginning and end.
+		return (buffer.length - (readPosition - writePosition));
+	}
+
+	/**
+	 * Bytes saved for supporting marks.
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	private int marked(){
+		if (markPosition <= readPosition){
+			// any space between the markPosition and
+			// the first write is marked.  In this case i
+			// is all in one piece.
+			return (readPosition - markPosition);
+		}
+		// space at the beginning and end.
+		return (buffer.length - (markPosition - readPosition));
+	}
+
+	/**
+	 * If we have passed the markSize reset the
+	 * mark so that the space can be used.
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	private void ensureMark(){
+		if (marked() >= markSize){
+			markPosition = readPosition;
+			markSize = 0;
+		}
+	}
+
+	/**
+	 * Create a new buffer with a default capacity.
+	 * Writing to a full buffer will block until space
+	 * is available rather than throw an exception.
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	public CircularByteBuffer(){
+		this (DEFAULT_SIZE, true);
+	}
+
+	/**
+	 * Create a new buffer with given capacity.
+	 * Writing to a full buffer will block until space
+	 * is available rather than throw an exception.
+	 * <p>
+	 * Note that the buffer may reserve some bytes for
+	 * special purposes and capacity number of bytes may
+	 * not be able to be written to the buffer.
+	 * <p>
+	 * Note that if the buffer is of INFINITE_SIZE it will
+	 * neither block or throw exceptions, but rather grow
+	 * without bound.
+	 *
+	 * @param size desired capacity of the buffer in bytes or CircularByteBuffer.INFINITE_SIZE.
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	public CircularByteBuffer(int size){
+		this (size, true);
+	}
+
+	/**
+	 * Create a new buffer with a default capacity and
+	 * given blocking behavior.
+	 *
+	 * @param blockingWrite true writing to a full buffer should block
+	 *        until space is available, false if an exception should
+	 *        be thrown instead.
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	public CircularByteBuffer(boolean blockingWrite){
+		this (DEFAULT_SIZE, blockingWrite);
+	}
+
+	/**
+	 * Create a new buffer with the given capacity and
+	 * blocking behavior.
+	 * <p>
+	 * Note that the buffer may reserve some bytes for
+	 * special purposes and capacity number of bytes may
+	 * not be able to be written to the buffer.
+	 * <p>
+	 * Note that if the buffer is of INFINITE_SIZE it will
+	 * neither block or throw exceptions, but rather grow
+	 * without bound.
+	 *
+	 * @param size desired capacity of the buffer in bytes or CircularByteBuffer.INFINITE_SIZE.
+	 * @param blockingWrite true writing to a full buffer should block
+	 *        until space is available, false if an exception should
+	 *        be thrown instead.
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	public CircularByteBuffer(int size, boolean blockingWrite){
+		if (size == INFINITE_SIZE){
+			buffer = new byte[DEFAULT_SIZE];
+			infinite = true;
+		} else {
+			buffer = new byte[size];
+			infinite = false;
+		}
+		this.blockingWrite = blockingWrite;
+	}
+
+	/**
+	 * Class for reading from a circular byte buffer.
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	protected class CircularByteBufferInputStream extends InputStream {
+
+		/**
+		 * Returns the number of bytes that can be read (or skipped over) from this
+		 * input stream without blocking by the next caller of a method for this input
+		 * stream. The next caller might be the same thread or or another thread.
+		 *
+		 * @return the number of bytes that can be read from this input stream without blocking.
+		 * @throws IOException if the stream is closed.
+		 *
+		 * @since ostermillerutils 1.00.00
+		 */
+		@Override public int available() throws IOException {
+			synchronized (CircularByteBuffer.this){
+				if (inputStreamClosed) throw new IOException("InputStream has been closed, it is not ready.");
+				return (CircularByteBuffer.this.available());
+			}
+		}
+
+		/**
+		 * Close the stream. Once a stream has been closed, further read(), available(),
+		 * mark(), or reset() invocations will throw an IOException. Closing a
+		 * previously-closed stream, however, has no effect.
+		 *
+		 * @throws IOException never.
+		 *
+		 * @since ostermillerutils 1.00.00
+		 */
+		@Override public void close() throws IOException {
+			synchronized (CircularByteBuffer.this){
+				inputStreamClosed = true;
+			}
+		}
+
+		/**
+		 * Mark the present position in the stream. Subsequent calls to reset() will
+		 * attempt to reposition the stream to this point.
+		 * <p>
+		 * The readAheadLimit must be less than the size of circular buffer, otherwise
+		 * this method has no effect.
+		 *
+		 * @param readAheadLimit Limit on the number of bytes that may be read while
+		 *    still preserving the mark. After reading this many bytes, attempting to
+		 *    reset the stream will fail.
+		 *
+		 * @since ostermillerutils 1.00.00
+		 */
+		@Override public void mark(int readAheadLimit) {
+			synchronized (CircularByteBuffer.this){
+				//if (inputStreamClosed) throw new IOException("InputStream has been closed; cannot mark a closed InputStream.");
+				if (buffer.length - 1 > readAheadLimit) {
+					markSize = readAheadLimit;
+					markPosition = readPosition;
+				}
+			}
+		}
+
+		/**
+		 * Tell whether this stream supports the mark() operation.
+		 *
+		 * @return true, mark is supported.
+		 *
+		 * @since ostermillerutils 1.00.00
+		 */
+		@Override public boolean markSupported() {
+			return true;
+		}
+
+		/**
+		 * Read a single byte.
+		 * This method will block until a byte is available, an I/O error occurs,
+		 * or the end of the stream is reached.
+		 *
+		 * @return The byte read, as an integer in the range 0 to 255 (0x00-0xff),
+		 *     or -1 if the end of the stream has been reached
+		 * @throws IOException if the stream is closed.
+		 *
+		 * @since ostermillerutils 1.00.00
+		 */
+		@Override public int read() throws IOException {
+			while (true){
+				synchronized (CircularByteBuffer.this){
+					if (inputStreamClosed) throw new IOException("InputStream has been closed; cannot read from a closed InputStream.");
+					int available = CircularByteBuffer.this.available();
+					if (available > 0){
+						int result = buffer[readPosition] & 0xff;
+						readPosition++;
+						if (readPosition == buffer.length){
+							readPosition = 0;
+						}
+						ensureMark();
+						return result;
+					} else if (outputStreamClosed){
+						return -1;
+					}
+				}
+				try {
+					Thread.sleep(100);
+				} catch(Exception x){
+					throw new IOException("Blocking read operation interrupted.");
+				}
+			}
+		}
+
+		/**
+		 * Read bytes into an array.
+		 * This method will block until some input is available,
+		 * an I/O error occurs, or the end of the stream is reached.
+		 *
+		 * @param cbuf Destination buffer.
+		 * @return The number of bytes read, or -1 if the end of
+		 *   the stream has been reached
+		 * @throws IOException if the stream is closed.
+		 *
+		 * @since ostermillerutils 1.00.00
+		 */
+		@Override public int read(byte[] cbuf) throws IOException {
+			return read(cbuf, 0, cbuf.length);
+		}
+
+		/**
+		 * Read bytes into a portion of an array.
+		 * This method will block until some input is available,
+		 * an I/O error occurs, or the end of the stream is reached.
+		 *
+		 * @param cbuf Destination buffer.
+		 * @param off Offset at which to start storing bytes.
+		 * @param len Maximum number of bytes to read.
+		 * @return The number of bytes read, or -1 if the end of
+		 *   the stream has been reached
+		 * @throws IOException if the stream is closed.
+		 *
+		 * @since ostermillerutils 1.00.00
+		 */
+		@Override public int read(byte[] cbuf, int off, int len) throws IOException {
+			while (true){
+				synchronized (CircularByteBuffer.this){
+					if (inputStreamClosed) throw new IOException("InputStream has been closed; cannot read from a closed InputStream.");
+					int available = CircularByteBuffer.this.available();
+					if (available > 0){
+						int length = Math.min(len, available);
+						int firstLen = Math.min(length, buffer.length - readPosition);
+						int secondLen = length - firstLen;
+						System.arraycopy(buffer, readPosition, cbuf, off, firstLen);
+						if (secondLen > 0){
+							System.arraycopy(buffer, 0, cbuf, off+firstLen,  secondLen);
+							readPosition = secondLen;
+						} else {
+							readPosition += length;
+						}
+						if (readPosition == buffer.length) {
+							readPosition = 0;
+						}
+						ensureMark();
+						return length;
+					} else if (outputStreamClosed){
+						return -1;
+					}
+				}
+				try {
+					Thread.sleep(100);
+				} catch(Exception x){
+					throw new IOException("Blocking read operation interrupted.");
+				}
+			}
+		}
+
+		/**
+		 * Reset the stream.
+		 * If the stream has been marked, then attempt to reposition i
+		 * at the mark. If the stream has not been marked, or more bytes
+		 * than the readAheadLimit have been read, this method has no effect.
+		 *
+		 * @throws IOException if the stream is closed.
+		 *
+		 * @since ostermillerutils 1.00.00
+		 */
+		@Override public void reset() throws IOException {
+			synchronized (CircularByteBuffer.this){
+				if (inputStreamClosed) throw new IOException("InputStream has been closed; cannot reset a closed InputStream.");
+				readPosition = markPosition;
+			}
+		}
+
+		/**
+		 * Skip bytes.
+		 * This method will block until some bytes are available,
+		 * an I/O error occurs, or the end of the stream is reached.
+		 *
+		 * @param n The number of bytes to skip
+		 * @return The number of bytes actually skipped
+		 * @throws IllegalArgumentException if n is negative.
+		 * @throws IOException if the stream is closed.
+		 *
+		 * @since ostermillerutils 1.00.00
+		 */
+		@Override public long skip(long n) throws IOException, IllegalArgumentException {
+			while (true){
+				synchronized (CircularByteBuffer.this){
+					if (inputStreamClosed) throw new IOException("InputStream has been closed; cannot skip bytes on a closed InputStream.");
+					int available = CircularByteBuffer.this.available();
+					if (available > 0){
+						int length = Math.min((int)n, available);
+						int firstLen = Math.min(length, buffer.length - readPosition);
+						int secondLen = length - firstLen;
+						if (secondLen > 0){
+							readPosition = secondLen;
+						} else {
+							readPosition += length;
+						}
+						if (readPosition == buffer.length) {
+							readPosition = 0;
+						}
+						ensureMark();
+						return length;
+					} else if (outputStreamClosed){
+						return 0;
+					}
+				}
+				try {
+					Thread.sleep(100);
+				} catch(Exception x){
+					throw new IOException("Blocking read operation interrupted.");
+				}
+			}
+		}
+	}
+
+	/**
+	 * Class for writing to a circular byte buffer.
+	 * If the buffer is full, the writes will either block
+	 * until there is some space available or throw an IOException
+	 * based on the CircularByteBuffer's preference.
+	 *
+	 * @since ostermillerutils 1.00.00
+	 */
+	protected class CircularByteBufferOutputStream extends OutputStream {
+
+		/**
+		 * Close the stream, flushing it first.
+		 * This will cause the InputStream associated with this circular buffer
+		 * to read its last bytes once it empties the buffer.
+		 * Once a stream has been closed, further write() or flush() invocations
+		 * will cause an IOException to be thrown. Closing a previously-closed stream,
+		 * however, has no effect.
+		 *
+		 * @throws IOException never.
+		 *
+		 * @since ostermillerutils 1.00.00
+		 */
+		@Override public void close() throws IOException {
+			synchronized (CircularByteBuffer.this){
+				if (!outputStreamClosed){
+					flush();
+				}
+				outputStreamClosed = true;
+			}
+		}
+
+		/**
+		 * Flush the stream.
+		 *
+		 * @throws IOException if the stream is closed.
+		 *
+		 * @since ostermillerutils 1.00.00
+		 */
+		@Override public void flush() throws IOException {
+			if (outputStreamClosed) throw new IOException("OutputStream has been closed; cannot flush a closed OutputStream.");
+			if (inputStreamClosed) throw new IOException("Buffer closed by inputStream; cannot flush.");
+			// this method needs to do nothing
+		}
+
+		/**
+		 * Write an array of bytes.
+		 * If the buffer allows blocking writes, this method will block until
+		 * all the data has been written rather than throw an IOException.
+		 *
+		 * @param cbuf Array of bytes to be written
+		 * @throws BufferOverflowException if buffer does not allow blocking writes
+		 *   and the buffer is full.  If the exception is thrown, no data
+		 *   will have been written since the buffer was set to be non-blocking.
+		 * @throws IOException if the stream is closed, or the write is interrupted.
+		 *
+		 * @since ostermillerutils 1.00.00
+		 */
+		@Override public void write(byte[] cbuf) throws IOException {
+			write(cbuf, 0, cbuf.length);
+		}
+
+		/**
+		 * Write a portion of an array of bytes.
+		 * If the buffer allows blocking writes, this method will block until
+		 * all the data has been written rather than throw an IOException.
+		 *
+		 * @param cbuf Array of bytes
+		 * @param off Offset from which to start writing bytes
+		 * @param len - Number of bytes to write
+		 * @throws BufferOverflowException if buffer does not allow blocking writes
+		 *   and the buffer is full.  If the exception is thrown, no data
+		 *   will have been written since the buffer was set to be non-blocking.
+		 * @throws IOException if the stream is closed, or the write is interrupted.
+		 *
+		 * @since ostermillerutils 1.00.00
+		 */
+		@Override public void write(byte[] cbuf, int off, int len) throws IOException {
+			while (len > 0){
+				synchronized (CircularByteBuffer.this){
+					if (outputStreamClosed) throw new IOException("OutputStream has been closed; cannot write to a closed OutputStream.");
+					if (inputStreamClosed) throw new IOException("Buffer closed by InputStream; cannot write to a closed buffer.");
+					int spaceLeft = spaceLeft();
+					while (infinite && spaceLeft < len){
+						resize();
+						spaceLeft = spaceLeft();
+					}
+					if (!blockingWrite && spaceLeft < len) throw new BufferOverflowException();
+					int realLen = Math.min(len, spaceLeft);
+					int firstLen = Math.min(realLen, buffer.length - writePosition);
+					int secondLen = Math.min(realLen - firstLen, buffer.length - markPosition - 1);
+					int written = firstLen + secondLen;
+					if (firstLen > 0){
+						System.arraycopy(cbuf, off, buffer, writePosition, firstLen);
+					}
+					if (secondLen > 0){
+						System.arraycopy(cbuf, off+firstLen, buffer, 0, secondLen);
+						writePosition = secondLen;
+					} else {
+						writePosition += written;
+					}
+					if (writePosition == buffer.length) {
+						writePosition = 0;
+					}
+					off += written;
+					len -= written;
+				}
+				if (len > 0){
+					try {
+						Thread.sleep(100);
+					} catch(Exception x){
+						throw new IOException("Waiting for available space in buffer interrupted.");
+					}
+				}
+			}
+		}
+
+		/**
+		 * Write a single byte.
+		 * The byte to be written is contained in the 8 low-order bits of the
+		 * given integer value; the 24 high-order bits are ignored.
+		 * If the buffer allows blocking writes, this method will block until
+		 * all the data has been written rather than throw an IOException.
+		 *
+		 * @param c number of bytes to be written
+		 * @throws BufferOverflowException if buffer does not allow blocking writes
+		 *   and the buffer is full.
+		 * @throws IOException if the stream is closed, or the write is interrupted.
+		 *
+		 * @since ostermillerutils 1.00.00
+		 */
+		@Override public void write(int c) throws IOException {
+			boolean written = false;
+			while (!written){
+				synchronized (CircularByteBuffer.this){
+					if (outputStreamClosed) throw new IOException("OutputStream has been closed; cannot write to a closed OutputStream.");
+					if (inputStreamClosed) throw new IOException("Buffer closed by InputStream; cannot write to a closed buffer.");
+					int spaceLeft = spaceLeft();
+					while (infinite && spaceLeft < 1){
+						resize();
+						spaceLeft = spaceLeft();
+					}
+					if (!blockingWrite && spaceLeft < 1) throw new BufferOverflowException();
+					if (spaceLeft > 0){
+						buffer[writePosition] = (byte)(c & 0xff);
+						writePosition++;
+						if (writePosition == buffer.length) {
+							writePosition = 0;
+						}
+						written = true;
+					}
+				}
+				if (!written){
+					try {
+						Thread.sleep(100);
+					} catch(Exception x){
+						throw new IOException("Waiting for available space in buffer interrupted.");
+					}
+				}
+			}
+		}
+	}
+}

Added: airavata/sandbox/gsissh/src/main/java/edu/illinois/ncsa/BCGSS/GlobusTlsCipherFactory.java
URL: http://svn.apache.org/viewvc/airavata/sandbox/gsissh/src/main/java/edu/illinois/ncsa/BCGSS/GlobusTlsCipherFactory.java?rev=1512378&view=auto
==============================================================================
--- airavata/sandbox/gsissh/src/main/java/edu/illinois/ncsa/BCGSS/GlobusTlsCipherFactory.java (added)
+++ airavata/sandbox/gsissh/src/main/java/edu/illinois/ncsa/BCGSS/GlobusTlsCipherFactory.java Fri Aug  9 16:24:07 2013
@@ -0,0 +1,42 @@
+package edu.illinois.ncsa.BCGSS;
+
+import edu.illinois.ncsa.bouncycastle.crypto.Digest;
+import edu.illinois.ncsa.bouncycastle.crypto.tls.AlertDescription;
+import edu.illinois.ncsa.bouncycastle.crypto.tls.DefaultTlsCipherFactory;
+import edu.illinois.ncsa.bouncycastle.crypto.tls.TlsBlockCipher;
+import edu.illinois.ncsa.bouncycastle.crypto.tls.TlsCipher;
+import edu.illinois.ncsa.bouncycastle.crypto.tls.TlsClientContext;
+import edu.illinois.ncsa.bouncycastle.crypto.tls.TlsFatalAlert;
+
+import java.io.IOException;
+
+public class GlobusTlsCipherFactory extends DefaultTlsCipherFactory {
+    protected TlsBlockCipher tlsBlockCipher;
+    protected Digest digest;
+
+    public TlsBlockCipher getTlsBlockCipher() {
+        return tlsBlockCipher;
+    }
+
+    public Digest getDigest() {
+        return digest;
+    }
+
+    public TlsCipher createCipher(TlsClientContext context,
+                                     int encAlg, int digestAlg)
+            throws IOException {
+        TlsCipher cipher = super.createCipher(context, encAlg, digestAlg);
+        if (cipher instanceof TlsBlockCipher) {
+            tlsBlockCipher = (TlsBlockCipher) cipher;
+        } else {
+            throw new TlsFatalAlert(AlertDescription.internal_error);
+        }
+
+        return cipher;
+    }
+
+    protected Digest createDigest(int digestAlgorithm) throws IOException {
+        digest = super.createDigest(digestAlgorithm);
+        return digest;
+    }
+}

Added: airavata/sandbox/gsissh/src/main/java/edu/illinois/ncsa/BCGSS/GlobusTlsClient.java
URL: http://svn.apache.org/viewvc/airavata/sandbox/gsissh/src/main/java/edu/illinois/ncsa/BCGSS/GlobusTlsClient.java?rev=1512378&view=auto
==============================================================================
--- airavata/sandbox/gsissh/src/main/java/edu/illinois/ncsa/BCGSS/GlobusTlsClient.java (added)
+++ airavata/sandbox/gsissh/src/main/java/edu/illinois/ncsa/BCGSS/GlobusTlsClient.java Fri Aug  9 16:24:07 2013
@@ -0,0 +1,223 @@
+package edu.illinois.ncsa.BCGSS;
+
+import edu.illinois.ncsa.bouncycastle.crypto.tls.*;
+import edu.illinois.ncsa.bouncycastle.asn1.*;
+import edu.illinois.ncsa.bouncycastle.asn1.x509.*;
+import org.globus.common.CoGProperties;
+import org.globus.gsi.CredentialException;
+import org.globus.gsi.X509Credential;
+import org.globus.gsi.X509ProxyCertPathParameters;
+import org.globus.gsi.provider.GlobusProvider;
+import org.globus.gsi.provider.KeyStoreParametersFactory;
+import org.globus.gsi.stores.ResourceCertStoreParameters;
+import org.globus.gsi.stores.ResourceSigningPolicyStore;
+import org.globus.gsi.stores.ResourceSigningPolicyStoreParameters;
+import org.globus.gsi.trustmanager.X509ProxyCertPathValidator;
+import org.globus.gsi.util.CertificateUtil;
+
+import javax.crypto.Cipher;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.cert.CertStore;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
+public class GlobusTlsClient extends DefaultTlsClient
+{
+    private Certificate clientCert = new Certificate(new X509CertificateStructure[0]);
+    private PrivateKey clientPrivateKey = null;
+    private X509Certificate[] peerCerts = null;
+
+    public X509Certificate[] getPeerCerts() {
+        return peerCerts;
+    }
+
+    public GlobusTlsClient(X509Credential cred, GlobusTlsCipherFactory factory)
+            throws IOException, CertificateException, CredentialException {
+        super(factory);
+        if (cred == null) {
+            throw new IllegalArgumentException("'cred' cannot be null");
+        }
+
+        clientCert = new Certificate(
+                X509CertArrayToStructArray(cred.getCertificateChain()));
+        clientPrivateKey = cred.getPrivateKey();
+
+        if (clientCert.getCerts().length == 0) {
+            throw new IllegalArgumentException(
+                    "'cred' contains no certificates");
+        }
+
+        if (clientPrivateKey == null) {
+            throw new IllegalArgumentException("'clientPrivateKey' cannot be null");
+        }
+    }
+
+    public TlsAuthentication getAuthentication() throws IOException {
+        return new GlobusTlsAuth();
+    }
+
+    public int[] getCipherSuites() {
+        return new int[] {
+                CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA,
+                CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
+                CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+        };
+    }
+
+    public class GlobusTlsAuth implements TlsAuthentication {
+
+        /**
+         * Validates the server's certificate
+         * @param certificate received from server
+         * @throws IOException
+         */
+        public void notifyServerCertificate(Certificate certificate)
+                throws IOException {
+            try {
+            peerCerts = X509CertStructArrayToCertArray(certificate.getCerts());
+
+            String caCertsLocation =
+                    "file:" + CoGProperties.getDefault().getCaCertLocations();
+            String crlPattern = caCertsLocation + "/*.r*";
+            String sigPolPattern = caCertsLocation + "/*.signing_policy";
+
+            KeyStore keyStore = KeyStore.getInstance(
+                    GlobusProvider.KEYSTORE_TYPE, GlobusProvider.PROVIDER_NAME);
+            CertStore crlStore = CertStore.getInstance(
+                    GlobusProvider.CERTSTORE_TYPE,
+                    new ResourceCertStoreParameters(null, crlPattern));
+            ResourceSigningPolicyStore sigPolStore =
+                    new ResourceSigningPolicyStore(
+                            new ResourceSigningPolicyStoreParameters(
+                                    sigPolPattern));
+            keyStore.load(
+                    KeyStoreParametersFactory.createTrustStoreParameters(
+                            caCertsLocation));
+            X509ProxyCertPathParameters parameters =
+                    new X509ProxyCertPathParameters(keyStore, crlStore,
+                            sigPolStore, false);
+            X509ProxyCertPathValidator validator =
+                    new X509ProxyCertPathValidator();
+            if (validator.engineValidate(CertificateUtil.getCertPath(peerCerts),
+                    parameters) == null) {
+                throw new Exception("X509ProxyCertPathValidator did not return a result");
+            }
+            } catch (Exception e) {
+                e.printStackTrace();
+                throw new TlsFatalAlert(AlertDescription.user_canceled);
+            }
+        }
+
+        /**
+         * Returns an object representing the client's credentials
+         * @param request
+         * @return the client's credentials
+         * @throws IOException
+         */
+        public TlsCredentials getClientCredentials(CertificateRequest request)
+                throws IOException {
+            return new GlobusTlsCred();
+        }
+    }
+
+    public class GlobusTlsCred implements TlsSignerCredentials {
+        /**
+         * Encrypts a hash with the client's private key, producing a signature
+         * @param md5andsha1 the hash to encrypt
+         * @return an array of bytes containing the signature
+         * @throws IOException
+         */
+        public byte[] generateCertificateSignature(byte[] md5andsha1)
+                throws IOException {
+            // encrypt the input hash with the private key to produce signature
+            try {
+                Cipher cipher = Cipher.getInstance(clientPrivateKey.getAlgorithm());
+                cipher.init(Cipher.ENCRYPT_MODE, clientPrivateKey);
+                return cipher.doFinal(md5andsha1);
+            } catch (Exception e) {
+                e.printStackTrace();
+                throw new IOException(e);
+            }
+        }
+
+        public Certificate getCertificate() {
+            return clientCert;
+        }
+    }
+
+       /**
+     *
+     * @param struct
+     * @return
+     * @throws CertificateException
+     * @throws IOException
+     */
+    public static X509Certificate X509CertStructToCert(
+            X509CertificateStructure struct) throws CertificateException,
+            IOException {
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        InputStream is = new ByteArrayInputStream(struct.getEncoded());
+        X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
+        is.close();
+        return cert;
+    }
+
+    /**
+     *
+     * @param structs
+     * @return
+     * @throws java.io.IOException
+     * @throws java.security.cert.CertificateException
+     */
+    public static X509Certificate[] X509CertStructArrayToCertArray(
+            X509CertificateStructure[] structs) throws IOException,
+            CertificateException {
+        X509Certificate[] certChain = new X509Certificate[structs.length];
+
+        for (int i = 0; i < structs.length; ++i) {
+            certChain[i] = X509CertStructToCert(structs[i]);
+        }
+
+        return certChain;
+    }
+
+    /**
+     *
+     * @param c
+     * @return
+     * @throws CertificateException
+     * @throws IOException
+     */
+    public static X509CertificateStructure X509CertToStruct(X509Certificate c)
+            throws CertificateException, IOException {
+        ASN1InputStream is = new ASN1InputStream(c.getEncoded());
+        DERObject o = is.readObject();
+        return X509CertificateStructure.getInstance(o);
+    }
+
+
+    /**
+     *
+     * @param certs
+     * @return
+     * @throws CertificateException
+     * @throws IOException
+     */
+    public static X509CertificateStructure[] X509CertArrayToStructArray(
+            X509Certificate[] certs) throws CertificateException, IOException {
+        X509CertificateStructure[] structs =
+                new X509CertificateStructure[certs.length];
+
+        for (int i = 0; i < certs.length; ++i) {
+            structs[i] = X509CertToStruct(certs[i]);
+        }
+
+        return structs;
+    }
+}
+



Mime
View raw message