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