View Javadoc

1   /**
2    * This file Copyright (c) 2003-2011 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.jaas.sp.jcr;
35  
36  import info.magnolia.cms.security.ACLImpl;
37  import info.magnolia.cms.security.MgnlUser;
38  import info.magnolia.cms.security.Permission;
39  import info.magnolia.cms.security.PrincipalUtil;
40  import info.magnolia.cms.security.SecuritySupport;
41  import info.magnolia.cms.security.User;
42  import info.magnolia.cms.security.auth.ACL;
43  import info.magnolia.cms.security.auth.GroupList;
44  import info.magnolia.cms.security.auth.PrincipalCollection;
45  import info.magnolia.cms.security.auth.PrincipalCollectionImpl;
46  import info.magnolia.cms.security.auth.RoleList;
47  import info.magnolia.jaas.principal.GroupListImpl;
48  import info.magnolia.jaas.principal.RoleListImpl;
49  import info.magnolia.jaas.sp.AbstractLoginModule;
50  
51  import java.security.Principal;
52  import java.util.ArrayList;
53  import java.util.Collection;
54  import java.util.HashSet;
55  import java.util.Iterator;
56  
57  import javax.security.auth.login.LoginException;
58  
59  import org.apache.commons.lang.ArrayUtils;
60  import org.slf4j.Logger;
61  import org.slf4j.LoggerFactory;
62  
63  
64  /**
65   * This is a default login module for magnolia, it uses initialized repository as defined by the provider interface.
66   * @author Sameer Charles
67   * @version $Id: JCRAuthorizationModule.java 50229 2011-10-20 16:10:16Z tmattsson $
68   */
69  public class JCRAuthorizationModule extends AbstractLoginModule {
70  
71      @Override
72      public void validateUser() throws LoginException {
73      }
74  
75      private static final Logger log = LoggerFactory.getLogger(JCRAuthorizationModule.class);
76  
77      // do nothing here, we are only responsible for authorization, not authentication!
78      @Override
79      public boolean login() throws LoginException
80      {
81          this.success = true;
82          this.setSharedStatus(STATUS_SUCCEEDED);
83          return this.success;
84      }
85  
86      /**
87       * Sets access control list from the user, roles and groups.
88       */
89      @Override
90      public void setACL() {
91          String[] roles = getRoleNames().toArray(new String[getRoleNames().size()]);
92          String[] groups = getGroupNames().toArray(new String[getGroupNames().size()]);
93  
94          if (log.isDebugEnabled()) {
95              log.debug("Roles: {}", ArrayUtils.toString(roles));
96              log.debug("Groups: {}", ArrayUtils.toString(groups));
97          }
98  
99          addRoles(roles);
100         addGroups(groups);
101 
102         PrincipalCollection principalList = new PrincipalCollectionImpl();
103         setACLForRoles(roles, principalList);
104         setACLForGroups(groups, principalList);
105         User user = null;
106 
107         // can't obtain SS instance at creation time as repo is not initialized yet and class can't be instantiated.
108         SecuritySupport securitySupport = SecuritySupport.Factory.getInstance();
109         user = PrincipalUtil.findPrincipal(subject, User.class);
110         // not all jaas modules will support magnolia users
111         if(user == null) {
112             user = securitySupport.getUserManager().getUser(subject);
113         }
114 
115         if (user instanceof MgnlUser) {
116             setACLForUser(principalList, user, securitySupport);
117         }
118 
119         if (log.isDebugEnabled()) {
120             for (Iterator<Principal> iterator =  principalList.iterator(); iterator.hasNext();) {
121                 Principal principal = iterator.next();
122                 log.debug("ACL: {}", principal);
123             }
124         }
125 
126         // set principal list, a set of info.magnolia.jaas.principal.ACL
127         this.subject.getPrincipals().add(principalList);
128     }
129 
130     protected void setACLForUser(PrincipalCollection principalList, User user, SecuritySupport securitySupport) {
131         Collection<ACL> principals = securitySupport.getUserManager(((MgnlUser) user).getRealm()).getACLs(user).values();
132         mergePrincipals(principalList, principals);
133     }
134 
135     private void mergePrincipals(PrincipalCollection principalList, Collection<ACL> principals) {
136         for (ACL princ : principals) {
137             if (principalList.contains(princ.getName())) {
138                 ACL oldACL = (ACL) principalList.get(princ.getName());
139                 Collection<Permission> permissions = new HashSet<Permission>(oldACL.getList());
140                 permissions.addAll(princ.getList());
141                 principalList.remove(oldACL);
142                 princ = new ACLImpl(princ.getName(), new ArrayList<Permission>(permissions));
143             }
144             principalList.add(princ);
145         }
146     }
147 
148     // do nothing here, we are only responsible for adding ACL passed on via shared state
149     @Override
150     public void setEntity() {}
151 
152     /**
153      * Sets the list of groups, <code>info.magnolia.jaas.principal.GroupList</code>.
154      * @param groups array of group names
155      */
156     protected void addGroups(String[] groups) {
157         GroupList groupList = new GroupListImpl();
158         for (Iterator<String> iterator = getGroupNames().iterator(); iterator.hasNext();) {
159             String group = iterator.next();
160             groupList.add(group);
161         }
162         this.subject.getPrincipals().add(groupList);
163     }
164 
165     /**
166      * Sets the list of roles, <code>info.magnolia.jaas.principal.RoleList</code>.
167      * @param roles array of role names
168      */
169     protected void addRoles(String[] roles) {
170         RoleList roleList = new RoleListImpl();
171         for (Iterator<String> iterator = getRoleNames().iterator(); iterator.hasNext();) {
172             String role = iterator.next();
173             roleList.add(role);
174         }
175         this.subject.getPrincipals().add(roleList);
176     }
177 
178     /**
179      * Looks for role configured in magnolia repository with the given name, and configures ACLs for it.
180      * @param roles array of role names.
181      * @param principalList PrincipalCollection
182      */
183     protected void setACLForRoles(String[] roles, PrincipalCollection principalList) {
184         SecuritySupport securitySupport = SecuritySupport.Factory.getInstance();
185         for (String role : roles) {
186             mergePrincipals(principalList, securitySupport.getRoleManager().getACLs(role).values());
187         }
188     }
189 
190     /**
191      * Looks for groups configured in magnolia repository with the given name, and configures ACLs for it.
192      * @param groups array of group names.
193      * @param principalList PrincipalCollection
194      */
195     protected void setACLForGroups(String[] groups, PrincipalCollection principalList) {
196         SecuritySupport securitySupport = SecuritySupport.Factory.getInstance();
197 
198         for (String group : groups) {
199             mergePrincipals(principalList, securitySupport.getGroupManager().getACLs(group).values());
200         }
201     }
202 }