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.security;
019
020 import org.apache.activemq.broker.Broker;
021 import org.apache.activemq.broker.BrokerFilter;
022 import org.apache.activemq.broker.ConnectionContext;
023 import org.apache.activemq.broker.Connector;
024 import org.apache.activemq.broker.EmptyBroker;
025 import org.apache.activemq.broker.TransportConnector;
026 import org.apache.activemq.command.ConnectionInfo;
027 import org.apache.activemq.transport.tcp.SslTransportServer;
028
029 /**
030 * A JAAS Authentication Broker that uses different JAAS domain configurations
031 * depending if the connection is over an SSL enabled Connector or not.
032 *
033 * This allows you to, for instance, do DN based authentication for SSL connections
034 * and use a mixture of username/passwords and simple guest authentication for
035 * non-SSL connections.
036 * <p>
037 * An example <code>login.config</code> to do do this is:
038 * <pre>
039 * activemq-domain {
040 * org.apache.activemq.jaas.PropertiesLoginModule sufficient
041 * debug=true
042 * org.apache.activemq.jaas.properties.user="users.properties"
043 * org.apache.activemq.jaas.properties.group="groups.properties";
044 * org.apache.activemq.jaas.GuestLoginModule sufficient
045 * debug=true
046 * org.apache.activemq.jaas.guest.user="guest"
047 * org.apache.activemq.jaas.guest.group="guests";
048 * };
049 *
050 * activemq-ssl-domain {
051 * org.apache.activemq.jaas.TextFileCertificateLoginModule required
052 * debug=true
053 * org.apache.activemq.jaas.textfiledn.user="dns.properties"
054 * org.apache.activemq.jaas.textfiledn.group="groups.properties";
055 * };
056 * </pre>
057 */
058 public class JaasDualAuthenticationBroker extends BrokerFilter {
059 private final JaasCertificateAuthenticationBroker sslBroker;
060 private final JaasAuthenticationBroker nonSslBroker;
061
062
063 /*** Simple constructor. Leaves everything to superclass.
064 *
065 * @param next The Broker that does the actual work for this Filter.
066 * @param jaasConfiguration The JAAS domain configuration name for
067 * non-SSL connections (refer to JAAS documentation).
068 * @param jaasSslConfiguration The JAAS domain configuration name for
069 * SSL connections (refer to JAAS documentation).
070 */
071 public JaasDualAuthenticationBroker(Broker next, String jaasConfiguration, String jaasSslConfiguration) {
072 super(next);
073
074 this.nonSslBroker = new JaasAuthenticationBroker(new EmptyBroker(), jaasConfiguration);
075 this.sslBroker = new JaasCertificateAuthenticationBroker(new EmptyBroker(), jaasSslConfiguration);
076 }
077
078 /**
079 * Overridden to allow for authentication using different Jaas
080 * configurations depending on if the connection is SSL or not.
081 *
082 * @param context The context for the incoming Connection.
083 * @param info The ConnectionInfo Command representing the incoming
084 * connection.
085 */
086 public void addConnection(ConnectionContext context, ConnectionInfo info) throws Exception {
087 if (context.getSecurityContext() == null) {
088 boolean isSSL;
089 Connector connector = context.getConnector();
090 if (connector instanceof TransportConnector) {
091 TransportConnector transportConnector = (TransportConnector) connector;
092 isSSL = transportConnector.getServer().isSslServer();
093 } else {
094 isSSL = false;
095 }
096
097 if (isSSL) {
098 this.sslBroker.addConnection(context, info);
099 } else {
100 this.nonSslBroker.addConnection(context, info);
101 }
102 super.addConnection(context, info);
103 }
104 }
105
106 /**
107 * Overriding removeConnection to make sure the security context is cleaned.
108 */
109 public void removeConnection(ConnectionContext context, ConnectionInfo info, Throwable error) throws Exception {
110 boolean isSSL;
111 Connector connector = context.getConnector();
112 if (connector instanceof TransportConnector) {
113 TransportConnector transportConnector = (TransportConnector) connector;
114 isSSL = (transportConnector.getServer() instanceof SslTransportServer);
115 } else {
116 isSSL = false;
117 }
118 super.removeConnection(context, info, error);
119 if (isSSL) {
120 this.sslBroker.removeConnection(context, info, error);
121 } else {
122 this.nonSslBroker.removeConnection(context, info, error);
123 }
124 }
125 }