You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by sc...@apache.org on 2024/03/11 21:45:18 UTC
(tomcat) 01/03: Add checking for the age of the Tomcat version running and warn if it's getting old.
This is an automated email from the ASF dual-hosted git repository.
schultz pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 17becc33476edeca3092864a0882bbd8178264ba
Author: Christopher Schultz <ch...@christopherschultz.net>
AuthorDate: Mon Mar 11 17:38:01 2024 -0400
Add checking for the age of the Tomcat version running and warn if it's getting old.
---
.../catalina/security/LocalStrings.properties | 3 ++
.../apache/catalina/security/SecurityListener.java | 63 ++++++++++++++++++++++
java/org/apache/catalina/util/ServerInfo.java | 18 +++++++
webapps/docs/changelog.xml | 5 ++
webapps/docs/config/listeners.xml | 5 ++
5 files changed, 94 insertions(+)
diff --git a/java/org/apache/catalina/security/LocalStrings.properties b/java/org/apache/catalina/security/LocalStrings.properties
index 2af8b37d12..e356c44a27 100644
--- a/java/org/apache/catalina/security/LocalStrings.properties
+++ b/java/org/apache/catalina/security/LocalStrings.properties
@@ -18,6 +18,9 @@ SecurityListener.checkUmaskNone=No umask setting was found in system property [{
SecurityListener.checkUmaskParseFail=Failed to parse value [{0}] as a valid umask.
SecurityListener.checkUmaskSkip=Unable to determine umask. It appears Tomcat is running on Windows so skip the umask check.
SecurityListener.checkUserWarning=Start attempted while running as user [{0}]. Running Tomcat as this user has been blocked by the Lifecycle listener org.apache.catalina.security.SecurityListener (usually configured in CATALINA_BASE/conf/server.xml)
+SecurityListener.buildDateAgeUnreadable=Unable to read configured buildDateWarningAgeDays [{0}], using default of [{1}] days.
+SecurityListener.buildDateUnreadable=Server build date [{0}] is unreadable as an ISO-8601 date.
+SecurityListener.buildDateIsOld=This version of Tomcat was built more than {0} days ago. You should consider upgrading to the current version.
SecurityUtil.doAsPrivilege=An exception occurs when running the PrivilegedExceptionAction block.
diff --git a/java/org/apache/catalina/security/SecurityListener.java b/java/org/apache/catalina/security/SecurityListener.java
index 2371e30f7d..0fd20933b4 100644
--- a/java/org/apache/catalina/security/SecurityListener.java
+++ b/java/org/apache/catalina/security/SecurityListener.java
@@ -16,6 +16,10 @@
*/
package org.apache.catalina.security;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
@@ -24,6 +28,7 @@ import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Server;
+import org.apache.catalina.util.ServerInfo;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.buf.StringUtils;
@@ -42,11 +47,18 @@ public class SecurityListener implements LifecycleListener {
private static final String UMASK_FORMAT = "%04o";
+ private static final int DEFAULT_BUILD_DATE_WARNING_AGE_DAYS = 180;
+
/**
* The list of operating system users not permitted to run Tomcat.
*/
private final Set<String> checkedOsUsers = new HashSet<>();
+ /**
+ * The number of days this Tomcat build can go without warning upon startup.
+ */
+ private int buildDateWarningAgeDays = DEFAULT_BUILD_DATE_WARNING_AGE_DAYS;
+
/**
* The minimum umask that must be configured for the operating system user running Tomcat. The umask is handled as
* an octal.
@@ -126,6 +138,33 @@ public class SecurityListener implements LifecycleListener {
return String.format(UMASK_FORMAT, minimumUmask);
}
+ /**
+ * Sets the number of days that may pass between the build-date of this
+ * Tomcat instance before warnings are printed.
+ *
+ * @param ageDays The number of days a Tomcat build is allowed to age
+ * before logging warnings.
+ */
+ public void setBuildDateWarningAgeDays(String ageDays) {
+ try {
+ buildDateWarningAgeDays = Integer.parseInt(ageDays);
+ } catch (NumberFormatException nfe) {
+ // Just use the default and warn the user
+ log.warn(sm.getString("SecurityListener.buildDateAgeUnreadable",
+ ageDays, DEFAULT_BUILD_DATE_WARNING_AGE_DAYS));
+ }
+ }
+
+ /**
+ * Gets the number of days that may pass between the build-date of this
+ * Tomcat instance before warnings are printed.
+ *
+ * @return The number of days a Tomcat build is allowed to age
+ * before logging warnings.
+ */
+ public int getBuildDateWarningAgeDays() {
+ return buildDateWarningAgeDays;
+ }
/**
* Execute the security checks. Each check should be in a separate method.
@@ -133,6 +172,7 @@ public class SecurityListener implements LifecycleListener {
protected void doChecks() {
checkOsUser();
checkUmask();
+ checkServerBuildAge();
}
@@ -179,4 +219,27 @@ public class SecurityListener implements LifecycleListener {
getMinimumUmask()));
}
}
+
+ protected void checkServerBuildAge() {
+ String buildDateString = ServerInfo.getServerBuiltISO();
+
+ if (null == buildDateString || buildDateString.length() < 1 || !Character.isDigit(buildDateString.charAt(0))) {
+ log.warn(sm.getString("SecurityListener.buildDateUnreadable", buildDateString));
+ } else {
+ try {
+ Date buildDate = new SimpleDateFormat("yyyy-MM-dd").parse(buildDateString);
+
+ int allowedAgeDays = getBuildDateWarningAgeDays();
+
+ Calendar old = Calendar.getInstance();
+ old.add(Calendar.DATE, -allowedAgeDays); // Subtract X days from today
+
+ if(buildDate.before(old.getTime())) {
+ log.warn(sm.getString("SecurityListener.buildDateIsOld", allowedAgeDays));
+ }
+ } catch (ParseException pe) {
+ log.warn(sm.getString("SecurityListener.buildDateUnreadable", buildDateString));
+ }
+ }
+ }
}
diff --git a/java/org/apache/catalina/util/ServerInfo.java b/java/org/apache/catalina/util/ServerInfo.java
index 4f45b29663..5ef6c54fe3 100644
--- a/java/org/apache/catalina/util/ServerInfo.java
+++ b/java/org/apache/catalina/util/ServerInfo.java
@@ -45,6 +45,11 @@ public class ServerInfo {
*/
private static final String serverBuilt;
+ /**
+ * The server built String, in ISO-8604 date format.
+ */
+ private static final String serverBuiltIso;
+
/**
* The server's version number String.
*/
@@ -54,6 +59,7 @@ public class ServerInfo {
String info = null;
String built = null;
+ String builtIso = null;
String number = null;
Properties props = new Properties();
@@ -62,6 +68,7 @@ public class ServerInfo {
props.load(is);
info = props.getProperty("server.info");
built = props.getProperty("server.built");
+ builtIso = props.getProperty("server.built.iso");
number = props.getProperty("server.number");
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
@@ -72,12 +79,16 @@ public class ServerInfo {
if (built == null || built.equals("@VERSION_BUILT@")) {
built = "unknown";
}
+ if (builtIso == null || builtIso.equals("@VERSION_BUILT_ISO@")) {
+ builtIso = "unknown";
+ }
if (number == null || number.equals("@VERSION_NUMBER@")) {
number = "10.1.x";
}
serverInfo = info;
serverBuilt = built;
+ serverBuiltIso = builtIso;
serverNumber = number;
}
@@ -99,6 +110,13 @@ public class ServerInfo {
return serverBuilt;
}
+ /**
+ * @return the server built date for this version of Tomcat in ISO-8601 date format.
+ */
+ public static String getServerBuiltISO() {
+ return serverBuiltIso;
+ }
+
/**
* @return the server's version number.
*/
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index afa4992dd5..c1d792269c 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -156,6 +156,11 @@
error status code to the client when a permit cannot be acquired from
the semaphore. (remm)
</update>
+ <add>
+ Add checking of the "age" of the running Tomcat instance since its
+ build-date to the SecurityListener, and log a warning if the server
+ is old. (schultz)
+ </add>
</changelog>
</subsection>
<subsection name="Coyote">
diff --git a/webapps/docs/config/listeners.xml b/webapps/docs/config/listeners.xml
index a34b62d515..101780e79b 100644
--- a/webapps/docs/config/listeners.xml
+++ b/webapps/docs/config/listeners.xml
@@ -355,6 +355,11 @@
is not performed on Windows platforms.</p>
</attribute>
+ <attribute name="buildDateWarningAgeDays" required="false">
+ <p>The maximim number of days between the build-date of this instance
+ of Tomcat and its startup date can be before warnings will be logged.
+ If not specified, the default value of <b>180</b> is used.</p>
+ </attribute>
</attributes>
</subsection>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org