Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/main/java/bsh/BSHAllocationExpression.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.CompletionException;

import bsh.security.SecurityError;

/**
New object, new array, or inner class style allocation with body.
*/
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/bsh/Interpreter.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
import java.net.URL;
import java.util.ResourceBundle;

import bsh.security.MainSecurityGuard;

/**
The BeanShell script interpreter.

Expand Down
4 changes: 2 additions & 2 deletions src/main/java/bsh/Name.java
Original file line number Diff line number Diff line change
Expand Up @@ -812,8 +812,8 @@ public Object invokeMethod(
Object instance = classNameSpace.getClassInstance();
Class<?> classStatic = classNameSpace.classStatic;

// Validate if can invoke this super method
Interpreter.mainSecurityGuard.canInvokeSuperMethod(instance.getClass().getSuperclass(), instance, methodName, args);
// Validate if can invoke this method
Interpreter.mainSecurityGuard.canInvokeMethod(instance, methodName, args);

return ClassGenerator.getClassGenerator()
.invokeSuperclassMethod( bcm, instance, classStatic, methodName, args );
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/bsh/Reflect.java
Original file line number Diff line number Diff line change
Expand Up @@ -1297,4 +1297,10 @@ static <T> T[] getEnumConstants(Class<T> enm) {
.filter(Objects::nonNull)
.toArray(len -> (T[]) Array.newInstance(enm, len));
}

/** Find the type of an object. */
public static Class<?> getType(Object arg) {
return Types.getType(arg);
}

}
21 changes: 0 additions & 21 deletions src/main/java/bsh/Types.java
Original file line number Diff line number Diff line change
Expand Up @@ -774,25 +774,4 @@ public static boolean isCollectionType(Class<?> clas) {
|| Entry.class.isAssignableFrom(clas);
}

/**
* Just a method to return the pretty name of any Class
*
* <pre>
* prettyName(String.class)
* returns "java.lang.String"
* prettyName(byte.class)
* returns "byte"
* prettyName((new Object[3]).getClass())
* returns "java.lang.Object[];"
* prettyName((new int[3][4][5][6][7][8][9]).getClass())
* returns "int[][][][][][][]"
* </pre>
*/
public static String prettyName(Class<?> clas) {
if (!clas.isArray()) return clas.getName();

// Return a string like "int[]", "double[]", "double[][]", etc...
Class<?> arrayType = clas.getComponentType();
return prettyName(arrayType) + "[]";
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package bsh;
package bsh.security;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
Expand All @@ -8,15 +8,19 @@
import java.util.HashSet;
import java.util.Set;

import bsh.Interpreter;
import bsh.Primitive;
import bsh.Reflect;

/**
* It's the "main" SecurityGuard that must be used to real validate something.
* This class store some implementations of {@link SecurityGuard} that each has some specific validation
*/
final class MainSecurityGuard {
public final class MainSecurityGuard {

private final Set<SecurityGuard> securityGuards = new HashSet<SecurityGuard>();

MainSecurityGuard() {
public MainSecurityGuard() {
this.securityGuards.add(new BasicSecurityGuard());
}

Expand All @@ -25,21 +29,21 @@ public void add(SecurityGuard guard) {
this.securityGuards.add(guard);
}

/** Remove a SecurityGuard that is being used. Return if it really contained this SecurityGuard */
public boolean remove(SecurityGuard guard) {
return this.securityGuards.remove(guard);
/** Remove a SecurityGuard if it's being used */
public void remove(SecurityGuard guard) {
this.securityGuards.remove(guard);
}

/** Validate if you can create a instance */
void canConstruct(Class<?> _class, Object[] args) throws SecurityError {
public void canConstruct(Class<?> _class, Object[] args) throws SecurityError {
final Object[] _args = Primitive.unwrap(args);
for (SecurityGuard guard: this.securityGuards)
if (!guard.canConstruct(_class, _args))
throw SecurityError.cantConstruct(_class, _args);
}

/** Validate if a specific static method of a specific class can be invoked */
void canInvokeStaticMethod(Class<?> _class, String methodName, Object[] args) throws SecurityError {
public void canInvokeStaticMethod(Class<?> _class, String methodName, Object[] args) throws SecurityError {
final Object[] _args = Primitive.unwrap(args);
this.canInvokeStaticMethodImpl(_class, methodName, _args);
this.canInvokeStaticMethodImplToReflectionCanGetArrayLength(_class, methodName, _args);
Expand All @@ -66,7 +70,7 @@ private void canInvokeStaticMethodImplToReflectionCanGetArrayLength(Class<?> _cl
}

/** Validate if a specific method of a specific object can be invoked. */
void canInvokeMethod(Object thisArg, String methodName, Object[] args) throws SecurityError {
public void canInvokeMethod(Object thisArg, String methodName, Object[] args) throws SecurityError {
final Object[] _args = Primitive.unwrap(args);
this.canInvokeMethodImpl(thisArg, methodName, _args);
this.canInvokeMethodImplToReflectionCanGetField(thisArg, methodName, _args);
Expand Down Expand Up @@ -159,44 +163,36 @@ else if (thisArg instanceof Constructor<?> && methodName.equals("newInstance"))
}

/** Validate if can call a local method ( aka commands ) */
void canInvokeLocalMethod(String methodName, Object[] args) throws SecurityError {
public void canInvokeLocalMethod(String methodName, Object[] args) throws SecurityError {
final Object[] _args = Primitive.unwrap(args);
for (SecurityGuard guard: this.securityGuards)
if (!guard.canInvokeLocalMethod(methodName, _args))
throw SecurityError.cantInvokeLocalMethod(methodName, _args);
}

/** Validate if can call a method of super class */
void canInvokeSuperMethod(Class<?> superClass, Object thisArg, String methodName, Object[] args) throws SecurityError {
final Object[] _args = Primitive.unwrap(args);
for (SecurityGuard guard: this.securityGuards)
if (!guard.canInvokeSuperMethod(superClass, thisArg, methodName, _args))
throw SecurityError.cantInvokeSuperMethod(superClass, methodName, _args);
}

/** Validate if can get a field of a specific object */
void canGetField(Object thisArg, String fieldName) throws SecurityError {
public void canGetField(Object thisArg, String fieldName) throws SecurityError {
for (SecurityGuard guard: this.securityGuards)
if (!guard.canGetField(thisArg, fieldName))
throw SecurityError.cantGetField(thisArg, fieldName);
}

/** Validate if can get a static field of a specific class */
void canGetStaticField(Class<?> _class, String fieldName) throws SecurityError {
public void canGetStaticField(Class<?> _class, String fieldName) throws SecurityError {
for (SecurityGuard guard: this.securityGuards)
if (!guard.canGetStaticField(_class, fieldName))
throw SecurityError.cantGetStaticField(_class, fieldName);
}

/** Validate if {@link _class} can extends {@link superClass} */
void canExtends(Class<?> superClass) throws SecurityError {
public void canExtends(Class<?> superClass) throws SecurityError {
for (SecurityGuard guard: this.securityGuards)
if (!guard.canExtends(superClass))
throw SecurityError.cantExtends(superClass);
}

/** Validate if {@link _class} can implements {@link _interface} */
void canImplements(Class<?> _interface) throws SecurityError {
public void canImplements(Class<?> _interface) throws SecurityError {
for (SecurityGuard guard: this.securityGuards)
if (!guard.canImplements(_interface))
throw SecurityError.cantImplements(_interface);
Expand All @@ -205,6 +201,12 @@ void canImplements(Class<?> _interface) throws SecurityError {
/** It prevents the execution of codes that manipulate the SecurityGuard or MainSecurityGuard */
private class BasicSecurityGuard implements SecurityGuard {

public boolean canConstruct(Class<?> _class, Object[] args) {
if (MainSecurityGuard.class.isAssignableFrom(_class)) return false;
if (SecurityGuard.class.isAssignableFrom(_class)) return false;
return true;
}

public boolean canInvokeMethod(Object thisArg, String methodName, Object[] args) {
return !(thisArg instanceof MainSecurityGuard);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package bsh;
package bsh.security;

import java.util.ArrayList;
import java.util.List;
import bsh.CallStack;
import bsh.EvalError;
import bsh.Node;
import bsh.Reflect;
import bsh.UtilEvalError;

/** It's a specific error that is throwed when try to execute something that mustn't be executed */
class SecurityError extends UtilEvalError {
public class SecurityError extends UtilEvalError {

SecurityError(String msg) {
super("SecurityError: " + msg);
Expand All @@ -22,10 +25,12 @@ public EvalError toEvalError(Node node, CallStack callstack) {

/** This method basically return the types of args at a concatened String by ", " */
private static String argsTypesString(Object[] args) {
List<String> typesString = new ArrayList<String>();
for (Class<?> typeClass: Types.getTypes(args))
typesString.add(typeClass != null ? Types.prettyName(typeClass) : "null");
return String.join(", ", typesString);
String[] argTypeNames = new String[args.length];
for (int i = 0; i < args.length; i++) {
final Class<?> _class = Reflect.getType(args[i]);
argTypeNames[i] = _class != null ? _class.getTypeName() : "null";
}
return String.join(", ", argTypeNames);
}

/** Create a error for when can't construct a instance */
Expand All @@ -42,29 +47,25 @@ static SecurityError reflectCantConstruct(Class<?> _class, Object[] args) {

/** Create a error for when can't invoke a static method */
static SecurityError cantInvokeStaticMethod(Class<?> _class, String methodName, Object[] args) {
String className = Types.prettyName(_class);
String msg = String.format("Can't invoke this static method: %s.%s(%s)", className, methodName, argsTypesString(args));
String msg = String.format("Can't invoke this static method: %s.%s(%s)", _class.getTypeName(), methodName, argsTypesString(args));
return new SecurityError(msg);
}

/** Create a error for when can't invoke a static method using reflection */
static SecurityError reflectCantInvokeStaticMethod(Class<?> _class, String methodName, Object[] args) {
String className = Types.prettyName(_class);
String msg = String.format("Can't invoke this static method using reflection: %s.%s(%s)", className, methodName, argsTypesString(args));
String msg = String.format("Can't invoke this static method using reflection: %s.%s(%s)", _class.getTypeName(), methodName, argsTypesString(args));
return new SecurityError(msg);
}

/** Create a error for when can't invoke a method */
static SecurityError cantInvokeMethod(Object thisArg, String methodName, Object[] args) {
String className = Types.prettyName(thisArg.getClass());
String msg = String.format("Can't invoke this method: %s.%s(%s)", className, methodName, argsTypesString(args));
String msg = String.format("Can't invoke this method: %s.%s(%s)", thisArg.getClass().getTypeName(), methodName, argsTypesString(args));
return new SecurityError(msg);
}

/** Create a error for when can't invoke a method using reflection */
static SecurityError reflectCantInvokeMethod(Object thisArg, String methodName, Object[] args) {
String className = Types.prettyName(thisArg.getClass());
String msg = String.format("Can't invoke this method using reflection: %s.%s(%s)", className, methodName, argsTypesString(args));
String msg = String.format("Can't invoke this method using reflection: %s.%s(%s)", thisArg.getClass().getTypeName(), methodName, argsTypesString(args));
return new SecurityError(msg);
}

Expand All @@ -74,50 +75,39 @@ static SecurityError cantInvokeLocalMethod(String methodName, Object[] args) {
return new SecurityError(msg);
}

/** Create a error for when can't invoke a super method */
static SecurityError cantInvokeSuperMethod(Class<?> superClass, String methodName, Object[] args) {
String superClassName = Types.prettyName(superClass);
String msg = String.format("Can't invoke this super method: %s.%s(%s)", superClassName, methodName, argsTypesString(args));
return new SecurityError(msg);
}

/** Create a error for when can't get a field */
static SecurityError cantGetField(Object thisArg, String fieldName) {
String className = Types.prettyName(thisArg.getClass());
String msg = String.format("Can't get this field: %s.%s", className, fieldName);
String msg = String.format("Can't get this field: %s.%s", thisArg.getClass().getTypeName(), fieldName);
return new SecurityError(msg);
}

/** Create a error for when can't get a field */
static SecurityError reflectCantGetField(Object thisArg, String fieldName) {
String className = Types.prettyName(thisArg.getClass());
String msg = String.format("Can't get this field using reflection: %s.%s", className, fieldName);
String msg = String.format("Can't get this field using reflection: %s.%s", thisArg.getClass().getTypeName(), fieldName);
return new SecurityError(msg);
}

/** Create a error for when can't get a field */
static SecurityError cantGetStaticField(Class<?> _class, String fieldName) {
String className = Types.prettyName(_class);
String msg = String.format("Can't get this static field: %s.%s", className, fieldName);
String msg = String.format("Can't get this static field: %s.%s", _class.getTypeName(), fieldName);
return new SecurityError(msg);
}

/** Create a error for when can't get a field */
static SecurityError reflectCantGetStaticField(Class<?> _class, String fieldName) {
String className = Types.prettyName(_class);
String msg = String.format("Can't get this static field using reflection: %s.%s", className, fieldName);
String msg = String.format("Can't get this static field using reflection: %s.%s", _class.getTypeName(), fieldName);
return new SecurityError(msg);
}

/** Create a error for when a class can't extends another class */
static SecurityError cantExtends(Class<?> superClass) {
String msg = String.format("This class can't be extended: %s", superClass.getName());
String msg = String.format("Can't extend this class: %s", superClass.getName());
return new SecurityError(msg);
}

/** Create a error for when a class can't implements an interface */
static SecurityError cantImplements(Class<?> _interface) {
String msg = String.format("This interface can't be implemented: %s", _interface.getName());
String msg = String.format("Can't implement this interface: %s", _interface.getName());
return new SecurityError(msg);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package bsh;
package bsh.security;

/** It's the interface to implement a single SecurityGuard to be used by MainSecurityGuard */
public interface SecurityGuard {
Expand Down Expand Up @@ -27,10 +27,7 @@ public default boolean canInvokeLocalMethod(String methodName, Object[] args) {
return true;
}

/** Validate and return if can call a method of super class */
public default boolean canInvokeSuperMethod(Class<?> superClass, Object thisArg, String methodName, Object[] args) {
return true;
}
// TODO: implement a 'canSetField' and 'canSetStaticField'

/** Validate and return if can get a field of a specific object */
public default boolean canGetField(Object thisArg, String fieldName) {
Expand Down
Loading