/*
Derby - Class org.apache.derby.security.SystemPermission
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package org.apache.derby.security;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.security.BasicPermission;
import java.security.Permission;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.StringTokenizer;
/**
* This class represents access to system-wide Derby privileges.
*
Permission Description Risk
"jmx" "control" Controls the ability of JMX clients to control
Derby and view security sensitive attributes through Derby's MBeans.
JMX clients may be able to change the state of the running system
"jmx" "monitor" Controls the ability of JMX clients to
monitor Derby through Derby's MBeans, such as viewing number of current connections and
configuration settings. Note: security related settings require control
action on jmx JMX clients can see information about a runing system
including software versions.
*/
final public class SystemPermission extends BasicPermission {
private static final long serialVersionUID = 1965420504091489898L;
/**
* Permission target name ("server") for actions applicable
* to the network server.
*/
public static final String SERVER = "server";
/**
* Permission target name ("engine") for actions applicable
* to the core database engine.
*/
public static final String ENGINE = "engine";
/**
* Permission target name ("jmx") for actions applicable
* to management of Derby's JMX MBeans.
*/
public static final String JMX = "jmx";
/**
* The server and engine shutdown action ("shutdown").
*/
static public final String SHUTDOWN = "shutdown";
/**
* Action ("control") to perform control actions through JMX
* on engine, server or jmx.
*
* For JMX control permission is required to get
* attributes that are deemed sensiive from a security
* aspect, such as the network server's port number,
* security mechanisms and any information about the
* file system.
*/
public static final String CONTROL = "control";
/**
* Action ("monitor") to perform monitoring actions through JMX
* on engine and server.
*/
public static final String MONITOR = "monitor";
/**
* The legal system permission names.
*/
static private final Set LEGAL_NAMES = new HashSet();
static {
// when adding new permissions, check whether to override inherited
// method: implies(Permission)
LEGAL_NAMES.add(SERVER);
LEGAL_NAMES.add(ENGINE);
LEGAL_NAMES.add(JMX);
};
/**
* Set of legal actions in their canonical form.
*/
static private final List LEGAL_ACTIONS = new ArrayList();
static {
LEGAL_ACTIONS.add(CONTROL);
LEGAL_ACTIONS.add(MONITOR);
LEGAL_ACTIONS.add(SHUTDOWN);
}
/**
* Actions for this permission.
*/
private String actions;
/**
* Creates a new SystemPermission with the specified name.
*
* @param name the name of the SystemPermission
* @throws NullPointerException if name or actions is null
* @throws IllegalArgumentException if name is empty or not a legal SystemPermission
* @see BasicPermission#BasicPermission(String)
*/
public SystemPermission(String name, String actions) {
super(name);
validateNameAndActions(name, actions);
}
/**
* Check if name and actions are valid, and normalize the actions
* string.
*
* @param name the name of the permission
* @param actions the actions of the permission
* @throws NullPointerException if actions is null
* @throws IllegalArgumentException if name is not a legal SystemPermission
*/
private void validateNameAndActions(String name, String actions) {
// superclass BasicPermission has checked that name isn't null
// (NullPointerException) or empty (IllegalArgumentException)
if (!LEGAL_NAMES.contains(name) ) {
throw new IllegalArgumentException("Unknown permission " + name);
}
this.actions = getCanonicalForm(actions);
}
/**
* Return the permission's actions in a canonical form.
*/
public String getActions() {
return actions;
}
/**
* Return a canonical form of the passed in actions.
* Actions are lower-cased, in the order of LEGAL_ACTIONS
* and only appear once.
*/
private static String getCanonicalForm(String actions) {
Set actionSet = parseActions(actions);
// Get all the legal actions that are in actionSet, in the order
// of LEGAL_ACTIONS.
List legalActions = new ArrayList(LEGAL_ACTIONS);
legalActions.retainAll(actionSet);
return buildActionsString(legalActions);
}
/**
* Get a set of all actions specified in a string. Actions are transformed
* to lower-case, and leading and trailing blanks are stripped off.
*
* @param actions the specified actions string
* @return a set of all the specified actions
*/
static Set parseActions(String actions) {
HashSet actionSet = new HashSet();
for (String s : actions.split(",", -1)) {
actionSet.add(s.trim().toLowerCase(Locale.ENGLISH));
}
return actionSet;
}
/**
* Build a comma-separated actions string suitable for returning from
* {@code getActions()}.
*
* @param actions the list of actions
* @return comma-separated string with the actions
*/
static String buildActionsString(Iterable actions) {
StringBuilder sb = new StringBuilder();
for (String action : actions) {
if (sb.length() > 0) {
sb.append(',');
}
sb.append(action);
}
return sb.toString();
}
/**
* Does this permission equal another object.
* True if its and identical class with same
* name and (canonical) actions.
*/
public boolean equals(Object other) {
if (!super.equals(other))
return false;
SystemPermission osp = (SystemPermission) other;
return getActions().equals(osp.getActions());
}
/**
* Does this permission imply another. Only true
* if the other permission is a SystemPermission
* with the same name and all the actions
* of the permission are present in this.
* Note that none of the actions imply any other
* with this SystemPermission.
*/
public boolean implies(Permission permission)
{
if (!super.implies(permission))
return false;
int myActionMask = getActionMask(getActions());
int permissionMask = getActionMask(permission.getActions());
return
(myActionMask & permissionMask) == permissionMask;
}
/**
* Get a mask of bits that represents the actions
* and can be used for the implies method.
*/
private static int getActionMask(String actions) {
int mask = 0;
StringTokenizer st = new StringTokenizer(actions, ",");
while (st.hasMoreTokens()) {
int validAction = LEGAL_ACTIONS.indexOf(st.nextElement());
if (validAction != -1)
mask |= 1 << validAction;
}
return mask;
}
/**
* Called upon deserialization for restoring the state of this
* SystemPermission from a stream.
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
// Read the fields from the stream.
s.defaultReadObject();
// Make sure the name and actions fields contain legal values.
validateNameAndActions(getName(), getActions());
}
}
Ads help maintain this website.