diff options
author | Andrew Johnson | 2021-03-15 15:23:01 +0000 |
---|---|---|
committer | Niraj Modi | 2021-03-16 11:47:53 +0000 |
commit | 213812355860e3732e1b28e620df31db8ff160aa (patch) | |
tree | 18c6e73a4008b6ae03a739e59ce95f6b5f0f73a3 | |
parent | f64d27a987cc424dc4330451fc6930899814b050 (diff) | |
download | eclipse.platform.ua-213812355860e3732e1b28e620df31db8ff160aa.tar.gz eclipse.platform.ua-213812355860e3732e1b28e620df31db8ff160aa.tar.xz eclipse.platform.ua-213812355860e3732e1b28e620df31db8ff160aa.zip |
569855: Fix for Eclipse live help.
- Use tokens
- Backport to R4_15_maintenance branch
Change-Id: I09cee753dc24d55a2704b80ae13d392d233aac0d
Signed-off-by: Andrew Johnson <andrew_johnson@uk.ibm.com>
Also-by: Niraj Modi <niraj.modi@in.ibm.com>
10 files changed, 123 insertions, 14 deletions
diff --git a/org.eclipse.help.base/META-INF/MANIFEST.MF b/org.eclipse.help.base/META-INF/MANIFEST.MF index fd1af134e..f5ec7a35e 100644 --- a/org.eclipse.help.base/META-INF/MANIFEST.MF +++ b/org.eclipse.help.base/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %help_base_plugin_name Bundle-SymbolicName: org.eclipse.help.base; singleton:=true -Bundle-Version: 4.2.901.qualifier +Bundle-Version: 4.2.902.qualifier Bundle-Activator: org.eclipse.help.internal.base.HelpBasePlugin Bundle-Vendor: %providerName Bundle-Localization: plugin diff --git a/org.eclipse.help.base/pom.xml b/org.eclipse.help.base/pom.xml index 212fed308..8c59e239c 100644 --- a/org.eclipse.help.base/pom.xml +++ b/org.eclipse.help.base/pom.xml @@ -18,7 +18,7 @@ </parent> <groupId>org.eclipse.help</groupId> <artifactId>org.eclipse.help.base</artifactId> - <version>4.2.901-SNAPSHOT</version> + <version>4.2.902-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> <properties> <defaultSigning-excludeInnerJars>true</defaultSigning-excludeInnerJars> diff --git a/org.eclipse.help.base/src/org/eclipse/help/internal/base/BaseHelpSystem.java b/org.eclipse.help.base/src/org/eclipse/help/internal/base/BaseHelpSystem.java index 192129a6c..087ba77f4 100644 --- a/org.eclipse.help.base/src/org/eclipse/help/internal/base/BaseHelpSystem.java +++ b/org.eclipse.help.base/src/org/eclipse/help/internal/base/BaseHelpSystem.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corporation and others. + * Copyright (c) 2000, 2021 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -15,6 +15,7 @@ package org.eclipse.help.internal.base; import java.net.MalformedURLException; import java.net.URL; + import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProduct; import org.eclipse.core.runtime.IStatus; @@ -59,6 +60,7 @@ public final class BaseHelpSystem { private IBrowser browser; private IBrowser internalBrowser; private HelpDisplay helpDisplay = null; + private String liveHelpToken = null; private BaseHelpSystem() { super(); @@ -350,4 +352,29 @@ public final class BaseHelpSystem { } } + /** + * Check supplied token against stored token. Clears the stored token if + * successful. + * + * @param helpSessionToken + * @return true if match successful + */ + public boolean matchOnceLiveHelpToken(String helpSessionToken) { + /* + * @FIXME - should we use a constant time comparison, and store/compare a + * cryptographic hash? + */ + if (liveHelpToken != null && liveHelpToken.equals(helpSessionToken)) { + // Enforce one-time use. + liveHelpToken = null; + return true; + } else { + return false; + } + } + + public void setLiveHelpToken(String helpSessionToken) { + liveHelpToken = helpSessionToken; + } + } diff --git a/org.eclipse.help.base/src/org/eclipse/help/internal/base/HelpDisplay.java b/org.eclipse.help.base/src/org/eclipse/help/internal/base/HelpDisplay.java index 3bf0fdca2..ff690ea24 100644 --- a/org.eclipse.help.base/src/org/eclipse/help/internal/base/HelpDisplay.java +++ b/org.eclipse.help.base/src/org/eclipse/help/internal/base/HelpDisplay.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2021 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -15,6 +15,8 @@ package org.eclipse.help.internal.base; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.UUID; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; @@ -196,6 +198,12 @@ public class HelpDisplay { String topic = helpURL.substring("topic=".length()); //$NON-NLS-1$ helpURL = getHelpDisplay().getHelpForTopic( topic, WebappManager.getHost(), WebappManager.getPort()); } + String basehelp = getBaseURL(); + if (BaseHelpSystem.getMode() != BaseHelpSystem.MODE_INFOCENTER && helpURL.startsWith(basehelp)) { + String sessid = UUID.randomUUID().toString(); + BaseHelpSystem.getInstance().setLiveHelpToken(sessid); + helpURL += (helpURL.indexOf('?') < 0 ? '?' : '&') + "token=" + sessid; //$NON-NLS-1$ + } BaseHelpSystem.getHelpBrowser(forceExternal) .displayURL(helpURL); diff --git a/org.eclipse.help.webapp/META-INF/MANIFEST.MF b/org.eclipse.help.webapp/META-INF/MANIFEST.MF index 333059ada..18e8f96b5 100644 --- a/org.eclipse.help.webapp/META-INF/MANIFEST.MF +++ b/org.eclipse.help.webapp/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %help_webapp_plugin_name Bundle-SymbolicName: org.eclipse.help.webapp;singleton:=true -Bundle-Version: 3.9.801.qualifier +Bundle-Version: 3.9.802.qualifier Bundle-Activator: org.eclipse.help.internal.webapp.HelpWebappPlugin Bundle-Vendor: %providerName Bundle-Localization: plugin diff --git a/org.eclipse.help.webapp/advanced/livehelp_js.jsp b/org.eclipse.help.webapp/advanced/livehelp_js.jsp index 23362f89e..6d04945d6 100644 --- a/org.eclipse.help.webapp/advanced/livehelp_js.jsp +++ b/org.eclipse.help.webapp/advanced/livehelp_js.jsp @@ -1,5 +1,5 @@ <%-- - Copyright (c) 2000, 2018 IBM Corporation and others. + Copyright (c) 2000, 2021 IBM Corporation and others. This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 @@ -47,7 +47,15 @@ function liveActionInternal(topHelpWindow, pluginId, className, argument) url=url.substring(0, i+1); var encodedArg=encodeURIComponent(argument); url=url+"livehelp/?pluginID="+pluginId+"&class="+className+"&arg="+encodedArg+"&nocaching="+Math.random(); - + <% + Object token = request.getSession().getAttribute("LSESSION"); //$NON-NLS-1$ + // Validate token to protect against XSS + if (token instanceof String && ((String)token).matches("[a-z0-9-]{36}")) {//$NON-NLS-1$) { + %> + url=url+"&token=<%=token%>"; + <% + } + %> // we need to find the toolbar frame. // to do: cleanup this, including the location of the hidden livehelp frame. var toolbarFrame = topHelpWindow.HelpFrame.ContentFrame.ContentToolbarFrame; diff --git a/org.eclipse.help.webapp/index.jsp b/org.eclipse.help.webapp/index.jsp index 6d6f47443..cd2757f6f 100644 --- a/org.eclipse.help.webapp/index.jsp +++ b/org.eclipse.help.webapp/index.jsp @@ -1,5 +1,5 @@ <%-- - Copyright (c) 2000, 2011 IBM Corporation and others. + Copyright (c) 2000, 2021 IBM Corporation and others. This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 @@ -12,9 +12,11 @@ IBM Corporation - initial API and implementation --%> <%@ page import="org.eclipse.help.internal.webapp.data.*" errorPage="/advanced/err.jsp" contentType="text/html; charset=UTF-8"%> +<%@ page import="java.util.UUID" %> +<%@ page import="org.eclipse.help.internal.base.BaseHelpSystem" %> <% request.setCharacterEncoding("UTF-8"); - ServerState.webappStarted(application,request, response); + ServerState.webappStarted(application,request, response); // Read the scope parameter RequestScope.setScopeFromRequest(request, response); LayoutData data = new LayoutData(application,request, response); @@ -33,7 +35,22 @@ </body> </html> <% - }else { + } else { + // For live help + String token = request.getParameter("token"); //$NON-NLS-1$ + if (token != null && token.matches("[a-z0-9-]{36}")) { //$NON-NLS-1$ + if (BaseHelpSystem.getInstance().matchOnceLiveHelpToken(token)) { + // Only one session can grab this + if (request.getSession().getAttribute("XSESSION") == null) { //$NON-NLS-1$ + String token2 = UUID.randomUUID().toString(); + request.getSession().setAttribute("XSESSION", token2); //$NON-NLS-1$ + int port = request.getLocalPort(); + response.addHeader("Set-Cookie", "XSESSION-" + port + "=" + token2 + "; HttpOnly; SameSite=Strict"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + String token3 = UUID.randomUUID().toString(); + request.getSession().setAttribute("LSESSION", token3); //$NON-NLS-1$ + } + } + } request.getRequestDispatcher("/advanced/index.jsp" + data.getQuery()).forward(request, response); } %> diff --git a/org.eclipse.help.webapp/pom.xml b/org.eclipse.help.webapp/pom.xml index eb0d7cf80..c08449836 100644 --- a/org.eclipse.help.webapp/pom.xml +++ b/org.eclipse.help.webapp/pom.xml @@ -18,7 +18,7 @@ </parent> <groupId>org.eclipse.help</groupId> <artifactId>org.eclipse.help.webapp</artifactId> - <version>3.9.801-SNAPSHOT</version> + <version>3.9.802-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> <build> <plugins> diff --git a/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/data/LayoutData.java b/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/data/LayoutData.java index e66c37eae..9214487a7 100644 --- a/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/data/LayoutData.java +++ b/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/data/LayoutData.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2021 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -46,6 +46,11 @@ public class LayoutData extends RequestData { // initialize the query string String qs = request.getQueryString(); + // Remove any live help token + if (qs != null) { + qs = qs.replaceFirst("^token=[a-z0-9-]{36}", ""); //$NON-NLS-1$ //$NON-NLS-2$ + qs = qs.replaceFirst("&token=[a-z0-9-]{36}", ""); //$NON-NLS-1$ //$NON-NLS-2$ + } if (qs != null && qs.length() > 0) query = "?" + qs; //$NON-NLS-1$ } diff --git a/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/servlet/LiveHelpServlet.java b/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/servlet/LiveHelpServlet.java index ded00b1c1..a2959a6a8 100644 --- a/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/servlet/LiveHelpServlet.java +++ b/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/servlet/LiveHelpServlet.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2021 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -14,8 +14,8 @@ package org.eclipse.help.internal.webapp.servlet; import java.io.IOException; - import javax.servlet.ServletException; +import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -51,6 +51,45 @@ public class LiveHelpServlet extends HttpServlet { return; } req.setCharacterEncoding("UTF-8"); //$NON-NLS-1$ + String sessionid = req.getSession().getId(); + Cookie cookies[] = req.getCookies(); + boolean jsessOK = false; + boolean xsessOK = false; + boolean lsessOK = false; + // Unique session ID per help server + int port = req.getLocalPort(); + String xsessname = "XSESSION-" + port; //$NON-NLS-1$ + if (cookies != null) { + for (Cookie cookie : cookies) { + if (cookie.getName().equals("JSESSIONID")) {//$NON-NLS-1$ + if (sessionid.length() >= 30 && + cookie.getValue().startsWith(sessionid)) { + jsessOK = true; + } + } + if (cookie.getName().equals(xsessname)) { + if (cookie.getValue().equals(req.getSession().getAttribute("XSESSION"))) { //$NON-NLS-1$ + xsessOK = true; + } + } + } + } + String token = req.getParameter("token"); //$NON-NLS-1$ + if (token != null && token.equals(req.getSession().getAttribute("LSESSION"))) { //$NON-NLS-1$ + lsessOK = true; + } + if (!jsessOK) { + resp.sendError(HttpServletResponse.SC_FORBIDDEN, "JSESSIONID"); //$NON-NLS-1$ + return; + } + if (!lsessOK) { + resp.sendError(HttpServletResponse.SC_FORBIDDEN, "token"); //$NON-NLS-1$ + return; + } + if (!xsessOK) { + resp.sendError(HttpServletResponse.SC_FORBIDDEN, xsessname); + return; + } String pluginID = req.getParameter("pluginID"); //$NON-NLS-1$ if (pluginID == null) return; @@ -59,6 +98,11 @@ public class LiveHelpServlet extends HttpServlet { return; String arg = req.getParameter("arg"); //$NON-NLS-1$ BaseHelpSystem.runLiveHelp(pluginID, className, arg); + /* + * @FIXME Should runLiveHelp return an error if the plugin/class is wrong + * so a SC_BAD_REQUEST can be returned? Or does this reveal too much? + */ + resp.setStatus(HttpServletResponse.SC_ACCEPTED); } /** * |