001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.activemq.broker;
019
020import java.io.IOException;
021import java.net.URI;
022import java.security.KeyManagementException;
023import java.security.SecureRandom;
024
025import javax.net.ssl.KeyManager;
026import javax.net.ssl.TrustManager;
027
028import org.apache.activemq.transport.TransportFactorySupport;
029import org.apache.activemq.transport.TransportServer;
030import org.apache.activemq.transport.tcp.SslTransportFactory;
031
032/**
033 * A BrokerService that allows access to the key and trust managers used by SSL
034 * connections. There is no reason to use this class unless SSL is being used
035 * AND the key and trust managers need to be specified from within code. In
036 * fact, if the URI passed to this class does not have an "ssl" scheme, this
037 * class will pass all work on to its superclass.
038 * 
039 * @author sepandm@gmail.com (Sepand)
040 */
041public class SslBrokerService extends BrokerService {
042    /**
043     * Adds a new transport connector for the given bind address. If the
044     * transport created uses SSL, it will also use the key and trust managers
045     * provided. Otherwise, this is the same as calling addConnector.
046     * 
047     * @param bindAddress The address to bind to.
048     * @param km The KeyManager to be used.
049     * @param tm The trustmanager to be used.
050     * @param random The source of randomness for the generator.
051     * @return the newly connected and added transport connector.
052     * @throws Exception
053     */
054
055    public TransportConnector addSslConnector(String bindAddress, KeyManager[] km, TrustManager[] tm, SecureRandom random) throws Exception {
056        return addSslConnector(new URI(bindAddress), km, tm, random);
057    }
058
059    /**
060     * Adds a new transport connector for the given bind address. If the
061     * transport created uses SSL, it will also use the key and trust managers
062     * provided. Otherwise, this is the same as calling addConnector.
063     * 
064     * @param bindAddress The URI to bind to.
065     * @param km The KeyManager to be used.
066     * @param tm The trustmanager to be used.
067     * @param random The source of randomness for the generator.
068     * @return the newly created and added transport connector.
069     * @throws Exception
070     */
071    public TransportConnector addSslConnector(URI bindAddress, KeyManager[] km, TrustManager[] tm, SecureRandom random) throws Exception {
072        return addConnector(createSslTransportServer(bindAddress, km, tm, random));
073    }
074
075    /**
076     * Creates a TransportServer that uses the given key and trust managers. The
077     * last three parameters will be eventually passed to SSLContext.init.
078     * 
079     * @param brokerURI The URI to bind to.
080     * @param km The KeyManager to be used.
081     * @param tm The trustmanager to be used.
082     * @param random The source of randomness for the generator.
083     * @return A new TransportServer that uses the given managers.
084     * @throws IOException If cannot handle URI.
085     * @throws KeyManagementException Passed on from SSL.
086     */
087    protected TransportServer createSslTransportServer(URI brokerURI, KeyManager[] km, TrustManager[] tm, SecureRandom random) throws IOException, KeyManagementException {
088
089        if (brokerURI.getScheme().equals("ssl")) {
090            // If given an SSL URI, use an SSL TransportFactory and configure
091            // it to use the given key and trust managers.
092            SslTransportFactory transportFactory = new SslTransportFactory();
093            
094            SslContext ctx = new SslContext(km, tm, random);
095            SslContext.setCurrentSslContext(ctx);
096            try {
097                return transportFactory.doBind(brokerURI);
098            } finally {
099                SslContext.setCurrentSslContext(null);
100            }
101            
102        } else {
103            // Else, business as usual.
104            return TransportFactorySupport.bind(this, brokerURI);
105        }
106    }
107}