diff --git a/CVE-2021-4104.patch b/CVE-2021-4104.patch new file mode 100644 index 0000000000000000000000000000000000000000..3438d87e25572edd39e87b6f399b1327b4005588 --- /dev/null +++ b/CVE-2021-4104.patch @@ -0,0 +1,166 @@ +From: Markus Koschany +Date: Mon, 31 Jan 2022 11:18:33 +0100 +Subject: CVE-2021-4104 + +Origin: https://github.com/qos-ch/reload4j/commit/fb7b1ff1c8beb8544933248d00a46e9e30547e87 +Origin: https://github.com/qos-ch/reload4j/commit/e65c98bbba48cb877e057992847114f1f0923da6 +--- + .../java/org/apache/log4j/net/JMSAppender.java | 11 ++--- + src/main/java/org/apache/log4j/net/JNDIUtil.java | 54 +++++++++++++++++++++ + .../java/org/apache/log4j/net/JNDIUtilTest.java | 55 ++++++++++++++++++++++ + 3 files changed, 114 insertions(+), 6 deletions(-) + create mode 100755 src/main/java/org/apache/log4j/net/JNDIUtil.java + create mode 100755 src/test/java/org/apache/log4j/net/JNDIUtilTest.java + +diff --git a/src/main/java/org/apache/log4j/net/JMSAppender.java b/src/main/java/org/apache/log4j/net/JMSAppender.java +index 3482702..c390aef 100644 +--- a/src/main/java/org/apache/log4j/net/JMSAppender.java ++++ b/src/main/java/org/apache/log4j/net/JMSAppender.java +@@ -32,7 +32,6 @@ import javax.jms.TopicPublisher; + import javax.jms.TopicSession; + import javax.naming.Context; + import javax.naming.InitialContext; +-import javax.naming.NameNotFoundException; + import javax.naming.NamingException; + import java.util.Properties; + +@@ -241,12 +240,12 @@ public class JMSAppender extends AppenderSkeleton { + } + + protected Object lookup(Context ctx, String name) throws NamingException { +- try { +- return ctx.lookup(name); +- } catch(NameNotFoundException e) { +- LogLog.error("Could not find name ["+name+"]."); +- throw e; ++ Object result = JNDIUtil.lookupObject(ctx, name); ++ if (result == null) { ++ String msg = "Could not find name [" + name + "]."; ++ throw new NamingException(msg); + } ++ return result; + } + + protected boolean checkEntryConditions() { +diff --git a/src/main/java/org/apache/log4j/net/JNDIUtil.java b/src/main/java/org/apache/log4j/net/JNDIUtil.java +new file mode 100755 +index 0000000..3a66a05 +--- /dev/null ++++ b/src/main/java/org/apache/log4j/net/JNDIUtil.java +@@ -0,0 +1,54 @@ ++/* ++ * 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.log4j.net; ++ ++import javax.naming.Context; ++import javax.naming.NamingException; ++ ++public class JNDIUtil { ++ ++ // See https://jakarta.ee/specifications/platform/8/platform-spec-8.html#a616 ++ // there are the java:comp, java:module, java:app, java:global namespaces ++ public static final String JNDI_JAVA_NAMESPACE = "java:"; ++ ++ static final String RESTRICTION_MSG = "JNDI name must start with " + JNDI_JAVA_NAMESPACE + " but was "; ++ ++ public static Object lookupObject(Context ctx, String name) throws NamingException { ++ if (ctx == null) { ++ return null; ++ } ++ ++ if (isNullOrEmpty(name)) { ++ return null; ++ } ++ ++ jndiNameSecurityCheck(name); ++ ++ Object lookup = ctx.lookup(name); ++ return lookup; ++ } ++ ++ private static boolean isNullOrEmpty(String str) { ++ return ((str == null) || str.trim().length() == 0); ++ } ++ ++ public static void jndiNameSecurityCheck(String name) throws NamingException { ++ if (!name.startsWith(JNDI_JAVA_NAMESPACE)) { ++ throw new NamingException(RESTRICTION_MSG + name); ++ } ++ } ++} +diff --git a/src/test/java/org/apache/log4j/net/JNDIUtilTest.java b/src/test/java/org/apache/log4j/net/JNDIUtilTest.java +new file mode 100755 +index 0000000..2439bc7 +--- /dev/null ++++ b/src/test/java/org/apache/log4j/net/JNDIUtilTest.java +@@ -0,0 +1,55 @@ ++/* ++ * 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.log4j.net; ++ ++import static org.junit.Assert.fail; ++ ++import javax.naming.Context; ++import javax.naming.InitialContext; ++import javax.naming.NamingException; ++ ++import org.junit.Test; ++ ++ ++/** ++ * Test copied form the logback project with permission. ++ * ++ * @author Ceki Gulcu ++ * ++ */ ++public class JNDIUtilTest { ++ ++ @Test ++ public void ensureJavaNameSpace() throws NamingException { ++ ++ try { ++ Context ctxt = new InitialContext(); ++ JNDIUtil.lookupObject(ctxt, "ldap:..."); ++ } catch (NamingException e) { ++ String excaptionMsg = e.getMessage(); ++ if (excaptionMsg.startsWith(JNDIUtil.RESTRICTION_MSG)) ++ return; ++ else { ++ fail("unexpected exception " + e); ++ } ++ } ++ ++ fail("Should aNot yet implemented"); ++ } ++ ++ ++} +\ No newline at end of file diff --git a/CVE-2022-23302.patch b/CVE-2022-23302.patch new file mode 100644 index 0000000000000000000000000000000000000000..200bef6499d3d81717aef251892262f3c5a6e858 --- /dev/null +++ b/CVE-2022-23302.patch @@ -0,0 +1,48 @@ +From: Markus Koschany +Date: Mon, 31 Jan 2022 11:30:35 +0100 +Subject: CVE-2022-23302 + +Origin: https://github.com/qos-ch/reload4j/commit/f221f2427c45134cf5768f46279ddf72fe1407c9 +--- + src/main/java/org/apache/log4j/net/JMSSink.java | 14 ++------------ + 1 file changed, 2 insertions(+), 12 deletions(-) + +diff --git a/src/main/java/org/apache/log4j/net/JMSSink.java b/src/main/java/org/apache/log4j/net/JMSSink.java +index 6a02831..c25b4a3 100644 +--- a/src/main/java/org/apache/log4j/net/JMSSink.java ++++ b/src/main/java/org/apache/log4j/net/JMSSink.java +@@ -88,8 +88,7 @@ public class JMSSink implements javax.jms.MessageListener { + try { + Context ctx = new InitialContext(); + TopicConnectionFactory topicConnectionFactory; +- topicConnectionFactory = (TopicConnectionFactory) lookup(ctx, +- tcfBindingName); ++ topicConnectionFactory = (TopicConnectionFactory) JNDIUtil.lookupObject(ctx, tcfBindingName); + + TopicConnection topicConnection = + topicConnectionFactory.createTopicConnection(username, +@@ -99,7 +98,7 @@ public class JMSSink implements javax.jms.MessageListener { + TopicSession topicSession = topicConnection.createTopicSession(false, + Session.AUTO_ACKNOWLEDGE); + +- Topic topic = (Topic)ctx.lookup(topicBindingName); ++ Topic topic = (Topic) JNDIUtil.lookupObject(ctx, topicBindingName); + + TopicSubscriber topicSubscriber = topicSession.createSubscriber(topic); + +@@ -135,15 +134,6 @@ public class JMSSink implements javax.jms.MessageListener { + } + + +- protected static Object lookup(Context ctx, String name) throws NamingException { +- try { +- return ctx.lookup(name); +- } catch(NameNotFoundException e) { +- logger.error("Could not find name ["+name+"]."); +- throw e; +- } +- } +- + static void usage(String msg) { + System.err.println(msg); + System.err.println("Usage: java " + JMSSink.class.getName() diff --git a/CVE-2022-23305.patch b/CVE-2022-23305.patch new file mode 100644 index 0000000000000000000000000000000000000000..0577eac27c8297e76dd5f7b351f83365cf469656 --- /dev/null +++ b/CVE-2022-23305.patch @@ -0,0 +1,631 @@ +From: Markus Koschany +Date: Mon, 31 Jan 2022 10:55:04 +0100 +Subject: CVE-2022-23305 + +Origin: https://github.com/qos-ch/reload4j/pull/26/commits/33d1697bb13b8cf869c450a64f8550b1593f8035 +--- + pom.xml | 6 + + .../java/org/apache/log4j/jdbc/JDBCAppender.java | 97 ++++++++-- + .../org/apache/log4j/jdbc/JdbcPatternParser.java | 101 ++++++++++ + src/test/input/jdbc_h2_bufferSize1.properties | 25 +++ + src/test/input/jdbc_h2_bufferSize2.properties | 25 +++ + .../org/apache/log4j/jdbc/JdbcAppenderTest.java | 208 +++++++++++++++++++++ + .../apache/log4j/jdbc/JdbcPatternParserTest.java | 50 +++++ + 7 files changed, 495 insertions(+), 17 deletions(-) + create mode 100644 src/main/java/org/apache/log4j/jdbc/JdbcPatternParser.java + create mode 100644 src/test/input/jdbc_h2_bufferSize1.properties + create mode 100644 src/test/input/jdbc_h2_bufferSize2.properties + create mode 100644 src/test/java/org/apache/log4j/jdbc/JdbcAppenderTest.java + create mode 100644 src/test/java/org/apache/log4j/jdbc/JdbcPatternParserTest.java + +diff --git a/pom.xml b/pom.xml +index 93881cd..3ec2ccc 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -577,6 +577,12 @@ target platform and specify -Dntdll_target=msbuild on the mvn command line. + 1.0 + true + ++ ++ com.h2database ++ h2 ++ 2.1.210 ++ test ++ + + + +diff --git a/src/main/java/org/apache/log4j/jdbc/JDBCAppender.java b/src/main/java/org/apache/log4j/jdbc/JDBCAppender.java +index ad35f65..2f979ae 100644 +--- a/src/main/java/org/apache/log4j/jdbc/JDBCAppender.java ++++ b/src/main/java/org/apache/log4j/jdbc/JDBCAppender.java +@@ -18,6 +18,7 @@ package org.apache.log4j.jdbc; + + import java.sql.Connection; + import java.sql.DriverManager; ++import java.sql.PreparedStatement; + import java.sql.SQLException; + import java.sql.Statement; + import java.util.ArrayList; +@@ -78,6 +79,12 @@ import org.apache.log4j.spi.LoggingEvent; + public class JDBCAppender extends org.apache.log4j.AppenderSkeleton + implements org.apache.log4j.Appender { + ++ private final Boolean secureSqlReplacement = ++ Boolean.parseBoolean(System.getProperty("org.apache.log4j.jdbc.JDBCAppender.secure_jdbc_replacement", "true")); ++ ++ private static final IllegalArgumentException ILLEGAL_PATTERN_FOR_SECURE_EXEC = ++ new IllegalArgumentException("Only org.apache.log4j.PatternLayout is supported for now due to CVE-2022-23305"); ++ + /** + * URL of the DB for default connection handling + */ +@@ -113,6 +120,8 @@ public class JDBCAppender extends org.apache.log4j.AppenderSkeleton + */ + protected String sqlStatement = ""; + ++ private JdbcPatternParser preparedStatementParser = new JdbcPatternParser(); ++ + /** + * size of LoggingEvent buffer before writting to the database. + * Default is 1. +@@ -245,11 +254,11 @@ public class JDBCAppender extends org.apache.log4j.AppenderSkeleton + */ + protected Connection getConnection() throws SQLException { + if (!DriverManager.getDrivers().hasMoreElements()) +- setDriver("sun.jdbc.odbc.JdbcOdbcDriver"); ++ setDriver("sun.jdbc.odbc.JdbcOdbcDriver"); + + if (connection == null) { + connection = DriverManager.getConnection(databaseURL, databaseUser, +- databasePassword); ++ databasePassword); + } + + return connection; +@@ -280,29 +289,83 @@ public class JDBCAppender extends org.apache.log4j.AppenderSkeleton + * If a statement fails the LoggingEvent stays in the buffer! + */ + public void flushBuffer() { ++ if (buffer.isEmpty()) { ++ return; ++ } + //Do the actual logging + removes.ensureCapacity(buffer.size()); +- for (Iterator i = buffer.iterator(); i.hasNext();) { +- LoggingEvent logEvent = (LoggingEvent)i.next(); +- try { +- String sql = getLogStatement(logEvent); +- execute(sql); +- } +- catch (SQLException e) { +- errorHandler.error("Failed to excute sql", e, +- ErrorCode.FLUSH_FAILURE); +- } finally { +- removes.add(logEvent); +- } ++ if (secureSqlReplacement) { ++ flushBufferSecure(); ++ } else { ++ flushBufferInsecure(); + } +- + // remove from the buffer any events that were reported + buffer.removeAll(removes); +- ++ + // clear the buffer of reported events + removes.clear(); + } + ++ private void flushBufferInsecure() { ++ for (Iterator i = buffer.iterator(); i.hasNext(); ) { ++ LoggingEvent logEvent = (LoggingEvent) i.next(); ++ try { ++ String sql = getLogStatement(logEvent); ++ execute(sql); ++ } catch (SQLException e) { ++ errorHandler.error("Failed to excute sql", e, ErrorCode.FLUSH_FAILURE); ++ } finally { ++ removes.add(logEvent); ++ } ++ } ++ } ++ ++ private void flushBufferSecure() { ++ // Prepare events that we will store to the DB ++ removes.addAll(buffer); ++ ++ if (layout.getClass() != PatternLayout.class) { ++ errorHandler.error("Failed to convert pattern " + layout + " to SQL", ILLEGAL_PATTERN_FOR_SECURE_EXEC, ErrorCode.MISSING_LAYOUT); ++ return; ++ } ++ PatternLayout patternLayout = (PatternLayout) layout; ++ preparedStatementParser.setPattern(patternLayout.getConversionPattern()); ++ Connection con = null; ++ boolean useBatch = removes.size() > 1; ++ try { ++ con = getConnection(); ++ PreparedStatement ps = con.prepareStatement(preparedStatementParser.getParameterizedSql()); ++ try { ++ for (Iterator i = removes.iterator(); i.hasNext(); ) { ++ LoggingEvent logEvent = (LoggingEvent) i.next(); ++ try { ++ preparedStatementParser.setParameters(ps, logEvent); ++ if (useBatch) { ++ ps.addBatch(); ++ } ++ } catch (SQLException e) { ++ errorHandler.error("Failed to append parameters", e, ErrorCode.FLUSH_FAILURE); ++ } ++ } ++ if (useBatch) { ++ ps.executeBatch(); ++ } else { ++ ps.execute(); ++ } ++ } finally { ++ try { ++ ps.close(); ++ } catch (SQLException ignored) { ++ } ++ } ++ } catch (SQLException e) { ++ errorHandler.error("Failed to append messages sql", e, ErrorCode.FLUSH_FAILURE); ++ } finally { ++ if (con != null) { ++ closeConnection(con); ++ } ++ } ++ } + + /** closes the appender before disposal */ + public void finalize() { +@@ -391,7 +454,7 @@ public class JDBCAppender extends org.apache.log4j.AppenderSkeleton + Class.forName(driverClass); + } catch (Exception e) { + errorHandler.error("Failed to load driver", e, +- ErrorCode.GENERIC_FAILURE); ++ ErrorCode.GENERIC_FAILURE); + } + } + } +diff --git a/src/main/java/org/apache/log4j/jdbc/JdbcPatternParser.java b/src/main/java/org/apache/log4j/jdbc/JdbcPatternParser.java +new file mode 100644 +index 0000000..691ed56 +--- /dev/null ++++ b/src/main/java/org/apache/log4j/jdbc/JdbcPatternParser.java +@@ -0,0 +1,101 @@ ++/* ++ * 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.log4j.jdbc; ++ ++import org.apache.log4j.helpers.PatternConverter; ++import org.apache.log4j.helpers.PatternParser; ++import org.apache.log4j.spi.LoggingEvent; ++ ++import java.sql.PreparedStatement; ++import java.sql.SQLException; ++import java.util.ArrayList; ++import java.util.List; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++class JdbcPatternParser { ++ private final static Pattern STRING_LITERAL_PATTERN = Pattern.compile("'((?>[^']|'')+)'"); ++ ++ private String lastPattern; ++ private String parameterizedSql; ++ private final List argPatterns = new ArrayList(); ++ private final List args = new ArrayList(); ++ private StringBuffer buffer = new StringBuffer(); ++ ++ public String getParameterizedSql() { ++ return parameterizedSql; ++ } ++ ++ @Override ++ public String toString() { ++ return "JdbcPatternParser{sql=" + parameterizedSql + ",args=" + argPatterns + "}"; ++ } ++ ++ /** ++ * Converts '....' literals into bind variables in JDBC. ++ */ ++ void setPattern(String pattern) { ++ if (pattern == null) { ++ throw new IllegalArgumentException("Null pattern"); ++ } ++ if (pattern.equals(lastPattern)) { ++ return; ++ } ++ Matcher m = STRING_LITERAL_PATTERN.matcher(pattern); ++ StringBuffer sb = new StringBuffer(); ++ args.clear(); ++ argPatterns.clear(); ++ while (m.find()) { ++ String literal = m.group(1); ++ if (literal.indexOf('%') == -1) { ++ // Just literal, append it as is ++ // It can't contain user-provided parts like %m, etc. ++ m.appendReplacement(sb, "'$1'"); ++ continue; ++ } ++ ++ // Replace with bind ++ m.appendReplacement(sb, "?"); ++ // We will use prepared statements, so we don't need to escape quotes. ++ // And we assume the users had 'That''s a string with quotes' in their configs. ++ literal = literal.replaceAll("''", "'"); ++ argPatterns.add(literal); ++ args.add(new PatternParser(literal).parse()); ++ } ++ m.appendTail(sb); ++ parameterizedSql = sb.toString(); ++ lastPattern = pattern; ++ } ++ ++ public void setParameters(PreparedStatement ps, LoggingEvent logEvent) throws SQLException { ++ for (int i = 0; i < args.size(); i++) { ++ buffer.setLength(0); ++ PatternConverter c = args.get(i); ++ while (c != null) { ++ c.format(buffer, logEvent); ++ c = c.next; ++ } ++ ps.setString(i + 1, buffer.toString()); ++ } ++ // This clears "toString cache" ++ buffer.setLength(0); ++ if (buffer.capacity() > 100000) { ++ // Avoid leaking too much memory if we discover long parameter ++ buffer = new StringBuffer(); ++ } ++ } ++} +diff --git a/src/test/input/jdbc_h2_bufferSize1.properties b/src/test/input/jdbc_h2_bufferSize1.properties +new file mode 100644 +index 0000000..77e6083 +--- /dev/null ++++ b/src/test/input/jdbc_h2_bufferSize1.properties +@@ -0,0 +1,25 @@ ++# 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. ++ ++log4j.threshold=ALL ++log4j.rootLogger=ALL,A ++log4j.appender.A=org.apache.log4j.jdbc.JDBCAppender ++log4j.appender.A.URL=jdbc:h2:mem:test_db ++log4j.appender.A.driver=org.h2.Driver ++log4j.appender.A.bufferSize=1 ++log4j.appender.A.user= ++log4j.appender.A.password= ++log4j.appender.A.layout=org.apache.log4j.PatternLayout ++log4j.appender.A.sql=insert into logs(level,location,message,message2) values('%p','%c','%m', ' %c %p %m') +diff --git a/src/test/input/jdbc_h2_bufferSize2.properties b/src/test/input/jdbc_h2_bufferSize2.properties +new file mode 100644 +index 0000000..fba02a3 +--- /dev/null ++++ b/src/test/input/jdbc_h2_bufferSize2.properties +@@ -0,0 +1,25 @@ ++# 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. ++ ++log4j.threshold=ALL ++log4j.rootLogger=ALL,A ++log4j.appender.A=org.apache.log4j.jdbc.JDBCAppender ++log4j.appender.A.URL=jdbc:h2:mem:test_db ++log4j.appender.A.driver=org.h2.Driver ++log4j.appender.A.bufferSize=2 ++log4j.appender.A.user= ++log4j.appender.A.password= ++log4j.appender.A.layout=org.apache.log4j.PatternLayout ++log4j.appender.A.sql=insert into logs(level,location,message,message2) values('%p','%c','%m', ' %c %p %m') +diff --git a/src/test/java/org/apache/log4j/jdbc/JdbcAppenderTest.java b/src/test/java/org/apache/log4j/jdbc/JdbcAppenderTest.java +new file mode 100644 +index 0000000..f851063 +--- /dev/null ++++ b/src/test/java/org/apache/log4j/jdbc/JdbcAppenderTest.java +@@ -0,0 +1,208 @@ ++/* ++ * 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.log4j.jdbc; ++ ++import org.apache.log4j.Appender; ++import org.apache.log4j.LogManager; ++import org.apache.log4j.Logger; ++import org.apache.log4j.PropertyConfigurator; ++import org.apache.log4j.TestContants; ++import org.apache.log4j.VectorErrorHandler; ++import org.apache.log4j.xml.XLevel; ++import org.junit.After; ++import org.junit.Assert; ++import org.junit.Before; ++import org.junit.Test; ++ ++import java.sql.Connection; ++import java.sql.DriverManager; ++import java.sql.PreparedStatement; ++import java.sql.ResultSet; ++import java.sql.SQLException; ++import java.sql.Statement; ++import java.util.ArrayList; ++import java.util.Collections; ++import java.util.List; ++ ++public class JdbcAppenderTest { ++ // Closing the last connection to "in-memory h2" removes the database ++ // So we keep the connection during the test ++ // The logger opens its own connection ++ Connection con; ++ ++ @Before ++ public void setup() throws SQLException { ++ con = DriverManager.getConnection("jdbc:h2:mem:test_db"); ++ Statement st = con.createStatement(); ++ try { ++ st.execute("create table logs(level varchar(100),location varchar(100),message varchar(100),message2 varchar(100))"); ++ } finally { ++ st.close(); ++ } ++ } ++ ++ @After ++ public void cleanup() throws SQLException { ++ LogManager.shutdown(); ++ con.close(); ++ } ++ ++ @Test ++ public void verifyJdbcInsecure() throws SQLException { ++ String secureJdbcReplacement = "org.apache.log4j.jdbc.JDBCAppender.secure_jdbc_replacement"; ++ System.setProperty(secureJdbcReplacement, "false"); ++ try { ++ PropertyConfigurator.configure(TestContants.TEST_INPUT_PREFIX + "jdbc_h2_bufferSize1.properties"); ++ Appender jdbcAppender = LogManager.getRootLogger().getAppender("A"); ++ // Keep errors ++ VectorErrorHandler errorHandler = new VectorErrorHandler(); ++ jdbcAppender.setErrorHandler(errorHandler); ++ ++ Logger logger = Logger.getLogger(JdbcAppenderTest.class); ++ ++ String oldThreadName = Thread.currentThread().getName(); ++ try { ++ Thread.currentThread().setName("main"); ++ logger.debug("message with '' quote"); ++ Assert.assertEquals( ++ "batchSize=1, so messages should be added immediately", ++ "DEBUG; org.apache.log4j.jdbc.JdbcAppenderTest; message with ' quote; org.apache.log4j.jdbc.JdbcAppenderTest DEBUG message with ' quote\n", ++ joinSorted(getMessages())); ++ ++ // It should fail ++ logger.fatal("message with ' quote"); ++ ++ Assert.assertEquals( ++ "Inserting a message with ' should cause failure in insecure mode, so only one message should be in the DB", ++ "DEBUG; org.apache.log4j.jdbc.JdbcAppenderTest; message with ' quote; org.apache.log4j.jdbc.JdbcAppenderTest DEBUG message with ' quote\n", ++ joinSorted(getMessages())); ++ ++ StringBuilder exceptions = new StringBuilder(); ++ StringBuilder errorCodes = new StringBuilder(); ++ for (int i = 0; i < errorHandler.size(); i++) { ++ Exception ex = errorHandler.getException(i); ++ exceptions.append(ex.toString()); ++ errorCodes.append( ++ ex instanceof SQLException ++ ? ("SQLException.getErrorCode() = " + ((SQLException) ex).getErrorCode()) ++ : ("SQL Exception expected, got " + ex.getClass())); ++ exceptions.append('\n'); ++ errorCodes.append('\n'); ++ } ++ Assert.assertEquals( ++ "Logging a message with ' should trigger SQLException 'Syntax error in SQL statement...' when using insecure JDBCAppender mode, actual exceptions are\n" + exceptions, ++ "SQLException.getErrorCode() = 42001\n", ++ errorCodes.toString() ++ ); ++ } finally { ++ Thread.currentThread().setName(oldThreadName); ++ } ++ } finally { ++ System.getProperties().remove(secureJdbcReplacement); ++ } ++ } ++ ++ @Test ++ public void verifyJdbcBufferSize1() throws SQLException { ++ PropertyConfigurator.configure(TestContants.TEST_INPUT_PREFIX + "jdbc_h2_bufferSize1.properties"); ++ ++ Logger logger = Logger.getLogger(JdbcAppenderTest.class); ++ ++ String oldThreadName = Thread.currentThread().getName(); ++ try { ++ Thread.currentThread().setName("main"); ++ logger.debug("message with ' quote"); ++ Assert.assertEquals( ++ "batchSize=1, so messages should be added immediately", ++ "DEBUG; org.apache.log4j.jdbc.JdbcAppenderTest; message with ' quote; org.apache.log4j.jdbc.JdbcAppenderTest DEBUG message with ' quote\n", ++ joinSorted(getMessages())); ++ ++ logger.fatal("message with \" quote"); ++ ++ Assert.assertEquals( ++ "batchSize=1, so two messages should be in DB after two logging calls", ++ "DEBUG; org.apache.log4j.jdbc.JdbcAppenderTest; message with ' quote; org.apache.log4j.jdbc.JdbcAppenderTest DEBUG message with ' quote\n" + ++ "FATAL; org.apache.log4j.jdbc.JdbcAppenderTest; message with \" quote; org.apache.log4j.jdbc.JdbcAppenderTest FATAL message with \" quote\n", ++ joinSorted(getMessages())); ++ } finally { ++ Thread.currentThread().setName(oldThreadName); ++ } ++ } ++ ++ @Test ++ public void verifyJdbcBufferSize2() throws SQLException { ++ PropertyConfigurator.configure(TestContants.TEST_INPUT_PREFIX + "jdbc_h2_bufferSize2.properties"); ++ ++ Logger logger = Logger.getLogger(JdbcAppenderTest.class); ++ ++ String oldThreadName = Thread.currentThread().getName(); ++ try { ++ Thread.currentThread().setName("main"); ++ logger.log(XLevel.TRACE, "xtrace message"); ++ logger.debug("message with ' quote"); ++ logger.info("message with \" quote"); ++ logger.warn("?"); ++ // bufferSize=2, so this message won't yet be stored to the db ++ logger.error("m4"); ++ ++ Assert.assertEquals( ++ "DEBUG; org.apache.log4j.jdbc.JdbcAppenderTest; message with ' quote; org.apache.log4j.jdbc.JdbcAppenderTest DEBUG message with ' quote\n" + ++ "INFO; org.apache.log4j.jdbc.JdbcAppenderTest; message with \" quote; org.apache.log4j.jdbc.JdbcAppenderTest INFO message with \" quote\n" + ++ "TRACE; org.apache.log4j.jdbc.JdbcAppenderTest; xtrace message; org.apache.log4j.jdbc.JdbcAppenderTest TRACE xtrace message\n" + ++ "WARN; org.apache.log4j.jdbc.JdbcAppenderTest; ?; org.apache.log4j.jdbc.JdbcAppenderTest WARN ?\n", ++ joinSorted(getMessages())); ++ ++ logger.fatal("m5"); ++ ++ Assert.assertEquals( ++ "Logging m5 message should trigger buffer flush for both m4 and m5", ++ "DEBUG; org.apache.log4j.jdbc.JdbcAppenderTest; message with ' quote; org.apache.log4j.jdbc.JdbcAppenderTest DEBUG message with ' quote\n" + ++ "ERROR; org.apache.log4j.jdbc.JdbcAppenderTest; m4; org.apache.log4j.jdbc.JdbcAppenderTest ERROR m4\n" + ++ "FATAL; org.apache.log4j.jdbc.JdbcAppenderTest; m5; org.apache.log4j.jdbc.JdbcAppenderTest FATAL m5\n" + ++ "INFO; org.apache.log4j.jdbc.JdbcAppenderTest; message with \" quote; org.apache.log4j.jdbc.JdbcAppenderTest INFO message with \" quote\n" + ++ "TRACE; org.apache.log4j.jdbc.JdbcAppenderTest; xtrace message; org.apache.log4j.jdbc.JdbcAppenderTest TRACE xtrace message\n" + ++ "WARN; org.apache.log4j.jdbc.JdbcAppenderTest; ?; org.apache.log4j.jdbc.JdbcAppenderTest WARN ?\n", ++ joinSorted(getMessages())); ++ } finally { ++ Thread.currentThread().setName(oldThreadName); ++ } ++ } ++ ++ private static String joinSorted(List list) { ++ Collections.sort(list); ++ StringBuilder sb = new StringBuilder(); ++ for (String s : list) { ++ sb.append(s).append('\n'); ++ } ++ return sb.toString(); ++ } ++ ++ private List getMessages() throws SQLException { ++ List res = new ArrayList(); ++ PreparedStatement ps = con.prepareStatement("select level,location,message,message2 from logs"); ++ ResultSet rs = ps.executeQuery(); ++ try { ++ while (rs.next()) { ++ res.add(rs.getString(1) + "; " + rs.getString(2) ++ + "; " + rs.getString(3) + "; " + rs.getString(4)); ++ } ++ } finally { ++ rs.close(); ++ } ++ return res; ++ } ++} +diff --git a/src/test/java/org/apache/log4j/jdbc/JdbcPatternParserTest.java b/src/test/java/org/apache/log4j/jdbc/JdbcPatternParserTest.java +new file mode 100644 +index 0000000..aafbd80 +--- /dev/null ++++ b/src/test/java/org/apache/log4j/jdbc/JdbcPatternParserTest.java +@@ -0,0 +1,50 @@ ++/* ++ * 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.log4j.jdbc; ++ ++import org.junit.Assert; ++import org.junit.Test; ++ ++public class JdbcPatternParserTest { ++ JdbcPatternParser parser = new JdbcPatternParser(); ++ ++ @Test ++ public void testParameterizedSql() { ++ assertParameterizedSql( ++ "JdbcPatternParser{sql=INSERT INTO A1 (TITLE3) VALUES ( ? ),args=[ %d - %c %-5p %c %x - %m%n ]}", ++ "INSERT INTO A1 (TITLE3) VALUES ( ' %d - %c %-5p %c %x - %m%n ' )" ++ ); ++ assertParameterizedSql( ++ "JdbcPatternParser{sql=INSERT INTO A1 (TITLE3) VALUES ( ?, ?, ?, ?, ?, ? ),args=[%d, %c, %-5p, '%c, %x, - %m%n ]}", ++ "INSERT INTO A1 (TITLE3) VALUES ( '%d', '%c', '%-5p', ' ''%c', '%x', ' - %m%n ' )" ++ ); ++ ++ assertParameterizedSql( ++ "JdbcPatternParser{sql=INSERT INTO A1 (TITLE3) VALUES ( ' just string literal', 'another literal with quotes '' asdf', ?),args=[message: %m]}", ++ "INSERT INTO A1 (TITLE3) VALUES ( ' just string literal', 'another literal with quotes '' asdf', 'message: %m')" ++ ); ++ } ++ ++ private void assertParameterizedSql(String expected, String input) { ++ parser.setPattern(input); ++ Assert.assertEquals( ++ "parser.setPattern(...).toString() for " + input, ++ expected, ++ parser.toString() ++ ); ++ } ++} diff --git a/CVE-2022-23307.patch b/CVE-2022-23307.patch new file mode 100644 index 0000000000000000000000000000000000000000..13e042c261d294f3621b156465b9f39fa5c7f291 --- /dev/null +++ b/CVE-2022-23307.patch @@ -0,0 +1,343 @@ +From: Markus Koschany +Date: Mon, 31 Jan 2022 11:37:03 +0100 +Subject: CVE-2022-23307 + +Origin: https://github.com/qos-ch/reload4j/commit/64902fe18ce5a5dd40487051a2f6231d9fbbe9b0 +--- + .../org/apache/log4j/chainsaw/LoggingReceiver.java | 8 +- + .../log4j/net/HardenedLoggingEventInputStream.java | 56 +++++++++++++ + .../log4j/net/HardenedObjectInputStream.java | 93 +++++++++++++++++++++ + src/test/input/xml/socketAppenderForChainsaw.xml | 24 ++++++ + .../org/apache/log4j/net/SocketAppenderTest.java | 96 ++++++++++++++++++++++ + 5 files changed, 273 insertions(+), 4 deletions(-) + create mode 100644 src/main/java/org/apache/log4j/net/HardenedLoggingEventInputStream.java + create mode 100644 src/main/java/org/apache/log4j/net/HardenedObjectInputStream.java + create mode 100644 src/test/input/xml/socketAppenderForChainsaw.xml + create mode 100644 src/test/java/org/apache/log4j/net/SocketAppenderTest.java + +diff --git a/src/main/java/org/apache/log4j/chainsaw/LoggingReceiver.java b/src/main/java/org/apache/log4j/chainsaw/LoggingReceiver.java +index ca087ad..74ecc06 100644 +--- a/src/main/java/org/apache/log4j/chainsaw/LoggingReceiver.java ++++ b/src/main/java/org/apache/log4j/chainsaw/LoggingReceiver.java +@@ -18,11 +18,11 @@ package org.apache.log4j.chainsaw; + + import java.io.EOFException; + import java.io.IOException; +-import java.io.ObjectInputStream; + import java.net.ServerSocket; + import java.net.Socket; + import java.net.SocketException; + import org.apache.log4j.Logger; ++import org.apache.log4j.net.HardenedLoggingEventInputStream; + import org.apache.log4j.spi.LoggingEvent; + + /** +@@ -58,10 +58,10 @@ class LoggingReceiver extends Thread { + public void run() { + LOG.debug("Starting to get data"); + try { +- final ObjectInputStream ois = +- new ObjectInputStream(mClient.getInputStream()); ++ final HardenedLoggingEventInputStream hleis = ++ new HardenedLoggingEventInputStream(mClient.getInputStream()); + while (true) { +- final LoggingEvent event = (LoggingEvent) ois.readObject(); ++ final LoggingEvent event = (LoggingEvent) hleis.readObject(); + mModel.addEvent(new EventDetails(event)); + } + } catch (EOFException e) { +diff --git a/src/main/java/org/apache/log4j/net/HardenedLoggingEventInputStream.java b/src/main/java/org/apache/log4j/net/HardenedLoggingEventInputStream.java +new file mode 100644 +index 0000000..f0f6a20 +--- /dev/null ++++ b/src/main/java/org/apache/log4j/net/HardenedLoggingEventInputStream.java +@@ -0,0 +1,56 @@ ++/* ++ * 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.log4j.net; ++ ++import java.io.IOException; ++import java.io.InputStream; ++import java.util.ArrayList; ++import java.util.List; ++ ++import org.apache.log4j.Level; ++import org.apache.log4j.Priority; ++import org.apache.log4j.spi.LocationInfo; ++import org.apache.log4j.spi.LoggingEvent; ++import org.apache.log4j.spi.ThrowableInformation; ++ ++// === Copied from the logback project with permission == ++public class HardenedLoggingEventInputStream extends HardenedObjectInputStream { ++ ++ static final String ARRAY_PREFIX = "[L"; ++ ++ static public List getWhilelist() { ++ ++ List whitelist = new ArrayList(); ++ whitelist.add(LoggingEvent.class.getName()); ++ whitelist.add(Level.class.getName()); ++ whitelist.add(Priority.class.getName()); ++ whitelist.add(ThrowableInformation.class.getName()); ++ whitelist.add(LocationInfo.class.getName()); ++ ++ return whitelist; ++ } ++ ++ public HardenedLoggingEventInputStream(InputStream is) throws IOException { ++ super(is, getWhilelist()); ++ } ++ ++ public HardenedLoggingEventInputStream(InputStream is, List additionalAuthorizedClasses) ++ throws IOException { ++ this(is); ++ super.addToWhitelist(additionalAuthorizedClasses); ++ } ++} +diff --git a/src/main/java/org/apache/log4j/net/HardenedObjectInputStream.java b/src/main/java/org/apache/log4j/net/HardenedObjectInputStream.java +new file mode 100644 +index 0000000..c911572 +--- /dev/null ++++ b/src/main/java/org/apache/log4j/net/HardenedObjectInputStream.java +@@ -0,0 +1,93 @@ ++/* ++ * 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.log4j.net; ++ ++import java.io.IOException; ++import java.io.InputStream; ++import java.io.InvalidClassException; ++import java.io.ObjectInputStream; ++import java.io.ObjectStreamClass; ++import java.util.ArrayList; ++import java.util.List; ++ ++/** ++ * HardenedObjectInputStream restricts the set of classes that can be ++ * deserialized to a set of explicitly whitelisted classes. This prevents ++ * certain type of attacks from being successful. ++ * ++ *

++ * It is assumed that classes in the "java.lang" and "java.util" packages are ++ * always authorized. ++ *

++ * ++ * @author Ceki Gülcü ++ * @since 1.2.18 ++ * ++ * === Copied from the logback project with permission == ++ */ ++public class HardenedObjectInputStream extends ObjectInputStream { ++ ++ static final String ARRAY_CLASS_PREFIX = "[L"; ++ final List whitelistedClassNames; ++ final static String[] JAVA_PACKAGES = new String[] { "java.lang", "java.util", ARRAY_CLASS_PREFIX + "java.lang" }; ++ ++ public HardenedObjectInputStream(InputStream in, String[] whilelist) throws IOException { ++ super(in); ++ ++ this.whitelistedClassNames = new ArrayList(); ++ if (whilelist != null) { ++ for (int i = 0; i < whilelist.length; i++) { ++ this.whitelistedClassNames.add(whilelist[i]); ++ } ++ } ++ } ++ ++ public HardenedObjectInputStream(InputStream in, List whitelist) throws IOException { ++ super(in); ++ ++ this.whitelistedClassNames = new ArrayList(); ++ this.whitelistedClassNames.addAll(whitelist); ++ } ++ ++ @Override ++ protected Class resolveClass(ObjectStreamClass anObjectStreamClass) throws IOException, ClassNotFoundException { ++ ++ String incomingClassName = anObjectStreamClass.getName(); ++ ++ if (!isWhitelisted(incomingClassName)) { ++ throw new InvalidClassException("Unauthorized deserialization attempt", incomingClassName); ++ } ++ ++ return super.resolveClass(anObjectStreamClass); ++ } ++ ++ private boolean isWhitelisted(String incomingClassName) { ++ for (int i = 0; i < JAVA_PACKAGES.length; i++) { ++ if (incomingClassName.startsWith(JAVA_PACKAGES[i])) ++ return true; ++ } ++ for (String whiteListed : whitelistedClassNames) { ++ if (incomingClassName.equals(whiteListed)) ++ return true; ++ } ++ return false; ++ } ++ ++ protected void addToWhitelist(List additionalAuthorizedClasses) { ++ whitelistedClassNames.addAll(additionalAuthorizedClasses); ++ } ++} +\ No newline at end of file +diff --git a/src/test/input/xml/socketAppenderForChainsaw.xml b/src/test/input/xml/socketAppenderForChainsaw.xml +new file mode 100644 +index 0000000..b022ba5 +--- /dev/null ++++ b/src/test/input/xml/socketAppenderForChainsaw.xml +@@ -0,0 +1,24 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/src/test/java/org/apache/log4j/net/SocketAppenderTest.java b/src/test/java/org/apache/log4j/net/SocketAppenderTest.java +new file mode 100644 +index 0000000..6c4a390 +--- /dev/null ++++ b/src/test/java/org/apache/log4j/net/SocketAppenderTest.java +@@ -0,0 +1,96 @@ ++/* ++ * 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.log4j.net; ++ ++import static org.apache.log4j.TestContants.TEST_INPUT_PREFIX; ++import static org.junit.Assert.assertEquals; ++ ++import org.apache.log4j.AppenderSkeleton; ++import org.apache.log4j.Logger; ++import org.apache.log4j.spi.LoggingEvent; ++import org.apache.log4j.xml.DOMConfigurator; ++import org.junit.After; ++import org.junit.Before; ++import org.junit.Test; ++ ++public class SocketAppenderTest { ++ ++ /* JUnit's setUp and tearDown */ ++ ++ @Before ++ public void setUp() { ++ DOMConfigurator.configure(TEST_INPUT_PREFIX + "xml/SocketAppenderTestConfig.xml"); ++ // DOMConfigurator.configure(TEST_INPUT_PREFIX + ++ // "xml/socketAppenderForChainsaw.xml"); ++ ++ logger = Logger.getLogger(SocketAppenderTest.class); ++ secondary = (LastOnlyAppender) Logger.getLogger("org.apache.log4j.net.SocketAppenderTestDummy") ++ .getAppender("lastOnly"); ++ } ++ ++ @After ++ public void tearDown() { ++ } ++ ++ /* Tests */ ++ ++ @Test ++ public void testFallbackErrorHandlerWhenStarting() { ++ String msg = "testFallbackErrorHandlerWhenStarting"; ++ logger.debug(msg); ++ ++ // above debug log will fail and shoul be redirected to secondary appender ++ assertEquals("SocketAppender with FallbackErrorHandler", msg, secondary.getLastMessage()); ++ } ++ ++ /* Fields */ ++ ++ private static Logger logger; ++ private static LastOnlyAppender secondary; ++ ++ /* Inner classes */ ++ ++ /** ++ * Inner-class For debugging purposes only Saves last LoggerEvent ++ */ ++ static public class LastOnlyAppender extends AppenderSkeleton { ++ protected void append(LoggingEvent event) { ++ this.lastEvent = event; ++ } ++ ++ public boolean requiresLayout() { ++ return false; ++ } ++ ++ public void close() { ++ this.closed = true; ++ } ++ ++ /** ++ * @return last appended LoggingEvent's message ++ */ ++ public String getLastMessage() { ++ if (this.lastEvent != null) ++ return this.lastEvent.getMessage().toString(); ++ else ++ return ""; ++ } ++ ++ private LoggingEvent lastEvent; ++ }; ++ ++} +\ No newline at end of file diff --git a/log4j12.spec b/log4j12.spec index 91e8f59bcc41c0fe6c8cdd81e447e9f6c799dde0..ed78a13b88084ef0a8c1fe0f6c756ab65327d65b 100644 --- a/log4j12.spec +++ b/log4j12.spec @@ -1,6 +1,6 @@ Name: log4j12 Version: 1.2.17 -Release: 24 +Release: 25 Summary: A logging library for Java License: ASL 2.0 URL: http://logging.apache.org/log4j/1.2/ @@ -12,6 +12,10 @@ Patch0000: 0001-logfactor5-changed-userdir.patch Patch0001: 0009-Fix-tests.patch Patch0002: 0010-Fix-javadoc-link.patch Patch0003: 0001-Backport-fix-for-CVE-2017-5645.patch +Patch0004: CVE-2021-4104.patch +Patch0005: CVE-2022-23302.patch +Patch0006: CVE-2022-23305.patch +Patch0007: CVE-2022-23307.patch BuildRequires: maven-local mvn(ant-contrib:ant-contrib) mvn(javax.mail:mail) BuildRequires: mvn(junit:junit) mvn(org.apache.ant:ant-junit) @@ -19,7 +23,7 @@ BuildRequires: mvn(org.apache.felix:maven-bundle-plugin) BuildRequires: mvn(org.apache.geronimo.specs:geronimo-jms_1.1_spec) BuildRequires: mvn(org.apache.maven.plugins:maven-antrun-plugin) BuildRequires: mvn(org.apache.maven.plugins:maven-assembly-plugin) -BuildRequires: mvn(oro:oro) mvn(org.apache.ant:ant-nodeps) +BuildRequires: mvn(oro:oro) mvn(org.apache.ant:ant-nodeps) maven Obsoletes: log4j <= 0:1.2.17-14 @@ -80,7 +84,7 @@ sed -i '/TelnetAppenderTest/d' tests/src/java/org/apache/log4j/CoreTestSuite.jav %mvn_file log4j:log4j log4j %{name} %build -%mvn_build +%mvn_build -b %install %mvn_install -X @@ -119,5 +123,8 @@ fi %files help -f .mfiles-javadoc %changelog +* Tue Feb 08 2022 wangkai - 1.2.17-25 +- Fix cves + * Fri Dec 13 2019 openEuler Buildteam - 1.2.17-24 - Package init