blob: 24d7c438bc2d23129ea8b6fdb56b7f652a9e1ede [file] [log] [blame]
/*
*
* 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.qpid.proton.engine.impl.ssl;
import java.nio.ByteBuffer;
import org.apache.qpid.proton.ProtonUnsupportedOperationException;
import org.apache.qpid.proton.engine.Ssl;
import org.apache.qpid.proton.engine.SslDomain;
import org.apache.qpid.proton.engine.SslDomain.VerifyMode;
import org.apache.qpid.proton.engine.SslPeerDetails;
import org.apache.qpid.proton.engine.Transport;
import org.apache.qpid.proton.engine.TransportException;
import org.apache.qpid.proton.engine.impl.PlainTransportWrapper;
import org.apache.qpid.proton.engine.impl.TransportInput;
import org.apache.qpid.proton.engine.impl.TransportLayer;
import org.apache.qpid.proton.engine.impl.TransportOutput;
import org.apache.qpid.proton.engine.impl.TransportWrapper;
public class SslImpl implements Ssl, TransportLayer
{
private SslTransportWrapper _unsecureClientAwareTransportWrapper;
private final SslDomain _domain;
private final ProtonSslEngineProvider _protonSslEngineProvider;
private final SslPeerDetails _peerDetails;
private TransportException _initException;
/**
* @param domain must implement {@link org.apache.qpid.proton.engine.impl.ssl.ProtonSslEngineProvider}. This is not possible
* enforce at the API level because {@link org.apache.qpid.proton.engine.impl.ssl.ProtonSslEngineProvider} is not part of the
* public Proton API.
*/
public SslImpl(SslDomain domain, SslPeerDetails peerDetails)
{
_domain = domain;
_protonSslEngineProvider = (ProtonSslEngineProvider)domain;
_peerDetails = peerDetails;
if(_domain.getMode() == null) {
throw new IllegalStateException("Client/server mode must be configured, SslDomain must have init called.");
}
if(_peerDetails == null && _domain.getPeerAuthentication() == VerifyMode.VERIFY_PEER_NAME) {
throw new IllegalArgumentException("Peer hostname verification is enabled, but no peer details were provided");
}
}
public TransportWrapper wrap(TransportInput inputProcessor, TransportOutput outputProcessor)
{
if (_unsecureClientAwareTransportWrapper != null)
{
throw new IllegalStateException("Transport already wrapped");
}
_unsecureClientAwareTransportWrapper = new UnsecureClientAwareTransportWrapper(inputProcessor, outputProcessor);
return _unsecureClientAwareTransportWrapper;
}
@Override
public String getCipherName()
{
if(_unsecureClientAwareTransportWrapper == null)
{
throw new IllegalStateException("Transport wrapper is uninitialised");
}
return _unsecureClientAwareTransportWrapper.getCipherName();
}
@Override
public String getProtocolName()
{
if(_unsecureClientAwareTransportWrapper == null)
{
throw new IllegalStateException("Transport wrapper is uninitialised");
}
return _unsecureClientAwareTransportWrapper.getProtocolName();
}
private class UnsecureClientAwareTransportWrapper implements SslTransportWrapper
{
private final TransportInput _inputProcessor;
private final TransportOutput _outputProcessor;
private SslTransportWrapper _transportWrapper;
private UnsecureClientAwareTransportWrapper(TransportInput inputProcessor,
TransportOutput outputProcessor)
{
_inputProcessor = inputProcessor;
_outputProcessor = outputProcessor;
}
@Override
public int capacity()
{
initTransportWrapperOnFirstIO();
if (_initException == null) {
return _transportWrapper.capacity();
} else {
return Transport.END_OF_STREAM;
}
}
@Override
public int position()
{
initTransportWrapperOnFirstIO();
if (_initException == null) {
return _transportWrapper.position();
} else {
return Transport.END_OF_STREAM;
}
}
@Override
public ByteBuffer tail()
{
initTransportWrapperOnFirstIO();
if (_initException == null) {
return _transportWrapper.tail();
} else {
return null;
}
}
@Override
public void process() throws TransportException
{
initTransportWrapperOnFirstIO();
if (_initException == null) {
_transportWrapper.process();
} else {
throw new TransportException(_initException);
}
}
@Override
public void close_tail()
{
initTransportWrapperOnFirstIO();
if (_initException == null) {
_transportWrapper.close_tail();
}
}
@Override
public int pending()
{
initTransportWrapperOnFirstIO();
if (_initException == null) {
return _transportWrapper.pending();
} else {
throw new TransportException(_initException);
}
}
@Override
public ByteBuffer head()
{
initTransportWrapperOnFirstIO();
if (_initException == null) {
return _transportWrapper.head();
} else {
return null;
}
}
@Override
public void pop(int bytes)
{
initTransportWrapperOnFirstIO();
if (_initException == null) {
_transportWrapper.pop(bytes);
}
}
@Override
public void close_head()
{
initTransportWrapperOnFirstIO();
if (_initException == null) {
_transportWrapper.close_head();
}
}
@Override
public String getCipherName()
{
if (_transportWrapper == null)
{
return null;
}
else
{
return _transportWrapper.getCipherName();
}
}
@Override
public String getProtocolName()
{
if(_transportWrapper == null)
{
return null;
}
else
{
return _transportWrapper.getProtocolName();
}
}
private void initTransportWrapperOnFirstIO()
{
try {
if (_initException == null && _transportWrapper == null)
{
SslTransportWrapper sslTransportWrapper = new SimpleSslTransportWrapper
(_protonSslEngineProvider.createSslEngine(_peerDetails),
_inputProcessor, _outputProcessor);
if (_domain.allowUnsecuredClient() && _domain.getMode() == SslDomain.Mode.SERVER)
{
TransportWrapper plainTransportWrapper = new PlainTransportWrapper
(_outputProcessor, _inputProcessor);
_transportWrapper = new SslHandshakeSniffingTransportWrapper
(sslTransportWrapper, plainTransportWrapper);
}
else
{
_transportWrapper = sslTransportWrapper;
}
}
} catch (TransportException e) {
_initException = e;
}
}
}
/**
* {@inheritDoc}
* @throws ProtonUnsupportedOperationException
*/
@Override
public void setPeerHostname(String hostname)
{
throw new ProtonUnsupportedOperationException();
}
/**
* {@inheritDoc}
* @throws ProtonUnsupportedOperationException
*/
@Override
public String getPeerHostname()
{
throw new ProtonUnsupportedOperationException();
}
}