Added: airavata/sandbox/gsissh/src/main/java/edu/illinois/ncsa/BCGSS/TlsHandlerUtil.java URL: http://svn.apache.org/viewvc/airavata/sandbox/gsissh/src/main/java/edu/illinois/ncsa/BCGSS/TlsHandlerUtil.java?rev=1512378&view=auto ============================================================================== --- airavata/sandbox/gsissh/src/main/java/edu/illinois/ncsa/BCGSS/TlsHandlerUtil.java (added) +++ airavata/sandbox/gsissh/src/main/java/edu/illinois/ncsa/BCGSS/TlsHandlerUtil.java Fri Aug 9 16:24:07 2013 @@ -0,0 +1,261 @@ +package edu.illinois.ncsa.BCGSS; +import edu.illinois.ncsa.bouncycastle.crypto.tls.*; + +import java.io.*; + +public class TlsHandlerUtil { + private TlsProtocolHandler tlsHandler; + private TlsClient tlsClient; + private CircularByteBuffer netInStream; + private ByteArrayOutputStream netOutStream; + private boolean connectionThreadStarted = false; + private IOException connectionThreadException = null; + + /* + public TlsHandlerUtil(TlsClient client) { + this(client, new TlsProtocolVersion[] {TlsProtocolVersion.TLSv10, + TlsProtocolVersion.SSLv3}); + } + */ + + //public TlsHandlerUtil(TlsClient client, TlsProtocolVersion[] protocols) { + public TlsHandlerUtil(TlsClient client) { + this.tlsClient = client; + + this.netInStream = new CircularByteBuffer( + CircularByteBuffer.INFINITE_SIZE); + + //TODO: set a good initial size of buffer? + this.netOutStream = new ByteArrayOutputStream(); + + this.tlsHandler = new TlsProtocolHandler( + netInStream.getInputStream(), netOutStream); + //this.tlsHandler.setEnabledProtocols(protocols); + } + + /** + * + * @param inNetBuf + * @return + */ + public byte[] nextHandshakeToken(byte[] inNetBuf) throws IOException { + return nextHandshakeToken(inNetBuf, 0, inNetBuf.length); + } + + /** + * + * @param inNetBuf + * @param off + * @param len + * @return + * @throws java.io.IOException + */ + public byte[] nextHandshakeToken(byte[] inNetBuf, int off, int len) + throws IOException { + if (isHandshakeFinished()) { + return null; + } + + if (! isConnectionThreadStarted()) { + (new ConnectionThread()).start(); + } + + + if (tlsHandler.getHandshakeBlocking() > 0) { + tlsHandler.decHandshakeBlocking(inNetBuf.length); + } + + netInStream.getOutputStream().write(inNetBuf, off, len); + + // block until the TlsProtocolHandler's record stream blocks + // or until the handshake is finished. After either, a handshake + // token may have been produced + while (tlsHandler.getHandshakeBlocking() == 0 && + ! isHandshakeFinished()) { + + IOException e = getConnectionThreadException(); + if (e != null) { + throw new IOException("TLS connection thread exception", e); + } + + try { + Thread.sleep(25); + } catch (InterruptedException e1) { + throw new IOException("Handshake interrupted while waiting " + + "for new network data to be processed", e1); + } + } + + byte[] token = drainNetOutStream(); + + if (token.length > 0) { + return token; + } + + if (tlsHandler.getHandshakeBlocking() > 0) { + // no token produced; need more data + return null; + } + + if (isHandshakeFinished()) { + return null; + } else { + throw new IOException("No handshake data available, but the " + + "record stream is not blocking and wasn't interrupted"); + } + } + + /** + * + * @param appData + * @return + * @throws IOException + */ + public byte[] wrap(byte[] appData) throws IOException { + return wrap(appData, 0, appData.length); + } + + /** + * + * @param appData + * @param off + * @param len + * @return + * @throws IOException + */ + public byte[] wrap(byte[] appData, int off, int len) throws IOException { + if (! isHandshakeFinished()) { + return null; + } + + tlsHandler.getOutputStream().write(appData, off, len); + return drainNetOutStream(); + } + + /** + * + * @param netData + * @return + * @throws IOException + */ + public byte[] unwrap(byte[] netData) throws IOException { + return unwrap(netData, 0, netData.length); + } + + /** + * + * @param netData + * @param off + * @param len + * @return + * @throws IOException + */ + public byte[] unwrap(byte[] netData, int off, int len) throws IOException { + if (! isHandshakeFinished()) { + return null; + } + + if (netData.length == 0) { + return null; + } + + netInStream.getOutputStream().write(netData, off, len); + + // Force the record to be processed in order to put an unknown + // amount of data in the application queue. It's assumed that + // the netData parameter is a full SSL record; if it's not, then + // this method will block indefinitely + byte[] tmp = new byte[1]; + tlsHandler.getInputStream().read(tmp, 0, 1); + + int avail = tlsHandler.getApplicationDataQueueSize(); + + if (avail == 0) { + return tmp; + } + + byte[] appBuf = new byte[avail + 1]; + appBuf[0] = tmp[0]; + tlsHandler.getInputStream().read(appBuf, 1, avail); + + return appBuf; + } + + /** + * + * @return + * @throws java.io.IOException + */ + public byte[] close() throws IOException { + tlsHandler.close(); + return drainNetOutStream(); + } + + /** + * + * @return + */ + public boolean isHandshakeFinished() { + return this.tlsHandler.isHandshakeFinished(); + } + + /** + * + * @return + */ + private byte[] drainNetOutStream() { + byte[] rval = netOutStream.toByteArray(); + netOutStream.reset(); + return rval; + } + + /** + * + * @param b + */ + private synchronized void setConnectionThreadStarted(boolean b) { + connectionThreadStarted = b; + } + + /** + * + * @return + */ + private synchronized boolean isConnectionThreadStarted() { + return connectionThreadStarted; + } + + /** + * + * @return + */ + private IOException getConnectionThreadException() { + return connectionThreadException; + } + + /** + * + * @param e + */ + private void setConnectionThreadException(IOException e) { + this.connectionThreadException = e; + } + + /** + * + */ + private class ConnectionThread extends Thread { + /** + * + */ + public void run() { + setConnectionThreadStarted(true); + try { + tlsHandler.connect(tlsClient); + } catch (IOException e) { + setConnectionThreadException(e); + } + //System.out.println("TLS connection thread done"); + } + } +}
Added: airavata/sandbox/gsissh/src/main/java/org/apache/airavata/gsi/ssh/GSSContextX509.java URL: http://svn.apache.org/viewvc/airavata/sandbox/gsissh/src/main/java/org/apache/airavata/gsi/ssh/GSSContextX509.java?rev=1512378&view=auto ============================================================================== --- airavata/sandbox/gsissh/src/main/java/org/apache/airavata/gsi/ssh/GSSContextX509.java (added) +++ airavata/sandbox/gsissh/src/main/java/org/apache/airavata/gsi/ssh/GSSContextX509.java Fri Aug 9 16:24:07 2013 @@ -0,0 +1,215 @@ +package org.apache.airavata.gsi.ssh; + +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* + * Copyright (c) 2004,2005,2006 ymnk, JCraft,Inc. All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. The names of the authors may not + * be used to endorse or promote products derived from this software without + * specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND + * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, INC. OR ANY CONTRIBUTORS TO THIS + * SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +import java.io.File; +import java.io.FileInputStream; +import java.net.InetAddress; +import java.net.UnknownHostException; + +import edu.illinois.ncsa.BCGSS.BCGSSContextImpl; +import org.globus.common.CoGProperties; +import org.globus.gsi.GSIConstants; +import org.globus.gsi.gssapi.GSSConstants; +import org.globus.gsi.gssapi.GlobusGSSContextImpl; +import org.globus.gsi.gssapi.GlobusGSSCredentialImpl; +import org.globus.gsi.gssapi.auth.HostAuthorization; +import org.globus.myproxy.MyProxy; +import org.globus.myproxy.MyProxyException; +import org.gridforum.jgss.ExtendedGSSContext; +import org.gridforum.jgss.ExtendedGSSCredential; +import org.gridforum.jgss.ExtendedGSSManager; +import org.ietf.jgss.*; + +import com.jcraft.jsch.JSchException; + +/** + * This class is based on GSSContextKrb5; it substitutes the globus + * ExtendedGSSManager and uses the SecurityUtils method to get the credential if + * one is not passed in from memory. + * + * @author Al Rossi + * @author Jeff Overbey + */ +public class GSSContextX509 implements com.jcraft.jsch.GSSContext { + + private GSSContext context = null; + private GSSCredential credential; + + public void create(String user, String host) throws JSchException { + System.out.printf("Attempting GSI authentication for %s on %s\n", user, host); + + try { +// ExtendedGSSManager manager = (ExtendedGSSManager) ExtendedGSSManager.getInstance(); + + if (credential == null) { + try { + credential = getMyProxyCredentials(); + } catch (SecurityException t) { + System.out.printf("Could not get proxy: %s: %s\n", t.getClass().getSimpleName(), t.getMessage()); + throw new JSchException(t.toString()); + } + } + + String cname = host; + + try { + cname = InetAddress.getByName(cname).getCanonicalHostName(); + } catch (UnknownHostException e) { + } + + GSSName name = HostAuthorization.getInstance().getExpectedName(credential, cname); + +// context = manager.createContext(name, null, credential, GSSContext.DEFAULT_LIFETIME); +// +// // RFC4462 3.4. GSS-API Session +// // +// // When calling GSS_Init_sec_context(), the client MUST set +// // integ_req_flag to "true" to request that per-message integrity +// // protection be supported for this context. In addition, +// // deleg_req_flag MAY be set to "true" to request access delegation, +// // if +// // requested by the user. +// // +// // Since the user authentication process by its nature authenticates +// // only the client, the setting of mutual_req_flag is not needed for +// // this process. This flag SHOULD be set to "false". +// +// // TODO: OpenSSH's sshd does accept 'false' for mutual_req_flag +// // context.requestMutualAuth(false); +// context.requestMutualAuth(true); +// context.requestConf(true); +// context.requestInteg(true); // for MIC +// context.requestCredDeleg(true); +// context.requestAnonymity(false); + + context = new BCGSSContextImpl(name, (GlobusGSSCredentialImpl) credential); + context.requestLifetime(GSSCredential.DEFAULT_LIFETIME); + context.requestCredDeleg(true); + context.requestMutualAuth(true); + context.requestReplayDet(true); + context.requestSequenceDet(true); + context.requestConf(false); + context.requestInteg(true); + ((ExtendedGSSContext)context).setOption(GSSConstants.DELEGATION_TYPE, GSIConstants.DELEGATION_TYPE_FULL); + + return; + } catch (GSSException ex) { + throw new JSchException(ex.toString()); + } + } + + private static GSSCredential getProxy() { + return getProxy(null, GSSCredential.DEFAULT_LIFETIME); + } + + private static GSSCredential getMyProxyCredentials() throws JSchException { + MyProxy myproxy = new MyProxy("myproxy.teragrid.org", 7512); + try { + return myproxy.get("xxx", "xxx", 17280000); + } catch (MyProxyException e) { + throw new JSchException("Error getting proxy credentials", e); + } + } + + /** + * @param x509_USER_PROXY + * path to the proxy. + * @param credentialLifetime + * in seconds. + * @return valid credential. + * if proxy task throws exception (or if proxy cannot be found). + */ + private static GSSCredential getProxy(String x509_USER_PROXY, int credentialLifetime) throws SecurityException { + if (x509_USER_PROXY == null) + x509_USER_PROXY = System.getProperty("x509.user.proxy"); + +// if (x509_USER_PROXY == null) { +// SystemUtils.envToProperties(); +// x509_USER_PROXY = System.getProperty("x509.user.proxy"); +// } + + if (x509_USER_PROXY == null || "".equals(x509_USER_PROXY)) + x509_USER_PROXY = CoGProperties.getDefault().getProxyFile(); + + if (x509_USER_PROXY == null) + throw new SecurityException("could not get credential; no location defined"); + + ExtendedGSSManager manager = (ExtendedGSSManager) ExtendedGSSManager.getInstance(); + + // file...load file into a buffer + try { + File f = new File(x509_USER_PROXY); + byte[] data = new byte[(int) f.length()]; + FileInputStream in = new FileInputStream(f); + // read in the credential data + in.read(data); + in.close(); + return manager.createCredential(data, ExtendedGSSCredential.IMPEXP_OPAQUE, credentialLifetime, null, // use + // default + // mechanism + // - + // GSI + GSSCredential.INITIATE_AND_ACCEPT); + } catch (Throwable t) { + throw new SecurityException("could not get credential from " + x509_USER_PROXY, t); + } + } + + public boolean isEstablished() { + // this must check to see if the call returned GSS_S_COMPLETE + return context.isEstablished(); + } + + public byte[] init(byte[] token, int s, int l) throws JSchException { + try { + return context.initSecContext(token, s, l); + } catch (GSSException ex) { + throw new JSchException(ex.toString()); + } + } + + public byte[] getMIC(byte[] message, int s, int l) { + try { + MessageProp prop = new MessageProp(0, false); + return context.getMIC(message, s, l, prop); + } catch (GSSException ex) { + ex.printStackTrace(); + return null; + } + } + + public void dispose() { + try { + context.dispose(); + } catch (GSSException ex) { + } + } + + public void setCredential(GSSCredential credential) { + this.credential = credential; + } +} + Added: airavata/sandbox/gsissh/src/main/java/org/apache/airavata/gsi/ssh/SSHGSSContextImpl.java URL: http://svn.apache.org/viewvc/airavata/sandbox/gsissh/src/main/java/org/apache/airavata/gsi/ssh/SSHGSSContextImpl.java?rev=1512378&view=auto ============================================================================== --- airavata/sandbox/gsissh/src/main/java/org/apache/airavata/gsi/ssh/SSHGSSContextImpl.java (added) +++ airavata/sandbox/gsissh/src/main/java/org/apache/airavata/gsi/ssh/SSHGSSContextImpl.java Fri Aug 9 16:24:07 2013 @@ -0,0 +1,785 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.airavata.gsi.ssh; + +import org.globus.gsi.GSIConstants; +import org.globus.gsi.bc.BouncyCastleCertProcessingFactory; +import org.globus.gsi.bc.BouncyCastleUtil; +import org.globus.gsi.gssapi.GSSConstants; +import org.globus.gsi.gssapi.GlobusGSSCredentialImpl; +import org.globus.gsi.gssapi.GlobusGSSException; +import org.globus.gsi.gssapi.GlobusGSSName; +import org.globus.gsi.util.CertificateUtil; +import org.globus.gsi.util.ProxyCertificateUtil; +import org.gridforum.jgss.ExtendedGSSContext; +import org.ietf.jgss.*; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.GeneralSecurityException; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.Map; + +/** + * User: AmilaJ ([email protected]) + * Date: 8/8/13 + * Time: 7:03 PM + */ + +public class SSHGSSContextImpl implements ExtendedGSSContext { + + //============= Following Options are set through setOptions method ==================// + protected Integer gssMode = GSIConstants.MODE_GSI; + + protected GSIConstants.DelegationType delegationType = + GSIConstants.DelegationType.LIMITED; + + protected Boolean checkContextExpiration = Boolean.FALSE; + + protected Boolean rejectLimitedProxy = Boolean.FALSE; + + protected Boolean requireClientAuth = Boolean.TRUE; + + protected Map proxyPolicyHandlers; + + protected Boolean acceptNoClientCerts = Boolean.FALSE; + + protected Boolean requireAuthzWithDelegation = Boolean.TRUE; + + //====================================================================================// + + protected boolean delegationFinished = false; + + protected boolean conn = false; + + // gss context state variables + protected boolean credentialDelegation = false; + protected boolean anonymity = false; + protected boolean encryption = false; + protected boolean established = false; + + /** + * Credential of this context. Might be anonymous + */ + protected GlobusGSSCredentialImpl ctxCred; + + protected BouncyCastleCertProcessingFactory certFactory; + + /* handshake states */ + private static final int + HANDSHAKE = 0, + CLIENT_START_DEL = 2, + CLIENT_END_DEL = 3; + + protected int state = HANDSHAKE; + + /** + * Limited peer credentials + */ + protected Boolean peerLimited = null; + + 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}); + } + + } + + //============== Set Option Methods =====================// + + 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"); + } + } + + 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"); + } + } + + 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; + } + + 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; + } + + 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; + } + + 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; + } + + 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; + } + + 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; + } + + //============== Set Option Methods =====================// + + + 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; + } + + public byte[] initDelegation(GSSCredential credential, Oid mechanism, + int lifetime, byte[] buf, int off, int len) + throws GSSException { + //TODO: implement this + return new byte[0]; + } + + public byte[] acceptDelegation(int i, byte[] bytes, int i1, int i2) + throws GSSException { + throw new GSSException(GSSException.UNAVAILABLE); + } + + /** + * TODO we need to implement delegation + * @return At the moment null + */ + public GSSCredential getDelegatedCredential() { + return null; + } + + public boolean isDelegationFinished() { + // TODO properly implement delegation + 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) { + // TODO implement this later + } + + 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); + } + + /** + * 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 { return new byte[0]; } + /*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; + }*/ + + + public int initSecContext(InputStream inStream, OutputStream outStream) throws GSSException { + return 0; //To change body of implemented methods use File | Settings | File Templates. + } + + public byte[] acceptSecContext(byte[] inToken, int offset, int len) throws GSSException { + return new byte[0]; //To change body of implemented methods use File | Settings | File Templates. + } + + public void acceptSecContext(InputStream inStream, OutputStream outStream) throws GSSException { + //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isEstablished() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public void dispose() throws GSSException { + //To change body of implemented methods use File | Settings | File Templates. + } + + public int getWrapSizeLimit(int qop, boolean confReq, int maxTokenSize) throws GSSException { + return 0; //To change body of implemented methods use File | Settings | File Templates. + } + + public byte[] wrap(byte[] inBuf, int offset, int len, MessageProp msgProp) throws GSSException { + return new byte[0]; //To change body of implemented methods use File | Settings | File Templates. + } + + public void wrap(InputStream inStream, OutputStream outStream, MessageProp msgProp) throws GSSException { + //To change body of implemented methods use File | Settings | File Templates. + } + + public byte[] unwrap(byte[] inBuf, int offset, int len, MessageProp msgProp) throws GSSException { + return new byte[0]; //To change body of implemented methods use File | Settings | File Templates. + } + + public void unwrap(InputStream inStream, OutputStream outStream, MessageProp msgProp) throws GSSException { + //To change body of implemented methods use File | Settings | File Templates. + } + + public byte[] getMIC(byte[] inMsg, int offset, int len, MessageProp msgProp) throws GSSException { + return new byte[0]; //To change body of implemented methods use File | Settings | File Templates. + } + + public void getMIC(InputStream inStream, OutputStream outStream, MessageProp msgProp) throws GSSException { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void verifyMIC(byte[] inToken, int tokOffset, int tokLen, byte[] inMsg, int msgOffset, int msgLen, MessageProp msgProp) throws GSSException { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void verifyMIC(InputStream tokStream, InputStream msgStream, MessageProp msgProp) throws GSSException { + //To change body of implemented methods use File | Settings | File Templates. + } + + public byte[] export() throws GSSException { + return new byte[0]; //To change body of implemented methods use File | Settings | File Templates. + } + + public void requestMutualAuth(boolean state) throws GSSException { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void requestReplayDet(boolean state) throws GSSException { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void requestSequenceDet(boolean state) throws GSSException { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void requestCredDeleg(boolean state) throws GSSException { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void requestAnonymity(boolean state) throws GSSException { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void requestConf(boolean state) throws GSSException { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void requestInteg(boolean state) throws GSSException { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void requestLifetime(int lifetime) throws GSSException { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void setChannelBinding(ChannelBinding cb) throws GSSException { + //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean getCredDelegState() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean getMutualAuthState() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean getReplayDetState() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean getSequenceDetState() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean getAnonymityState() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isTransferable() throws GSSException { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isProtReady() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean getConfState() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean getIntegState() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public int getLifetime() { + return 0; //To change body of implemented methods use File | Settings | File Templates. + } + + public GSSName getSrcName() throws GSSException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public GSSName getTargName() throws GSSException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public Oid getMech() throws GSSException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public GSSCredential getDelegCred() throws GSSException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isInitiator() throws GSSException { + return false; //To change body of implemented methods use File | Settings | File Templates. + } +}
