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    
018    package org.apache.activemq.broker;
019    
020    import java.io.IOException;
021    import java.net.URI;
022    import java.security.KeyManagementException;
023    import java.security.SecureRandom;
024    
025    import javax.net.ssl.KeyManager;
026    import javax.net.ssl.TrustManager;
027    
028    import org.apache.activemq.transport.TransportFactory;
029    import org.apache.activemq.transport.TransportServer;
030    import 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     */
041    public 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 TransportFactory.bind(this, brokerURI);
105            }
106        }
107    }