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