This is an automated email from the ASF dual-hosted git repository. kwin pushed a commit to branch maintenance-1.0.x in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-console.git
commit 12a418d8a53d6e067ddb8b8e88a5578e82f01724 Author: Konrad Windszus <[email protected]> AuthorDate: Tue Jan 7 14:10:02 2020 +0100 SLING-8966 escape all dynamic input --- .../impl/console/AbstractWebConsolePlugin.java | 80 ++++++++++++++++++++++ .../ConfigurationSerializerWebConsolePlugin.java | 55 +++------------ .../console/OsgiInstallerWebConsolePlugin.java | 72 +++++++++---------- 3 files changed, 121 insertions(+), 86 deletions(-) diff --git a/src/main/java/org/apache/sling/installer/core/impl/console/AbstractWebConsolePlugin.java b/src/main/java/org/apache/sling/installer/core/impl/console/AbstractWebConsolePlugin.java new file mode 100644 index 0000000..a9e8895 --- /dev/null +++ b/src/main/java/org/apache/sling/installer/core/impl/console/AbstractWebConsolePlugin.java @@ -0,0 +1,80 @@ +/* + * 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.sling.installer.core.impl.console; + +import java.net.URL; + +import javax.servlet.GenericServlet; + +@SuppressWarnings("serial") +abstract class AbstractWebConsolePlugin extends GenericServlet { + + /** + * + * @return the prefix under which resources are requested (must not start with "/", must end with "/") + */ + abstract String getRelativeResourcePrefix(); + + /** + * Method to retrieve static resources from this bundle. + */ + @SuppressWarnings("unused") + private URL getResource(final String path) { + if (path.startsWith("/" + getRelativeResourcePrefix())) { + // strip label + int index = path.indexOf('/', 1); + if (index <= 0) { + throw new IllegalStateException("The relativeResourcePrefix must contain at least one '/'"); + } + return this.getClass().getResource(path.substring(index)); + } + return null; + } + + /** + * Copied from org.apache.sling.api.request.ResponseUtil + * Escape XML text + * @param input The input text + * @return The escaped text + */ + protected String escapeXml(final String input) { + if (input == null) { + return null; + } + + final StringBuilder b = new StringBuilder(input.length()); + for(int i = 0;i < input.length(); i++) { + final char c = input.charAt(i); + if(c == '&') { + b.append("&"); + } else if(c == '<') { + b.append("<"); + } else if(c == '>') { + b.append(">"); + } else if(c == '"') { + b.append("""); + } else if(c == '\'') { + b.append("'"); + } else { + b.append(c); + } + } + return b.toString(); + } +} diff --git a/src/main/java/org/apache/sling/installer/core/impl/console/ConfigurationSerializerWebConsolePlugin.java b/src/main/java/org/apache/sling/installer/core/impl/console/ConfigurationSerializerWebConsolePlugin.java index d6d065f..b90e1cb 100644 --- a/src/main/java/org/apache/sling/installer/core/impl/console/ConfigurationSerializerWebConsolePlugin.java +++ b/src/main/java/org/apache/sling/installer/core/impl/console/ConfigurationSerializerWebConsolePlugin.java @@ -21,7 +21,6 @@ package org.apache.sling.installer.core.impl.console; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintWriter; -import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.Dictionary; import java.util.Enumeration; @@ -29,7 +28,6 @@ import java.util.HashSet; import java.util.Hashtable; import java.util.Set; -import javax.servlet.GenericServlet; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; @@ -52,10 +50,10 @@ import org.slf4j.LoggerFactory; "felix.webconsole.category=OSGi" }) @SuppressWarnings("serial") -public class ConfigurationSerializerWebConsolePlugin extends GenericServlet { +public class ConfigurationSerializerWebConsolePlugin extends AbstractWebConsolePlugin { public static final String LABEL = "osgi-installer-config-printer"; - private static final String RES_LOC = LABEL + "/res/ui"; + private static final String RES_LOC = LABEL + "/res/ui/"; private static final String PARAMETER_PID = "pid"; private static final String PARAMETER_FORMAT = "format"; @@ -87,17 +85,6 @@ public class ConfigurationSerializerWebConsolePlugin extends GenericServlet { @Reference ConfigurationAdmin configurationAdmin; - /** - * Method to retrieve static resources from this bundle. - */ - @SuppressWarnings("unused") - private URL getResource(final String path) { - if (path.startsWith("/" + RES_LOC)) { - return this.getClass().getResource(path.substring(LABEL.length()+1)); - } - return null; - } - @Override public void service(final ServletRequest request, final ServletResponse response) throws IOException { @@ -114,7 +101,7 @@ public class ConfigurationSerializerWebConsolePlugin extends GenericServlet { } final PrintWriter pw = response.getWriter(); - pw.println("<script type=\"text/javascript\" src=\"" + RES_LOC + "/clipboard.js\"></script>"); + pw.println("<script type=\"text/javascript\" src=\"" + RES_LOC + "clipboard.js\"></script>"); pw.print("<form method='get'>"); pw.println("<table class='content' cellpadding='0' cellspacing='0' width='100%'>"); @@ -191,37 +178,6 @@ public class ConfigurationSerializerWebConsolePlugin extends GenericServlet { pw.print("</form>"); } - /** - * Copied from org.apache.sling.api.request.ResponseUtil - * Escape XML text - * @param input The input text - * @return The escaped text - */ - private String escapeXml(final String input) { - if (input == null) { - return null; - } - - final StringBuilder b = new StringBuilder(input.length()); - for(int i = 0;i < input.length(); i++) { - final char c = input.charAt(i); - if(c == '&') { - b.append("&"); - } else if(c == '<') { - b.append("<"); - } else if(c == '>') { - b.append(">"); - } else if(c == '"') { - b.append("""); - } else if(c == '\'') { - b.append("'"); - } else { - b.append(c); - } - } - return b.toString(); - } - // copied from org.apache.sling.installer.factories.configuration.impl.ConfigUtil /** * Remove all ignored properties @@ -289,4 +245,9 @@ public class ConfigurationSerializerWebConsolePlugin extends GenericServlet { } } + @Override + String getRelativeResourcePrefix() { + return RES_LOC; + } + } diff --git a/src/main/java/org/apache/sling/installer/core/impl/console/OsgiInstallerWebConsolePlugin.java b/src/main/java/org/apache/sling/installer/core/impl/console/OsgiInstallerWebConsolePlugin.java index 2f4b17a..97bc12d 100644 --- a/src/main/java/org/apache/sling/installer/core/impl/console/OsgiInstallerWebConsolePlugin.java +++ b/src/main/java/org/apache/sling/installer/core/impl/console/OsgiInstallerWebConsolePlugin.java @@ -21,14 +21,12 @@ package org.apache.sling.installer.core.impl.console; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; -import java.net.URL; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Collection; import java.util.Date; import java.util.Iterator; -import javax.servlet.GenericServlet; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; @@ -55,13 +53,13 @@ import org.osgi.service.component.annotations.ReferencePolicyOption; "felix.webconsole.category=OSGi", "felix.webconsole.configprinter.modes=zip", "felix.webconsole.configprinter.modes=txt", - "felix.webconsole.css=" + OsgiInstallerWebConsolePlugin.RES_LOC + "/list.css" + "felix.webconsole.css=" + OsgiInstallerWebConsolePlugin.RES_LOC + "list.css" }) @SuppressWarnings("serial") -public class OsgiInstallerWebConsolePlugin extends GenericServlet { +public class OsgiInstallerWebConsolePlugin extends AbstractWebConsolePlugin { public static final String LABEL = "osgi-installer"; - protected static final String RES_LOC = LABEL + "/res/ui"; + protected static final String RES_LOC = LABEL + "/res/ui/"; @Reference(policyOption=ReferencePolicyOption.GREEDY) @@ -159,8 +157,8 @@ public class OsgiInstallerWebConsolePlugin extends GenericServlet { if ( rt != null ) { bufferedPw.println("</tbody></table>"); } - String anchor = "active-" + getType(toActivate); - pw.println("<li><a href='#" + anchor + "'>" + getType(toActivate) + "</a></li>"); + String anchor = "active-" + escapeXml(getType(toActivate)); + pw.println("<li><a href='#" + anchor + "'>" + escapeXml(getType(toActivate)) + "</a></li>"); bufferedPw.println("<div id='" + anchor + "' class='ui-widget-header ui-corner-top buttonGroup' style='height: 15px;'>"); bufferedPw.printf("<span style='float: left; margin-left: 1em;'>Active Resources - %s</span>", getType(toActivate)); bufferedPw.println("</div>"); @@ -169,11 +167,11 @@ public class OsgiInstallerWebConsolePlugin extends GenericServlet { rt = toActivate.getType(); } bufferedPw.printf("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>", - getEntityId(toActivate, group.getAlias()), - getInfo(toActivate), - getURL(toActivate), - toActivate.getState(), - getError(toActivate)); + escapeXml(getEntityId(toActivate, group.getAlias())), + escapeXml(getInfo(toActivate)), + escapeXml(getURL(toActivate)), + escapeXml(toActivate.getState().toString()), + escapeXml(getError(toActivate))); } if ( rt != null ) { bufferedPw.println("</tbody></table>"); @@ -195,8 +193,8 @@ public class OsgiInstallerWebConsolePlugin extends GenericServlet { if ( rt != null ) { bufferedPw.println("</tbody></table>"); } - String anchor = "processed-" + getType(first); - pw.println("<li><a href='#" + anchor + "'>" + getType(first) + "</a></li>"); + String anchor = "processed-" + escapeXml(getType(first)); + pw.println("<li><a href='#" + anchor + "'>" + escapeXml(getType(first)) + "</a></li>"); bufferedPw.println("<div id='" + anchor + "' class='ui-widget-header ui-corner-top buttonGroup' style='height: 15px;'>"); bufferedPw.printf("<span style='float: left; margin-left: 1em;'>Processed Resources - %s</span>", getType(first)); @@ -206,13 +204,13 @@ public class OsgiInstallerWebConsolePlugin extends GenericServlet { rt = first.getType(); } bufferedPw.print("<tr><td>"); - bufferedPw.print(getEntityId(first, group.getAlias())); + bufferedPw.print(escapeXml(getEntityId(first, group.getAlias()))); bufferedPw.print("</td><td>"); - bufferedPw.print(getInfo(first)); + bufferedPw.print(escapeXml(getInfo(first))); bufferedPw.print("</td><td>"); - bufferedPw.print(getURL(first)); + bufferedPw.print(escapeXml(getURL(first))); bufferedPw.print("</td><td>"); - bufferedPw.print(getState(first)); + bufferedPw.print(escapeXml(getState(first))); if ( first.getState() == ResourceState.INSTALLED ) { final long lastChange = first.getLastChange(); if ( lastChange > 0 ) { @@ -221,24 +219,24 @@ public class OsgiInstallerWebConsolePlugin extends GenericServlet { } } bufferedPw.print("</td><td>"); - bufferedPw.print(getError(first)); + bufferedPw.print(escapeXml(getError(first))); bufferedPw.print("</td></tr>"); if ( first.getAttribute(TaskResource.ATTR_INSTALL_EXCLUDED) != null ) { bufferedPw.printf("<tr><td></td><td colspan='2'>%s</td><td></td><td></td></tr>", - first.getAttribute(TaskResource.ATTR_INSTALL_EXCLUDED)); + escapeXml(first.getAttribute(TaskResource.ATTR_INSTALL_EXCLUDED).toString())); } if ( first.getAttribute(TaskResource.ATTR_INSTALL_INFO) != null ) { bufferedPw.printf("<tr><td></td><td colspan='2'>%s</td><td></td><td></td></tr>", - first.getAttribute(TaskResource.ATTR_INSTALL_INFO)); + escapeXml(first.getAttribute(TaskResource.ATTR_INSTALL_INFO).toString())); } while ( iter.hasNext() ) { final Resource resource = iter.next(); bufferedPw.printf("<tr><td></td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>", - getInfo(resource), - getURL(resource), - resource.getState(), - getError(resource)); + escapeXml(getInfo(resource)), + escapeXml(getURL(resource)), + escapeXml(resource.getState().toString()), + escapeXml(getError(resource))); } } } @@ -258,8 +256,8 @@ public class OsgiInstallerWebConsolePlugin extends GenericServlet { if ( rt != null ) { bufferedPw.println("</tbody></table>"); } - String anchor = "untransformed-" + getType(registeredResource); - pw.println("<li><a href='#" + anchor + "'>" + getType(registeredResource) + "</a></li>"); + String anchor = "untransformed-" + escapeXml(getType(registeredResource)); + pw.println("<li><a href='#" + anchor + "'>" + escapeXml(getType(registeredResource)) + "</a></li>"); bufferedPw.println("<div id='" + anchor + "' class='ui-widget-header ui-corner-top buttonGroup' style='height: 15px;'>"); bufferedPw.printf("<span style='float: left; margin-left: 1em;'>Untransformed Resources - %s</span>", getType(registeredResource)); @@ -270,8 +268,8 @@ public class OsgiInstallerWebConsolePlugin extends GenericServlet { rt = registeredResource.getType(); } bufferedPw.printf("<tr><td>%s</td><td>%s</td></tr>", - getInfo(registeredResource), - registeredResource.getURL()); + escapeXml(getInfo(registeredResource)), + escapeXml(registeredResource.getURL())); } if ( rt != null ) { bufferedPw.println("</tbody></table>"); @@ -364,15 +362,11 @@ public class OsgiInstallerWebConsolePlugin extends GenericServlet { registeredResource.getURL()); } } - - /** - * Method to retrieve static resources from this bundle. - */ - @SuppressWarnings("unused") - private URL getResource(final String path) { - if (path.startsWith("/" + RES_LOC)) { - return this.getClass().getResource(path.substring(LABEL.length()+1)); - } - return null; + + @Override + String getRelativeResourcePrefix() { + return RES_LOC; } + + }
