1 /*
   2  * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 
  27 package com.sun.jmx.snmp.IPAcl;
  28 
  29 
  30 
  31 import java.security.Principal;
  32 import java.security.acl.Acl;
  33 import java.security.acl.AclEntry;
  34 import java.security.acl.NotOwnerException;
  35 
  36 import java.io.Serializable;
  37 import java.security.acl.Permission;
  38 import java.util.Vector;
  39 import java.util.Enumeration;
  40 
  41 
  42 /**
  43  * Represent an Access Control List (ACL) which is used to guard access to http adaptor.
  44  * <P>
  45  * It is a data structure with multiple ACL entries. Each ACL entry, of interface type
  46  * AclEntry, contains a set of permissions and a set of communities associated with a
  47  * particular principal. (A principal represents an entity such as a host or a group of host).
  48  * Additionally, each ACL entry is specified as being either positive or negative.
  49  * If positive, the permissions are to be granted to the associated principal.
  50  * If negative, the permissions are to be denied.
  51  *
  52  * @see java.security.acl.Acl
  53  */
  54 
  55 class AclImpl extends OwnerImpl implements Acl, Serializable {
  56   private static final long serialVersionUID = -2250957591085270029L;
  57 
  58   private Vector<AclEntry> entryList = null;
  59   private String aclName = null;
  60 
  61   /**
  62    * Constructs the ACL with a specified owner
  63    *
  64    * @param owner owner of the ACL.
  65    * @param name  name of this ACL.
  66    */
  67   public AclImpl (PrincipalImpl owner, String name) {
  68         super(owner);
  69         entryList = new Vector<>();
  70         aclName = name;
  71   }
  72 
  73   /**
  74    * Sets the name of this ACL.
  75    *
  76    * @param caller the principal invoking this method. It must be an owner
  77    *        of this ACL.
  78    * @param name the name to be given to this ACL.
  79    *
  80    * @exception NotOwnerException if the caller principal is not an owner
  81    *            of this ACL.
  82    * @see java.security.Principal
  83    */
  84   @Override
  85   public void setName(Principal caller, String name)
  86         throws NotOwnerException {
  87           if (!isOwner(caller))
  88                 throw new NotOwnerException();
  89           aclName = name;
  90   }
  91 
  92   /**
  93    * Returns the name of this ACL.
  94    *
  95    * @return the name of this ACL.
  96    */
  97   @Override
  98   public String getName(){
  99         return aclName;
 100   }
 101 
 102   /**
 103    * Adds an ACL entry to this ACL. An entry associates a principal (e.g., an individual or a group)
 104    * with a set of permissions. Each principal can have at most one positive ACL entry
 105    * (specifying permissions to be granted to the principal) and one negative ACL entry
 106    * (specifying permissions to be denied). If there is already an ACL entry
 107    * of the same type (negative or positive) already in the ACL, false is returned.
 108    *
 109    * @param caller the principal invoking this method. It must be an owner
 110    *        of this ACL.
 111    * @param entry the ACL entry to be added to this ACL.
 112    * @return true on success, false if an entry of the same type (positive
 113    *       or negative) for the same principal is already present in this ACL.
 114    * @exception NotOwnerException if the caller principal is not an owner of
 115    *       this ACL.
 116    * @see java.security.Principal
 117    */
 118   @Override
 119   public boolean addEntry(Principal caller, AclEntry entry)
 120         throws NotOwnerException {
 121           if (!isOwner(caller))
 122                 throw new NotOwnerException();
 123 
 124           if (entryList.contains(entry))
 125                 return false;
 126           /*
 127                  for (Enumeration e = entryList.elements();e.hasMoreElements();){
 128                  AclEntry ent = (AclEntry) e.nextElement();
 129                  if (ent.getPrincipal().equals(entry.getPrincipal()))
 130                  return false;
 131                  }
 132                  */
 133 
 134           entryList.addElement(entry);
 135           return true;
 136   }
 137 
 138   /**
 139    * Removes an ACL entry from this ACL.
 140    *
 141    * @param caller the principal invoking this method. It must be an owner
 142    *        of this ACL.
 143    * @param entry the ACL entry to be removed from this ACL.
 144    * @return true on success, false if the entry is not part of this ACL.
 145    * @exception NotOwnerException if the caller principal is not an owner
 146    *   of this Acl.
 147    * @see java.security.Principal
 148    * @see java.security.acl.AclEntry
 149    */
 150   @Override
 151   public boolean removeEntry(Principal caller, AclEntry entry)
 152         throws NotOwnerException {
 153           if (!isOwner(caller))
 154                 throw new NotOwnerException();
 155 
 156           return (entryList.removeElement(entry));
 157   }
 158 
 159   /**
 160    * Removes all ACL entries from this ACL.
 161    *
 162    * @param caller the principal invoking this method. It must be an owner
 163    *        of this ACL.
 164    * @exception NotOwnerException if the caller principal is not an owner of
 165    *        this Acl.
 166    * @see java.security.Principal
 167    */
 168   public void removeAll(Principal caller)
 169         throws NotOwnerException {
 170           if (!isOwner(caller))
 171                 throw new NotOwnerException();
 172         entryList.removeAllElements();
 173   }
 174 
 175   /**
 176    * Returns an enumeration for the set of allowed permissions for
 177    * the specified principal
 178    * (representing an entity such as an individual or a group).
 179    * This set of allowed permissions is calculated as follows:
 180    * <UL>
 181    * <LI>If there is no entry in this Access Control List for the specified
 182    * principal, an empty permission set is returned.</LI>
 183    * <LI>Otherwise, the principal's group permission sets are determined.
 184    * (A principal can belong to one or more groups, where a group is a group
 185    * of principals, represented by the Group interface.)</LI>
 186    * </UL>
 187    * @param user the principal whose permission set is to be returned.
 188    * @return the permission set specifying the permissions the principal
 189    *     is allowed.
 190    * @see java.security.Principal
 191    */
 192   @Override
 193   public Enumeration<Permission> getPermissions(Principal user){
 194         Vector<Permission> empty = new Vector<>();
 195         for (Enumeration<AclEntry> e = entryList.elements();e.hasMoreElements();){
 196           AclEntry ent = e.nextElement();
 197           if (ent.getPrincipal().equals(user))
 198                 return ent.permissions();
 199         }
 200         return empty.elements();
 201   }
 202 
 203   /**
 204    * Returns an enumeration of the entries in this ACL. Each element in the
 205    * enumeration is of type AclEntry.
 206    *
 207    * @return an enumeration of the entries in this ACL.
 208    */
 209   @Override
 210   public Enumeration<AclEntry> entries(){
 211         return entryList.elements();
 212   }
 213 
 214   /**
 215    * Checks whether or not the specified principal has the specified
 216    * permission.
 217    * If it does, true is returned, otherwise false is returned.
 218    * More specifically, this method checks whether the passed permission
 219    * is a member of the allowed permission set of the specified principal.
 220    * The allowed permission set is determined by the same algorithm as is
 221    * used by the getPermissions method.
 222    *
 223    * @param user the principal, assumed to be a valid authenticated Principal.
 224    * @param perm the permission to be checked for.
 225    * @return true if the principal has the specified permission,
 226    *         false otherwise.
 227    * @see java.security.Principal
 228    * @see java.security.Permission
 229    */
 230   @Override
 231   public boolean checkPermission(Principal user,
 232                                  java.security.acl.Permission perm) {
 233         for (Enumeration<AclEntry> e = entryList.elements();e.hasMoreElements();){
 234           AclEntry ent = e.nextElement();
 235           if (ent.getPrincipal().equals(user))
 236                 if (ent.checkPermission(perm)) return true;
 237         }
 238         return false;
 239   }
 240 
 241   /**
 242    * Checks whether or not the specified principal has the specified
 243    * permission.
 244    * If it does, true is returned, otherwise false is returned.
 245    * More specifically, this method checks whether the passed permission
 246    * is a member of the allowed permission set of the specified principal.
 247    * The allowed permission set is determined by the same algorithm as is
 248    * used by the getPermissions method.
 249    *
 250    * @param user the principal, assumed to be a valid authenticated Principal.
 251    * @param community the community name associated with the principal.
 252    * @param perm the permission to be checked for.
 253    * @return true if the principal has the specified permission, false
 254    *        otherwise.
 255    * @see java.security.Principal
 256    * @see java.security.Permission
 257    */
 258   public boolean checkPermission(Principal user, String community,
 259                                  java.security.acl.Permission perm) {
 260         for (Enumeration<AclEntry> e = entryList.elements();e.hasMoreElements();){
 261           AclEntryImpl ent = (AclEntryImpl) e.nextElement();
 262           if (ent.getPrincipal().equals(user))
 263                 if (ent.checkPermission(perm) && ent.checkCommunity(community)) return true;
 264         }
 265         return false;
 266   }
 267 
 268   /**
 269    * Checks whether or not the specified community string is defined.
 270    *
 271    * @param community the community name associated with the principal.
 272    *
 273    * @return true if the specified community string is defined, false
 274    *      otherwise.
 275    * @see java.security.Principal
 276    * @see java.security.Permission
 277    */
 278   public boolean checkCommunity(String community) {
 279         for (Enumeration<AclEntry> e = entryList.elements();e.hasMoreElements();){
 280           AclEntryImpl ent = (AclEntryImpl) e.nextElement();
 281           if (ent.checkCommunity(community)) return true;
 282         }
 283         return false;
 284   }
 285 
 286   /**
 287    * Returns a string representation of the ACL contents.
 288    *
 289    * @return a string representation of the ACL contents.
 290    */
 291   @Override
 292   public String toString(){
 293         return ("AclImpl: "+ getName());
 294   }
 295 }