AuditTarget.java

/*
** Module   : AuditTarget.java
** Abstract : Implements abstract resource audit records filtering.
**
** Copyright (c) 2004-2022, Golden Code Development Corporation.
**
** -#- -I- --Date-- -T- --JPRM-- ----------------Description-----------------
** 001 NVS 20050329 NEW   @20528 Created. This class implements abstract 
**                               resource audit records filtering by instance 
*                                name and/or by access mode (requested rights)
** 002 TJD 20220504              Java 11 compatibility minor changes
*/ 
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
** 
** Additional terms under GNU Affero GPL version 3 section 7:
** 
**   Under Section 7 of the GNU Affero GPL version 3, the following additional
**   terms apply to the works covered under the License.  These additional terms
**   are non-permissive additional terms allowed under Section 7 of the GNU
**   Affero GPL version 3 and may not be removed by you.
** 
**   0. Attribution Requirement.
** 
**     You must preserve all legal notices or author attributions in the covered
**     work or Appropriate Legal Notices displayed by works containing the covered
**     work.  You may not remove from the covered work any author or developer
**     credit already included within the covered work.
** 
**   1. No License To Use Trademarks.
** 
**     This license does not grant any license or rights to use the trademarks
**     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
**     of Golden Code Development Corporation. You are not authorized to use the
**     name Golden Code, FWD, or the names of any author or contributor, for
**     publicity purposes without written authorization.
** 
**   2. No Misrepresentation of Affiliation.
** 
**     You may not represent yourself as Golden Code Development Corporation or FWD.
** 
**     You may not represent yourself for publicity purposes as associated with
**     Golden Code Development Corporation, FWD, or any author or contributor to
**     the covered work, without written authorization.
** 
**   3. No Misrepresentation of Source or Origin.
** 
**     You may not represent the covered work as solely your work.  All modified
**     versions of the covered work must be marked in a reasonable way to make it
**     clear that the modified work is not originating from Golden Code Development
**     Corporation or FWD.  All modified versions must contain the notices of
**     attribution required in this license.
*/

package com.goldencode.p2j.security;

import java.util.*;

/**
 * Represents a security audit target which is an instance of an abstract
 * resource.
 * <p>
 * Filtering is done by instance name and by access mode independently. These
 * are the combinations and how they are interpreted. A combination is an
 * instance name and a list of access modes. Either or both can be empty.
 * <ul>
 *   <li>{nothing, nothing}
 *       <br>this combination means "all";
 *   <li>{nothing, list of access modes}; 
 *       <br>this combination means "any instance, specified access modes
 *           only";
 *   <li>{instance, nothing}
 *       <br>this combination means "any access mode for this instance";
 *   <li>{instance, list of access modes}; 
 *       <br>this combination means "this instance, specified access modes
 *           only";
 * </ul>
 * All combinations are kept in a Map. The key in this map is the instance
 * name, and the value is a Set, possibly empty, which holds access modes.
 * <p> 
 * When a request comes to filter a
 * record, two searches are done agains the Map:
 * <ul>
 *   <li>specified name.
 *   <li><code>null</code> as the instance name, which means "any name";
 * </ul>
 * Each request may return a list of access modes or <code>null</code>.
 * The latter means a match, otherwise the access mode is compared with the
 * list.
 */
class AuditTarget
{
   /** keeps the instance and list of access modes combinations */
   private Map target = new HashMap();

   /**
    * Package private constructor.
    */
   AuditTarget()
   {
   }

   /**
    * Checks the given integer for a match in the given array.
    *
    * @param values
    *        Set of integers to be checked
    *
    * @param value
    *        integer value
    *
    * @return <code>true</code> if the specified value has the match in the
    *        set or the latter is empty
    */
   private static boolean checkMode(Set values, int value)
   {
      if (values.isEmpty() || values.contains(Integer.valueOf(value)))
         return true;

      return false;
   }

   /**
    * Adds another combination to the map of targets. If a target with the 
    * given instance name exists in the map, the access modes are merged.
    *
    * @param instance
    *        resource instance name or <code>null</code>
    *
    * @param modes
    *        array of access modes or <code>null</code>
    */
   void addTarget(String instance, Integer[] modes)
   {
      if (target.containsKey(instance))
      {
         // merge access modes
         Set set = (Set)target.get(instance);
         if (set.isEmpty())
         {
            // empty set remains empty, as it means "all"
            return;
         }
         else
         {
            if (modes == null)
            {
               // adding an empty array means adding "all"
               set.clear();
               return;
            }
            for (int i = 0; i < modes.length; i ++)
               set.add(modes[i]);
         }
      }
      else
      {
         // add new entry
         Set set = new HashSet();
         if (modes != null)
         {
            for (int i = 0; i < modes.length; i ++)
               set.add(modes[i]);
         }
         target.put(instance, set);
      }
   }

   /**
    * Checks the given resource instance and access mode to see if they are
    * a valid audit target.
    *
    * @param instance
    *        resource instance name
    *
    * @param mode
    *        access mode (requested rights)
    *
    * @return <code>true</code> if the specified combination is a valid
    *        audit target
    */
   boolean checkTarget(String instance, int mode)
   {
      Set modes = null;
      boolean result = false;

      if (target.containsKey(instance))
      {
         modes = (Set)target.get(instance);
         result = checkMode(modes, mode);
         if (result)
            return true;
      }

      if (target.containsKey(null))
      {
         modes = (Set)target.get(null);
         result = checkMode(modes, mode);
      }

      return result;
   }
}