diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main/java/org/traccar/config/Keys.java | 95 | ||||
-rw-r--r-- | src/main/java/org/traccar/handler/ComputedAttributesHandler.java | 43 |
2 files changed, 134 insertions, 4 deletions
diff --git a/src/main/java/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java index 093f4298c..49af7cfab 100644 --- a/src/main/java/org/traccar/config/Keys.java +++ b/src/main/java/org/traccar/config/Keys.java @@ -1299,6 +1299,101 @@ public final class Keys { public static final ConfigKey<Boolean> PROCESSING_COMPUTED_ATTRIBUTES_DEVICE_ATTRIBUTES = new BooleanConfigKey( "processing.computedAttributes.deviceAttributes", List.of(KeyType.CONFIG)); + /** + * Enable annotation constructs processing. + * When disabled, parsing a script/expression using syntactic annotation constructs (@annotation) will throw a parsing exception. + */ + public static final ConfigKey<Boolean> PROCESSING_COMPUTED_ATTRIBUTES_ANNOTATION = new BooleanConfigKey( + "processing.computedAttributes.parser.annotation", + List.of(KeyType.CONFIG)); + /** + * Enable array references processing. + * When disabled, parsing a script/expression using 'obj[ ref ]' where ref is not a string or integer literal will throw a parsing exception; + */ + public static final ConfigKey<Boolean> PROCESSING_COMPUTED_ATTRIBUTES_ARRAY_REFERENCES = new BooleanConfigKey( + "processing.computedAttributes.parser.arrayReferences", + List.of(KeyType.CONFIG)); + /** + * Enable lambda declaration. + * When disabled, parsing a script/expression using syntactic lambda constructs (->,function) will throw a parsing exception. + */ + public static final ConfigKey<Boolean> PROCESSING_COMPUTED_ATTRIBUTES_LAMBDA = new BooleanConfigKey( + "processing.computedAttributes.parser.lambda", + List.of(KeyType.CONFIG)); + /** + * Enable whether redefining local variables is an error. + * When disabled, parsing a script/expression using a local variable or parameter syntax will throw a parsing exception. + */ + public static final ConfigKey<Boolean> PROCESSING_COMPUTED_ATTRIBUTES_LEXICAL = new BooleanConfigKey( + "processing.computedAttributes.parser.lexical", + List.of(KeyType.CONFIG)); + /** + * Enable whether local variables shade global variables outside their scope. + */ + public static final ConfigKey<Boolean> PROCESSING_COMPUTED_ATTRIBUTES_LEXICAL_SHADE = new BooleanConfigKey( + "processing.computedAttributes.parser.lexicalShade", + List.of(KeyType.CONFIG)); + /** + * Enable local variables declaration. + */ + public static final ConfigKey<Boolean> PROCESSING_COMPUTED_ATTRIBUTES_LOCAL_VARIABLES = new BooleanConfigKey( + "processing.computedAttributes.parser.localVariables", + List.of(KeyType.CONFIG)); + /** + * Enable loops processing. + */ + public static final ConfigKey<Boolean> PROCESSING_COMPUTED_ATTRIBUTES_LOOPS = new BooleanConfigKey( + "processing.computedAttributes.parser.loops", + List.of(KeyType.CONFIG)); + /** + * Set whether object method calls are enabled. + * When disabled, parsing a script/expression using 'obj.method()' will throw a parsing exception; + */ + public static final ConfigKey<Boolean> PROCESSING_COMPUTED_ATTRIBUTES_METHOD_CALLS = new BooleanConfigKey( + "processing.computedAttributes.parser.method_calls", + List.of(KeyType.CONFIG)); + /** + * Enable new instances creation. + * When disabled, parsing a script/expression using 'new(...)' will throw a parsing exception; using a class as functor will fail. + */ + public static final ConfigKey<Boolean> PROCESSING_COMPUTED_ATTRIBUTES_NEW_INSTANCE_CREATION = new BooleanConfigKey( + "processing.computedAttributes.parser.newInstanceCreation", + List.of(KeyType.CONFIG)); + /** + * Enable pragma expressions processing. + * When disabled, parsing a script/expression using syntactic pragma constructs (#pragma) will throw a parsing exception. + */ + public static final ConfigKey<Boolean> PROCESSING_COMPUTED_ATTRIBUTES_PRAGMA = new BooleanConfigKey( + "processing.computedAttributes.parser.pragma", + List.of(KeyType.CONFIG)); + /** + * Enable scripts constructs processing. + * When disabled, parsing a script using syntactic script constructs (statements, ...) will throw a parsing exception. + * Dangerous, as can be used to escalate privileges on the Traccar server. + */ + public static final ConfigKey<Boolean> PROCESSING_COMPUTED_ATTRIBUTES_SCRIPT_CONSTRUCTS = new BooleanConfigKey( + "processing.computedAttributes.parser.scriptConstructs", + List.of(KeyType.CONFIG)); + /** + * Enable side effect expressions processing. + * When disabled, parsing a script/expression using syntactical constructs modifying variables or members will throw a parsing exception. + */ + public static final ConfigKey<Boolean> PROCESSING_COMPUTED_ATTRIBUTES_SIDE_EFFECT = new BooleanConfigKey( + "processing.computedAttributes.parser.sideEffect", + List.of(KeyType.CONFIG)); + /** + * Set whether side effect expressions on global variables (aka non-local) are enabled. + * When disabled, parsing a script/expression using syntactical constructs modifying variables including all potentially ant-ish variables will throw a parsing exception. + */ + public static final ConfigKey<Boolean> PROCESSING_COMPUTED_ATTRIBUTES_SIDE_EFFECT_GLOBAL = new BooleanConfigKey( + "processing.computedAttributes.parser.sideEffectGlobal", + List.of(KeyType.CONFIG)); + /** + * Enable array/map/set literal expressions processing. + */ + public static final ConfigKey<Boolean> PROCESSING_COMPUTED_ATTRIBUTES_STRUCTURED_LITERAL = new BooleanConfigKey( + "processing.computedAttributes.parser.structuredLiteral", + List.of(KeyType.CONFIG)); /** * Boolean flag to enable or disable reverse geocoder. diff --git a/src/main/java/org/traccar/handler/ComputedAttributesHandler.java b/src/main/java/org/traccar/handler/ComputedAttributesHandler.java index ca6c0fc74..c3f202fa2 100644 --- a/src/main/java/org/traccar/handler/ComputedAttributesHandler.java +++ b/src/main/java/org/traccar/handler/ComputedAttributesHandler.java @@ -26,10 +26,8 @@ import java.util.Map; import java.util.Set; import io.netty.channel.ChannelHandler; -import org.apache.commons.jexl3.JexlBuilder; -import org.apache.commons.jexl3.JexlEngine; -import org.apache.commons.jexl3.JexlException; -import org.apache.commons.jexl3.MapContext; +import org.apache.commons.jexl3.*; +import org.apache.commons.jexl3.introspection.JexlSandbox; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.traccar.BaseDataHandler; @@ -55,14 +53,51 @@ public class ComputedAttributesHandler extends BaseDataHandler { private final boolean includeDeviceAttributes; + @Inject public ComputedAttributesHandler(Config config, CacheManager cacheManager) { this.cacheManager = cacheManager; + boolean enableJEXLAnnotation = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_ANNOTATION); + boolean enableJEXLArrayReferences = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_ARRAY_REFERENCES); + boolean enableJEXLLambdas = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_LAMBDA); + boolean enableJEXLLexical = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_LEXICAL); + boolean enableJEXLLexicalShade = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_LEXICAL_SHADE); + boolean enableJEXLLocalVariables = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_LOCAL_VARIABLES); + boolean enableJEXLLoops = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_LOOPS); + boolean enableJEXLMethodCalls = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_METHOD_CALLS); + boolean enableJEXLNewInstanceCreation = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_NEW_INSTANCE_CREATION); + boolean enableJEXLPragma = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_PRAGMA); + boolean enableJEXLScriptConstructs = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_SCRIPT_CONSTRUCTS); + boolean enableJEXLSideEffect = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_SIDE_EFFECT); + boolean enableJEXLSideEffectGlobal = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_SIDE_EFFECT_GLOBAL); + boolean enableJEXLStructuredLiteral = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_STRUCTURED_LITERAL); + JexlSandbox sandbox = new JexlSandbox(false); + sandbox.allow("com.safe.Functions"); + boolean enableJEXLRegister = true; + JexlFeatures features = new JexlFeatures() + .annotation(enableJEXLAnnotation) + .arrayReferenceExpr(enableJEXLArrayReferences) + .lambda(enableJEXLLambdas) + .lexical(enableJEXLLexical) + .lexicalShade(enableJEXLLexicalShade) + .localVar(enableJEXLLocalVariables) + .loops(enableJEXLLoops) + .methodCall(enableJEXLMethodCalls) + .newInstance(enableJEXLNewInstanceCreation) + .pragma(enableJEXLPragma) + .register(enableJEXLRegister) + .script(enableJEXLScriptConstructs) + .sideEffect(enableJEXLSideEffect) + .sideEffectGlobal(enableJEXLSideEffectGlobal) + .structuredLiteral(enableJEXLStructuredLiteral); engine = new JexlBuilder() .strict(true) .namespaces(Collections.singletonMap("math", Math.class)) + .sandbox(sandbox) + .features(features) .create(); includeDeviceAttributes = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_DEVICE_ATTRIBUTES); + } private MapContext prepareContext(Position position) { |