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