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.TransportFactorySupport;
030    import org.apache.activemq.transport.TransportServer;
031    import org.apache.activemq.transport.tcp.SslTransportFactory;
032    
033    /**
034     * A BrokerService that allows access to the key and trust managers used by SSL
035     * connections. There is no reason to use this class unless SSL is being used
036     * AND the key and trust managers need to be specified from within code. In
037     * fact, if the URI passed to this class does not have an "ssl" scheme, this
038     * class will pass all work on to its superclass.
039     * 
040     * @author sepandm@gmail.com (Sepand)
041     */
042    public class SslBrokerService extends BrokerService {
043        /**
044         * Adds a new transport connector for the given bind address. If the
045         * transport created uses SSL, it will also use the key and trust managers
046         * provided. Otherwise, this is the same as calling addConnector.
047         * 
048         * @param bindAddress The address to bind to.
049         * @param km The KeyManager to be used.
050         * @param tm The trustmanager to be used.
051         * @param random The source of randomness for the generator.
052         * @return the newly connected and added transport connector.
053         * @throws Exception
054         */
055    
056        public TransportConnector addSslConnector(String bindAddress, KeyManager[] km, TrustManager[] tm, SecureRandom random) throws Exception {
057            return addSslConnector(new URI(bindAddress), km, tm, random);
058        }
059    
060        /**
061         * Adds a new transport connector for the given bind address. If the
062         * transport created uses SSL, it will also use the key and trust managers
063         * provided. Otherwise, this is the same as calling addConnector.
064         * 
065         * @param bindAddress The URI to bind to.
066         * @param km The KeyManager to be used.
067         * @param tm The trustmanager to be used.
068         * @param random The source of randomness for the generator.
069         * @return the newly created and added transport connector.
070         * @throws Exception
071         */
072        public TransportConnector addSslConnector(URI bindAddress, KeyManager[] km, TrustManager[] tm, SecureRandom random) throws Exception {
073            return addConnector(createSslTransportServer(bindAddress, km, tm, random));
074        }
075    
076        /**
077         * Creates a TransportServer that uses the given key and trust managers. The
078         * last three parameters will be eventually passed to SSLContext.init.
079         * 
080         * @param brokerURI The URI to bind to.
081         * @param km The KeyManager to be used.
082         * @param tm The trustmanager to be used.
083         * @param random The source of randomness for the generator.
084         * @return A new TransportServer that uses the given managers.
085         * @throws IOException If cannot handle URI.
086         * @throws KeyManagementException Passed on from SSL.
087         */
088        protected TransportServer createSslTransportServer(URI brokerURI, KeyManager[] km, TrustManager[] tm, SecureRandom random) throws IOException, KeyManagementException {
089    
090            if (brokerURI.getScheme().equals("ssl")) {
091                // If given an SSL URI, use an SSL TransportFactory and configure
092                // it to use the given key and trust managers.
093                SslTransportFactory transportFactory = new SslTransportFactory();
094                
095                SslContext ctx = new SslContext(km, tm, random);
096                SslContext.setCurrentSslContext(ctx);
097                try {
098                    return transportFactory.doBind(brokerURI);
099                } finally {
100                    SslContext.setCurrentSslContext(null);
101                }
102                
103            } else {
104                // Else, business as usual.
105                return TransportFactorySupport.bind(this, brokerURI);
106            }
107        }
108    }