682 lines
25 KiB
Diff
682 lines
25 KiB
Diff
|
This security patch addresses the following vulnerabilities:
|
||
|
CVE-2024-12801 (bsc#1234743)
|
||
|
Server-Side Request Forgery (SSRF) in SaxEventRecorder
|
||
|
CVE-2024-12798 (bsc#1234742)
|
||
|
ACE vulnerability in JaninoEventEvaluator
|
||
|
|
||
|
It is based on the following upstream patches:
|
||
|
https://github.com/qos-ch/logback/commit/2cb6d520df7592ef1c3a198f1b5df3c10c93e183.patch
|
||
|
https://github.com/qos-ch/logback/commit/5f05041cba4c4ac0a62748c5c527a2da48999f2d.patch
|
||
|
https://github.com/qos-ch/logback/commit/6ddf91890a4c23e855132c89086ad7e069d81755.patch
|
||
|
|
||
|
The change addresses the above issues by:
|
||
|
- removing SaxEventRecorder and JaninoEventEvaluator
|
||
|
- ignoring external DTD files in DOCTYPE to further reduce vulnerability to SSRF attacks
|
||
|
--- a/logback-access/src/main/java/ch/qos/logback/access/boolex/JaninoEventEvaluator.java
|
||
|
+++ /dev/null
|
||
|
@@ -1,84 +0,0 @@
|
||
|
-/**
|
||
|
- * Logback: the reliable, generic, fast and flexible logging framework.
|
||
|
- * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
|
||
|
- *
|
||
|
- * This program and the accompanying materials are dual-licensed under
|
||
|
- * either the terms of the Eclipse Public License v1.0 as published by
|
||
|
- * the Eclipse Foundation
|
||
|
- *
|
||
|
- * or (per the licensee's choosing)
|
||
|
- *
|
||
|
- * under the terms of the GNU Lesser General Public License version 2.1
|
||
|
- * as published by the Free Software Foundation.
|
||
|
- */
|
||
|
-package ch.qos.logback.access.boolex;
|
||
|
-
|
||
|
-import java.util.ArrayList;
|
||
|
-import java.util.List;
|
||
|
-
|
||
|
-import ch.qos.logback.access.spi.IAccessEvent;
|
||
|
-import ch.qos.logback.core.CoreConstants;
|
||
|
-import ch.qos.logback.core.boolex.JaninoEventEvaluatorBase;
|
||
|
-import ch.qos.logback.core.boolex.Matcher;
|
||
|
-
|
||
|
-public class JaninoEventEvaluator extends JaninoEventEvaluatorBase<IAccessEvent> {
|
||
|
-
|
||
|
- public final static List<String> DEFAULT_PARAM_NAME_LIST = new ArrayList<String>();
|
||
|
- public final static List<Class> DEFAULT_PARAM_TYPE_LIST = new ArrayList<Class>();
|
||
|
-
|
||
|
- static {
|
||
|
- DEFAULT_PARAM_NAME_LIST.add("event");
|
||
|
- DEFAULT_PARAM_TYPE_LIST.add(IAccessEvent.class);
|
||
|
- }
|
||
|
-
|
||
|
- @Override
|
||
|
- protected String getDecoratedExpression() {
|
||
|
- String expression = getExpression();
|
||
|
- if (!expression.contains("return")) {
|
||
|
- expression = "return " + expression + ";";
|
||
|
- addInfo("Adding [return] prefix and a semicolon suffix. Expression becomes [" + expression + "]");
|
||
|
- addInfo("See also " + CoreConstants.CODES_URL + "#block");
|
||
|
- }
|
||
|
- return expression;
|
||
|
- }
|
||
|
-
|
||
|
- @Override
|
||
|
- protected String[] getParameterNames() {
|
||
|
- List<String> fullNameList = new ArrayList<String>();
|
||
|
- fullNameList.addAll(DEFAULT_PARAM_NAME_LIST);
|
||
|
-
|
||
|
- for (int i = 0; i < matcherList.size(); i++) {
|
||
|
- Matcher m = (Matcher) matcherList.get(i);
|
||
|
- fullNameList.add(m.getName());
|
||
|
- }
|
||
|
-
|
||
|
- return (String[]) fullNameList.toArray(CoreConstants.EMPTY_STRING_ARRAY);
|
||
|
- }
|
||
|
-
|
||
|
- @Override
|
||
|
- protected Class[] getParameterTypes() {
|
||
|
- List<Class> fullTypeList = new ArrayList<Class>();
|
||
|
- fullTypeList.addAll(DEFAULT_PARAM_TYPE_LIST);
|
||
|
- for (int i = 0; i < matcherList.size(); i++) {
|
||
|
- fullTypeList.add(Matcher.class);
|
||
|
- }
|
||
|
- return (Class[]) fullTypeList.toArray(CoreConstants.EMPTY_CLASS_ARRAY);
|
||
|
- }
|
||
|
-
|
||
|
- @Override
|
||
|
- protected Object[] getParameterValues(IAccessEvent accessEvent) {
|
||
|
- final int matcherListSize = matcherList.size();
|
||
|
-
|
||
|
- int i = 0;
|
||
|
- Object[] values = new Object[DEFAULT_PARAM_NAME_LIST.size() + matcherListSize];
|
||
|
-
|
||
|
- values[i++] = accessEvent;
|
||
|
-
|
||
|
- for (int j = 0; j < matcherListSize; j++) {
|
||
|
- values[i++] = matcherList.get(j);
|
||
|
- }
|
||
|
-
|
||
|
- return values;
|
||
|
- }
|
||
|
-
|
||
|
-}
|
||
|
--- a/logback-classic/src/main/java/ch/qos/logback/classic/boolex/JaninoEventEvaluator.java
|
||
|
+++ /dev/null
|
||
|
@@ -1,152 +0,0 @@
|
||
|
-/**
|
||
|
- * Logback: the reliable, generic, fast and flexible logging framework.
|
||
|
- * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
|
||
|
- *
|
||
|
- * This program and the accompanying materials are dual-licensed under
|
||
|
- * either the terms of the Eclipse Public License v1.0 as published by
|
||
|
- * the Eclipse Foundation
|
||
|
- *
|
||
|
- * or (per the licensee's choosing)
|
||
|
- *
|
||
|
- * under the terms of the GNU Lesser General Public License version 2.1
|
||
|
- * as published by the Free Software Foundation.
|
||
|
- */
|
||
|
-package ch.qos.logback.classic.boolex;
|
||
|
-
|
||
|
-import java.util.ArrayList;
|
||
|
-import java.util.List;
|
||
|
-import java.util.Map;
|
||
|
-
|
||
|
-import org.slf4j.Marker;
|
||
|
-
|
||
|
-import ch.qos.logback.classic.Level;
|
||
|
-import ch.qos.logback.classic.spi.ILoggingEvent;
|
||
|
-import ch.qos.logback.classic.spi.IThrowableProxy;
|
||
|
-import ch.qos.logback.classic.spi.LoggerContextVO;
|
||
|
-import ch.qos.logback.classic.spi.ThrowableProxy;
|
||
|
-import ch.qos.logback.core.CoreConstants;
|
||
|
-import ch.qos.logback.core.boolex.JaninoEventEvaluatorBase;
|
||
|
-import ch.qos.logback.core.boolex.Matcher;
|
||
|
-
|
||
|
-public class JaninoEventEvaluator extends JaninoEventEvaluatorBase<ILoggingEvent> {
|
||
|
-
|
||
|
- public final static String IMPORT_LEVEL = "import ch.qos.logback.classic.Level;\r\n";
|
||
|
-
|
||
|
- public final static List<String> DEFAULT_PARAM_NAME_LIST = new ArrayList<String>();
|
||
|
- public final static List<Class> DEFAULT_PARAM_TYPE_LIST = new ArrayList<Class>();
|
||
|
-
|
||
|
- static {
|
||
|
- DEFAULT_PARAM_NAME_LIST.add("DEBUG");
|
||
|
- DEFAULT_PARAM_NAME_LIST.add("INFO");
|
||
|
- DEFAULT_PARAM_NAME_LIST.add("WARN");
|
||
|
- DEFAULT_PARAM_NAME_LIST.add("ERROR");
|
||
|
-
|
||
|
- DEFAULT_PARAM_NAME_LIST.add("event");
|
||
|
- DEFAULT_PARAM_NAME_LIST.add("message");
|
||
|
-
|
||
|
- DEFAULT_PARAM_NAME_LIST.add("formattedMessage");
|
||
|
- DEFAULT_PARAM_NAME_LIST.add("logger");
|
||
|
- DEFAULT_PARAM_NAME_LIST.add("loggerContext");
|
||
|
- DEFAULT_PARAM_NAME_LIST.add("level");
|
||
|
- DEFAULT_PARAM_NAME_LIST.add("timeStamp");
|
||
|
- DEFAULT_PARAM_NAME_LIST.add("marker");
|
||
|
- DEFAULT_PARAM_NAME_LIST.add("mdc");
|
||
|
- DEFAULT_PARAM_NAME_LIST.add("throwableProxy");
|
||
|
- DEFAULT_PARAM_NAME_LIST.add("throwable");
|
||
|
-
|
||
|
- DEFAULT_PARAM_TYPE_LIST.add(int.class);
|
||
|
- DEFAULT_PARAM_TYPE_LIST.add(int.class);
|
||
|
- DEFAULT_PARAM_TYPE_LIST.add(int.class);
|
||
|
- DEFAULT_PARAM_TYPE_LIST.add(int.class);
|
||
|
-
|
||
|
- DEFAULT_PARAM_TYPE_LIST.add(ILoggingEvent.class);
|
||
|
- DEFAULT_PARAM_TYPE_LIST.add(String.class);
|
||
|
- DEFAULT_PARAM_TYPE_LIST.add(String.class);
|
||
|
- DEFAULT_PARAM_TYPE_LIST.add(String.class);
|
||
|
- DEFAULT_PARAM_TYPE_LIST.add(LoggerContextVO.class);
|
||
|
- DEFAULT_PARAM_TYPE_LIST.add(int.class);
|
||
|
- DEFAULT_PARAM_TYPE_LIST.add(long.class);
|
||
|
- DEFAULT_PARAM_TYPE_LIST.add(Marker.class);
|
||
|
- DEFAULT_PARAM_TYPE_LIST.add(Map.class);
|
||
|
- DEFAULT_PARAM_TYPE_LIST.add(IThrowableProxy.class);
|
||
|
- DEFAULT_PARAM_TYPE_LIST.add(Throwable.class);
|
||
|
- }
|
||
|
-
|
||
|
- protected String getDecoratedExpression() {
|
||
|
- String expression = getExpression();
|
||
|
- if (!expression.contains("return")) {
|
||
|
- expression = "return " + expression + ";";
|
||
|
- addInfo("Adding [return] prefix and a semicolon suffix. Expression becomes [" + expression + "]");
|
||
|
- addInfo("See also " + CoreConstants.CODES_URL + "#block");
|
||
|
-
|
||
|
- }
|
||
|
- return IMPORT_LEVEL + expression;
|
||
|
- }
|
||
|
-
|
||
|
- protected String[] getParameterNames() {
|
||
|
- List<String> fullNameList = new ArrayList<String>();
|
||
|
- fullNameList.addAll(DEFAULT_PARAM_NAME_LIST);
|
||
|
-
|
||
|
- for (int i = 0; i < matcherList.size(); i++) {
|
||
|
- Matcher m = (Matcher) matcherList.get(i);
|
||
|
- fullNameList.add(m.getName());
|
||
|
- }
|
||
|
-
|
||
|
- return (String[]) fullNameList.toArray(CoreConstants.EMPTY_STRING_ARRAY);
|
||
|
- }
|
||
|
-
|
||
|
- protected Class[] getParameterTypes() {
|
||
|
- List<Class> fullTypeList = new ArrayList<Class>();
|
||
|
- fullTypeList.addAll(DEFAULT_PARAM_TYPE_LIST);
|
||
|
- for (int i = 0; i < matcherList.size(); i++) {
|
||
|
- fullTypeList.add(Matcher.class);
|
||
|
- }
|
||
|
- return (Class[]) fullTypeList.toArray(CoreConstants.EMPTY_CLASS_ARRAY);
|
||
|
- }
|
||
|
-
|
||
|
- protected Object[] getParameterValues(ILoggingEvent loggingEvent) {
|
||
|
- final int matcherListSize = matcherList.size();
|
||
|
-
|
||
|
- int i = 0;
|
||
|
- Object[] values = new Object[DEFAULT_PARAM_NAME_LIST.size() + matcherListSize];
|
||
|
-
|
||
|
- values[i++] = Level.DEBUG_INTEGER;
|
||
|
- values[i++] = Level.INFO_INTEGER;
|
||
|
- values[i++] = Level.WARN_INTEGER;
|
||
|
- values[i++] = Level.ERROR_INTEGER;
|
||
|
-
|
||
|
- values[i++] = loggingEvent;
|
||
|
- values[i++] = loggingEvent.getMessage();
|
||
|
- values[i++] = loggingEvent.getFormattedMessage();
|
||
|
- values[i++] = loggingEvent.getLoggerName();
|
||
|
- values[i++] = loggingEvent.getLoggerContextVO();
|
||
|
- values[i++] = loggingEvent.getLevel().toInteger();
|
||
|
- values[i++] = loggingEvent.getTimeStamp();
|
||
|
- // In order to avoid NullPointerException, we could push a dummy marker if
|
||
|
- // the event's marker is null. However, this would surprise user who
|
||
|
- // expect to see a null marker instead of a dummy one.
|
||
|
- values[i++] = loggingEvent.getMarker();
|
||
|
- values[i++] = loggingEvent.getMDCPropertyMap();
|
||
|
-
|
||
|
- IThrowableProxy iThrowableProxy = loggingEvent.getThrowableProxy();
|
||
|
-
|
||
|
- if (iThrowableProxy != null) {
|
||
|
- values[i++] = iThrowableProxy;
|
||
|
- if (iThrowableProxy instanceof ThrowableProxy) {
|
||
|
- values[i++] = ((ThrowableProxy) iThrowableProxy).getThrowable();
|
||
|
- } else {
|
||
|
- values[i++] = null;
|
||
|
- }
|
||
|
- } else {
|
||
|
- values[i++] = null;
|
||
|
- values[i++] = null;
|
||
|
- }
|
||
|
-
|
||
|
- for (int j = 0; j < matcherListSize; j++) {
|
||
|
- values[i++] = (Matcher) matcherList.get(j);
|
||
|
- }
|
||
|
-
|
||
|
- return values;
|
||
|
- }
|
||
|
-
|
||
|
-}
|
||
|
--- a/logback-classic/src/main/java/ch/qos/logback/classic/util/DefaultNestedComponentRules.java
|
||
|
+++ b/logback-classic/src/main/java/ch/qos/logback/classic/util/DefaultNestedComponentRules.java
|
||
|
@@ -14,7 +14,6 @@
|
||
|
package ch.qos.logback.classic.util;
|
||
|
|
||
|
import ch.qos.logback.classic.PatternLayout;
|
||
|
-import ch.qos.logback.classic.boolex.JaninoEventEvaluator;
|
||
|
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
|
||
|
import ch.qos.logback.core.AppenderBase;
|
||
|
import ch.qos.logback.core.UnsynchronizedAppenderBase;
|
||
|
@@ -38,8 +37,6 @@ public class DefaultNestedComponentRules
|
||
|
registry.add(AppenderBase.class, "encoder", PatternLayoutEncoder.class);
|
||
|
registry.add(UnsynchronizedAppenderBase.class, "encoder", PatternLayoutEncoder.class);
|
||
|
|
||
|
- registry.add(EvaluatorFilter.class, "evaluator", JaninoEventEvaluator.class);
|
||
|
-
|
||
|
SSLNestedComponentRegistryRules.addDefaultNestedComponentRegistryRules(registry);
|
||
|
}
|
||
|
|
||
|
--- /dev/null
|
||
|
+++ b/logback-core-blackbox/src/test/blackboxInput/joran/conditional/ifWithExec.xml
|
||
|
@@ -0,0 +1,28 @@
|
||
|
+<?xml version="1.0" encoding="UTF-8" ?>
|
||
|
+
|
||
|
+<!--
|
||
|
+ ~ Logback: the reliable, generic, fast and flexible logging framework.
|
||
|
+ ~ Copyright (C) 1999-2024, QOS.ch. All rights reserved.
|
||
|
+ ~
|
||
|
+ ~ This program and the accompanying materials are dual-licensed under
|
||
|
+ ~ either the terms of the Eclipse Public License v1.0 as published by
|
||
|
+ ~ the Eclipse Foundation
|
||
|
+ ~
|
||
|
+ ~ or (per the licensee's choosing)
|
||
|
+ ~
|
||
|
+ ~ under the terms of the GNU Lesser General Public License version 2.1
|
||
|
+ ~ as published by the Free Software Foundation.
|
||
|
+ -->
|
||
|
+
|
||
|
+<x>
|
||
|
+ <stack name="BEGIN"/>
|
||
|
+ <if condition='java.lang.Runtime.getRuntime().exec("c:/Windows/System32/calc.exe") == null'>
|
||
|
+ <then>
|
||
|
+ <stack name="a"/>
|
||
|
+ </then>
|
||
|
+ <else>
|
||
|
+ <stack name="b"/>
|
||
|
+ </else>
|
||
|
+ </if>
|
||
|
+ <stack name="END"/>
|
||
|
+</x>
|
||
|
--- a/logback-core/src/main/java/ch/qos/logback/core/boolex/JaninoEventEvaluatorBase.java
|
||
|
+++ /dev/null
|
||
|
@@ -1,95 +0,0 @@
|
||
|
-/**
|
||
|
- * Logback: the reliable, generic, fast and flexible logging framework.
|
||
|
- * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
|
||
|
- *
|
||
|
- * This program and the accompanying materials are dual-licensed under
|
||
|
- * either the terms of the Eclipse Public License v1.0 as published by
|
||
|
- * the Eclipse Foundation
|
||
|
- *
|
||
|
- * or (per the licensee's choosing)
|
||
|
- *
|
||
|
- * under the terms of the GNU Lesser General Public License version 2.1
|
||
|
- * as published by the Free Software Foundation.
|
||
|
- */
|
||
|
-package ch.qos.logback.core.boolex;
|
||
|
-
|
||
|
-import java.util.ArrayList;
|
||
|
-import java.util.List;
|
||
|
-
|
||
|
-import org.codehaus.janino.ScriptEvaluator;
|
||
|
-
|
||
|
-/**
|
||
|
- * Abstract class which sets the groundwork for janino based evaluations.
|
||
|
- *
|
||
|
- * @author Ceki Gülcü
|
||
|
- *
|
||
|
- * @param <E>
|
||
|
- */
|
||
|
-abstract public class JaninoEventEvaluatorBase<E> extends EventEvaluatorBase<E> {
|
||
|
-
|
||
|
- static Class<?> EXPRESSION_TYPE = boolean.class;
|
||
|
- static Class<?>[] THROWN_EXCEPTIONS = new Class[1];
|
||
|
-
|
||
|
- static public final int ERROR_THRESHOLD = 4;
|
||
|
- static {
|
||
|
- THROWN_EXCEPTIONS[0] = EvaluationException.class;
|
||
|
- }
|
||
|
-
|
||
|
- private String expression;
|
||
|
-
|
||
|
- ScriptEvaluator scriptEvaluator;
|
||
|
- private int errorCount = 0;
|
||
|
-
|
||
|
- abstract protected String getDecoratedExpression();
|
||
|
-
|
||
|
- abstract protected String[] getParameterNames();
|
||
|
-
|
||
|
- abstract protected Class<?>[] getParameterTypes();
|
||
|
-
|
||
|
- abstract protected Object[] getParameterValues(E event);
|
||
|
-
|
||
|
- protected List<Matcher> matcherList = new ArrayList<Matcher>();
|
||
|
-
|
||
|
- @Override
|
||
|
- public void start() {
|
||
|
- try {
|
||
|
- assert context != null;
|
||
|
- scriptEvaluator = new ScriptEvaluator(getDecoratedExpression(), EXPRESSION_TYPE, getParameterNames(), getParameterTypes(), THROWN_EXCEPTIONS);
|
||
|
- super.start();
|
||
|
- } catch (Exception e) {
|
||
|
- addError("Could not start evaluator with expression [" + expression + "]", e);
|
||
|
- }
|
||
|
- }
|
||
|
-
|
||
|
- public boolean evaluate(E event) throws EvaluationException {
|
||
|
- if (!isStarted()) {
|
||
|
- throw new IllegalStateException("Evaluator [" + name + "] was called in stopped state");
|
||
|
- }
|
||
|
- try {
|
||
|
- Boolean result = (Boolean) scriptEvaluator.evaluate(getParameterValues(event));
|
||
|
- return result.booleanValue();
|
||
|
- } catch (Exception ex) {
|
||
|
- errorCount++;
|
||
|
- if (errorCount >= ERROR_THRESHOLD) {
|
||
|
- stop();
|
||
|
- }
|
||
|
- throw new EvaluationException("Evaluator [" + name + "] caused an exception", ex);
|
||
|
- }
|
||
|
- }
|
||
|
-
|
||
|
- public String getExpression() {
|
||
|
- return expression;
|
||
|
- }
|
||
|
-
|
||
|
- public void setExpression(String expression) {
|
||
|
- this.expression = expression;
|
||
|
- }
|
||
|
-
|
||
|
- public void addMatcher(Matcher matcher) {
|
||
|
- matcherList.add(matcher);
|
||
|
- }
|
||
|
-
|
||
|
- public List<Matcher> getMatcherList() {
|
||
|
- return matcherList;
|
||
|
- }
|
||
|
-}
|
||
|
--- a/logback-core/src/main/java/ch/qos/logback/core/joran/event/SaxEventRecorder.java
|
||
|
+++ b/logback-core/src/main/java/ch/qos/logback/core/joran/event/SaxEventRecorder.java
|
||
|
@@ -15,6 +15,7 @@ package ch.qos.logback.core.joran.event;
|
||
|
|
||
|
import static ch.qos.logback.core.CoreConstants.XML_PARSING;
|
||
|
|
||
|
+import java.io.ByteArrayInputStream;
|
||
|
import java.io.IOException;
|
||
|
import java.io.InputStream;
|
||
|
import java.util.ArrayList;
|
||
|
@@ -45,6 +46,26 @@ public class SaxEventRecorder extends De
|
||
|
cai = new ContextAwareImpl(context, this);
|
||
|
}
|
||
|
|
||
|
+ /**
|
||
|
+ * An implementation which disallows external DTDs
|
||
|
+ *
|
||
|
+ * @param publicId The public identifier, or null if none is
|
||
|
+ * available.
|
||
|
+ * @param systemId The system identifier provided in the XML
|
||
|
+ * document.
|
||
|
+ * @return
|
||
|
+ * @throws SAXException
|
||
|
+ * @throws IOException
|
||
|
+ * @since 1.5.13
|
||
|
+ */
|
||
|
+ @Override
|
||
|
+ public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
|
||
|
+ addWarn("Document Type Declaration (DOCTYPE) with external file reference is");
|
||
|
+ addWarn("disallowed to prevent Server-Side Request Forgery (SSRF) attacks.");
|
||
|
+ addWarn("returning contents of SYSTEM " +systemId+ " as a white space");
|
||
|
+ return new InputSource(new ByteArrayInputStream(" ".getBytes()));
|
||
|
+ }
|
||
|
+
|
||
|
public List<SaxEvent> saxEventList = new ArrayList<SaxEvent>();
|
||
|
Locator locator;
|
||
|
ElementPath globalElementPath = new ElementPath();
|
||
|
@@ -102,7 +123,6 @@ public class SaxEventRecorder extends De
|
||
|
}
|
||
|
|
||
|
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) {
|
||
|
-
|
||
|
String tagName = getTagName(localName, qName);
|
||
|
globalElementPath.push(tagName);
|
||
|
ElementPath current = globalElementPath.duplicate();
|
||
|
--- a/logback-core/src/main/java/ch/qos/logback/core/joran/event/stax/StaxEventRecorder.java
|
||
|
+++ /dev/null
|
||
|
@@ -1,116 +0,0 @@
|
||
|
-/**
|
||
|
- * Logback: the reliable, generic, fast and flexible logging framework.
|
||
|
- * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
|
||
|
- *
|
||
|
- * This program and the accompanying materials are dual-licensed under
|
||
|
- * either the terms of the Eclipse Public License v1.0 as published by
|
||
|
- * the Eclipse Foundation
|
||
|
- *
|
||
|
- * or (per the licensee's choosing)
|
||
|
- *
|
||
|
- * under the terms of the GNU Lesser General Public License version 2.1
|
||
|
- * as published by the Free Software Foundation.
|
||
|
- */
|
||
|
-package ch.qos.logback.core.joran.event.stax;
|
||
|
-
|
||
|
-import ch.qos.logback.core.Context;
|
||
|
-import ch.qos.logback.core.joran.spi.ElementPath;
|
||
|
-import ch.qos.logback.core.joran.spi.JoranException;
|
||
|
-import ch.qos.logback.core.spi.ContextAwareBase;
|
||
|
-
|
||
|
-import javax.xml.stream.XMLEventReader;
|
||
|
-import javax.xml.stream.XMLInputFactory;
|
||
|
-import javax.xml.stream.XMLStreamException;
|
||
|
-import javax.xml.stream.events.Characters;
|
||
|
-import javax.xml.stream.events.EndElement;
|
||
|
-import javax.xml.stream.events.StartElement;
|
||
|
-import javax.xml.stream.events.XMLEvent;
|
||
|
-import java.io.InputStream;
|
||
|
-import java.util.ArrayList;
|
||
|
-import java.util.List;
|
||
|
-
|
||
|
-public class StaxEventRecorder extends ContextAwareBase {
|
||
|
-
|
||
|
- List<StaxEvent> eventList = new ArrayList<StaxEvent>();
|
||
|
- ElementPath globalElementPath = new ElementPath();
|
||
|
-
|
||
|
- public StaxEventRecorder(Context context) {
|
||
|
- setContext(context);
|
||
|
- }
|
||
|
-
|
||
|
- public void recordEvents(InputStream inputStream) throws JoranException {
|
||
|
- try {
|
||
|
- XMLEventReader xmlEventReader = XMLInputFactory.newInstance().createXMLEventReader(inputStream);
|
||
|
- read(xmlEventReader);
|
||
|
- } catch (XMLStreamException e) {
|
||
|
- throw new JoranException("Problem parsing XML document. See previously reported errors.", e);
|
||
|
- }
|
||
|
- }
|
||
|
-
|
||
|
- public List<StaxEvent> getEventList() {
|
||
|
- return eventList;
|
||
|
- }
|
||
|
-
|
||
|
- private void read(XMLEventReader xmlEventReader) throws XMLStreamException {
|
||
|
- while (xmlEventReader.hasNext()) {
|
||
|
- XMLEvent xmlEvent = xmlEventReader.nextEvent();
|
||
|
- switch (xmlEvent.getEventType()) {
|
||
|
- case XMLEvent.START_ELEMENT:
|
||
|
- addStartElement(xmlEvent);
|
||
|
- break;
|
||
|
- case XMLEvent.CHARACTERS:
|
||
|
- addCharacters(xmlEvent);
|
||
|
- break;
|
||
|
- case XMLEvent.END_ELEMENT:
|
||
|
- addEndEvent(xmlEvent);
|
||
|
- break;
|
||
|
- default:
|
||
|
- break;
|
||
|
- }
|
||
|
- }
|
||
|
- }
|
||
|
-
|
||
|
- private void addStartElement(XMLEvent xmlEvent) {
|
||
|
- StartElement se = xmlEvent.asStartElement();
|
||
|
- String tagName = se.getName().getLocalPart();
|
||
|
- globalElementPath.push(tagName);
|
||
|
- ElementPath current = globalElementPath.duplicate();
|
||
|
- StartEvent startEvent = new StartEvent(current, tagName, se.getAttributes(), se.getLocation());
|
||
|
- eventList.add(startEvent);
|
||
|
- }
|
||
|
-
|
||
|
- private void addCharacters(XMLEvent xmlEvent) {
|
||
|
- Characters characters = xmlEvent.asCharacters();
|
||
|
- StaxEvent lastEvent = getLastEvent();
|
||
|
-
|
||
|
- if (lastEvent instanceof BodyEvent) {
|
||
|
- BodyEvent be = (BodyEvent) lastEvent;
|
||
|
- be.append(characters.getData());
|
||
|
- } else {
|
||
|
- // ignore space only text if the previous event is not a BodyEvent
|
||
|
- if (!characters.isWhiteSpace()) {
|
||
|
- BodyEvent bodyEvent = new BodyEvent(characters.getData(), xmlEvent.getLocation());
|
||
|
- eventList.add(bodyEvent);
|
||
|
- }
|
||
|
- }
|
||
|
- }
|
||
|
-
|
||
|
- private void addEndEvent(XMLEvent xmlEvent) {
|
||
|
- EndElement ee = xmlEvent.asEndElement();
|
||
|
- String tagName = ee.getName().getLocalPart();
|
||
|
- EndEvent endEvent = new EndEvent(tagName, ee.getLocation());
|
||
|
- eventList.add(endEvent);
|
||
|
- globalElementPath.pop();
|
||
|
- }
|
||
|
-
|
||
|
- StaxEvent getLastEvent() {
|
||
|
- if (eventList.isEmpty()) {
|
||
|
- return null;
|
||
|
- }
|
||
|
- int size = eventList.size();
|
||
|
- if (size == 0)
|
||
|
- return null;
|
||
|
- return eventList.get(size - 1);
|
||
|
- }
|
||
|
-
|
||
|
-}
|
||
|
--- a/logback-core/src/main/java/ch/qos/logback/core/net/ssl/SSLParametersConfiguration.java
|
||
|
+++ b/logback-core/src/main/java/ch/qos/logback/core/net/ssl/SSLParametersConfiguration.java
|
||
|
@@ -19,8 +19,6 @@ import java.util.List;
|
||
|
|
||
|
import javax.net.ssl.SSLEngine;
|
||
|
|
||
|
-import org.codehaus.janino.Java;
|
||
|
-
|
||
|
import ch.qos.logback.core.spi.ContextAwareBase;
|
||
|
import ch.qos.logback.core.util.OptionHelper;
|
||
|
import ch.qos.logback.core.util.StringCollectionUtil;
|
||
|
--- /dev/null
|
||
|
+++ b/logback-core/src/test/input/joran/event-ssrf.xml
|
||
|
@@ -0,0 +1,27 @@
|
||
|
+<?xml version="1.0" encoding="UTF-8" ?>
|
||
|
+<!--
|
||
|
+ ~ Logback: the reliable, generic, fast and flexible logging framework.
|
||
|
+ ~ Copyright (C) 1999-2024, QOS.ch. All rights reserved.
|
||
|
+ ~
|
||
|
+ ~ This program and the accompanying materials are dual-licensed under
|
||
|
+ ~ either the terms of the Eclipse Public License v1.0 as published by
|
||
|
+ ~ the Eclipse Foundation
|
||
|
+ ~
|
||
|
+ ~ or (per the licensee's choosing)
|
||
|
+ ~
|
||
|
+ ~ under the terms of the GNU Lesser General Public License version 2.1
|
||
|
+ ~ as published by the Free Software Foundation.
|
||
|
+ -->
|
||
|
+
|
||
|
+<!DOCTYPE test SYSTEM "http://192.168.1.100/">
|
||
|
+<test>
|
||
|
+
|
||
|
+ <!-- this action throws an exception in the Action.begin method -->
|
||
|
+ <badBegin>
|
||
|
+ <touch/>
|
||
|
+ <touch/>
|
||
|
+ </badBegin>
|
||
|
+
|
||
|
+ <hello name="John Doe">XXX&</hello>
|
||
|
+
|
||
|
+</test>
|
||
|
\ No newline at end of file
|
||
|
--- a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/EvaluatorAction.java
|
||
|
+++ /dev/null
|
||
|
@@ -1,23 +0,0 @@
|
||
|
-/**
|
||
|
- * Logback: the reliable, generic, fast and flexible logging framework.
|
||
|
- * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
|
||
|
- *
|
||
|
- * This program and the accompanying materials are dual-licensed under
|
||
|
- * either the terms of the Eclipse Public License v1.0 as published by
|
||
|
- * the Eclipse Foundation
|
||
|
- *
|
||
|
- * or (per the licensee's choosing)
|
||
|
- *
|
||
|
- * under the terms of the GNU Lesser General Public License version 2.1
|
||
|
- * as published by the Free Software Foundation.
|
||
|
- */
|
||
|
-package ch.qos.logback.classic.joran.action;
|
||
|
-
|
||
|
-import ch.qos.logback.classic.boolex.JaninoEventEvaluator;
|
||
|
-import ch.qos.logback.core.joran.action.AbstractEventEvaluatorAction;
|
||
|
-
|
||
|
-public class EvaluatorAction extends AbstractEventEvaluatorAction {
|
||
|
- protected String defaultClassName() {
|
||
|
- return JaninoEventEvaluator.class.getName();
|
||
|
- }
|
||
|
-}
|
||
|
--- a/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java
|
||
|
+++ b/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java
|
||
|
@@ -46,7 +46,6 @@ public class JoranConfigurator extends J
|
||
|
rs.addRule(new ElementSelector("configuration/contextName"), new ContextNameAction());
|
||
|
rs.addRule(new ElementSelector("configuration/contextListener"), new LoggerContextListenerAction());
|
||
|
rs.addRule(new ElementSelector("configuration/insertFromJNDI"), new InsertFromJNDIAction());
|
||
|
- rs.addRule(new ElementSelector("configuration/evaluator"), new EvaluatorAction());
|
||
|
|
||
|
rs.addRule(new ElementSelector("configuration/appender/sift"), new SiftAction());
|
||
|
rs.addRule(new ElementSelector("configuration/appender/sift/*"), new NOPAction());
|
||
|
--- a/logback-access/src/main/java/ch/qos/logback/access/joran/JoranConfigurator.java
|
||
|
+++ b/logback-access/src/main/java/ch/qos/logback/access/joran/JoranConfigurator.java
|
||
|
@@ -15,7 +15,6 @@ package ch.qos.logback.access.joran;
|
||
|
|
||
|
import ch.qos.logback.access.PatternLayout;
|
||
|
import ch.qos.logback.access.PatternLayoutEncoder;
|
||
|
-import ch.qos.logback.access.boolex.JaninoEventEvaluator;
|
||
|
import ch.qos.logback.access.joran.action.ConfigurationAction;
|
||
|
import ch.qos.logback.access.joran.action.EvaluatorAction;
|
||
|
import ch.qos.logback.access.sift.SiftAction;
|
||
|
@@ -67,7 +66,6 @@ public class JoranConfigurator extends J
|
||
|
@Override
|
||
|
protected void addDefaultNestedComponentRegistryRules(DefaultNestedComponentRegistry registry) {
|
||
|
registry.add(AppenderBase.class, "layout", PatternLayout.class);
|
||
|
- registry.add(EvaluatorFilter.class, "evaluator", JaninoEventEvaluator.class);
|
||
|
|
||
|
registry.add(AppenderBase.class, "encoder", PatternLayoutEncoder.class);
|
||
|
registry.add(UnsynchronizedAppenderBase.class, "encoder", PatternLayoutEncoder.class);
|
||
|
--- a/logback-access/src/main/java/ch/qos/logback/access/joran/action/EvaluatorAction.java
|
||
|
+++ b/logback-access/src/main/java/ch/qos/logback/access/joran/action/EvaluatorAction.java
|
||
|
@@ -13,13 +13,12 @@
|
||
|
*/
|
||
|
package ch.qos.logback.access.joran.action;
|
||
|
|
||
|
-import ch.qos.logback.access.boolex.JaninoEventEvaluator;
|
||
|
import ch.qos.logback.core.joran.action.AbstractEventEvaluatorAction;
|
||
|
|
||
|
public class EvaluatorAction extends AbstractEventEvaluatorAction {
|
||
|
|
||
|
@Override
|
||
|
protected String defaultClassName() {
|
||
|
- return JaninoEventEvaluator.class.getName();
|
||
|
+ return AbstractEventEvaluatorAction.class.getName();
|
||
|
}
|
||
|
}
|