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 package org.apache.activemq.security;
018
019 import java.security.Principal;
020 import java.util.HashSet;
021 import java.util.Iterator;
022 import java.util.Map;
023 import java.util.Set;
024 import java.util.concurrent.CopyOnWriteArrayList;
025
026 import org.apache.activemq.broker.Broker;
027 import org.apache.activemq.broker.BrokerFilter;
028 import org.apache.activemq.broker.ConnectionContext;
029 import org.apache.activemq.command.ConnectionInfo;
030 import org.apache.activemq.jaas.GroupPrincipal;
031
032 /**
033 * Handles authenticating a users against a simple user name/password map.
034 *
035 *
036 */
037 public class SimpleAuthenticationBroker extends BrokerFilter {
038
039 private boolean anonymousAccessAllowed = false;
040 private String anonymousUser;
041 private String anonymousGroup;
042 private final Map<String,String> userPasswords;
043 private final Map<String,Set<Principal>> userGroups;
044 private final CopyOnWriteArrayList<SecurityContext> securityContexts = new CopyOnWriteArrayList<SecurityContext>();
045
046 public SimpleAuthenticationBroker(Broker next, Map<String,String> userPasswords, Map<String,Set<Principal>> userGroups) {
047 super(next);
048 this.userPasswords = userPasswords;
049 this.userGroups = userGroups;
050 }
051
052 public void setAnonymousAccessAllowed(boolean anonymousAccessAllowed) {
053 this.anonymousAccessAllowed = anonymousAccessAllowed;
054 }
055
056 public void setAnonymousUser(String anonymousUser) {
057 this.anonymousUser = anonymousUser;
058 }
059
060 public void setAnonymousGroup(String anonymousGroup) {
061 this.anonymousGroup = anonymousGroup;
062 }
063
064 public void addConnection(ConnectionContext context, ConnectionInfo info) throws Exception {
065
066 SecurityContext s = context.getSecurityContext();
067 if (s == null) {
068 // Check the username and password.
069 if (anonymousAccessAllowed && info.getUserName() == null && info.getPassword() == null) {
070 info.setUserName(anonymousUser);
071 s = new SecurityContext(info.getUserName()) {
072 public Set<Principal> getPrincipals() {
073 Set<Principal> groups = new HashSet<Principal>();
074 groups.add(new GroupPrincipal(anonymousGroup));
075 return groups;
076 }
077 };
078 } else {
079 String pw = userPasswords.get(info.getUserName());
080 if (pw == null || !pw.equals(info.getPassword())) {
081 throw new SecurityException(
082 "User name [" + info.getUserName() + "] or password is invalid.");
083 }
084
085 final Set<Principal> groups = userGroups.get(info.getUserName());
086 s = new SecurityContext(info.getUserName()) {
087 public Set<Principal> getPrincipals() {
088 return groups;
089 }
090 };
091 }
092
093 context.setSecurityContext(s);
094 securityContexts.add(s);
095 }
096 try {
097 super.addConnection(context, info);
098 } catch (Exception e) {
099 securityContexts.remove(s);
100 context.setSecurityContext(null);
101 throw e;
102 }
103 }
104
105 public void removeConnection(ConnectionContext context, ConnectionInfo info, Throwable error)
106 throws Exception {
107 super.removeConnection(context, info, error);
108 if (securityContexts.remove(context.getSecurityContext())) {
109 context.setSecurityContext(null);
110 }
111 }
112
113 /**
114 * Previously logged in users may no longer have the same access anymore.
115 * Refresh all the logged into users.
116 */
117 public void refresh() {
118 for (Iterator<SecurityContext> iter = securityContexts.iterator(); iter.hasNext();) {
119 SecurityContext sc = iter.next();
120 sc.getAuthorizedReadDests().clear();
121 sc.getAuthorizedWriteDests().clear();
122 }
123 }
124
125 }