diff options
author | Andrew Johnson | 2021-02-16 21:40:49 +0000 |
---|---|---|
committer | Lakshmi P Shanmugam | 2021-02-22 10:57:00 +0000 |
commit | 90661664f30d4e1225e4a68b179c6ee110cd7f75 (patch) | |
tree | e1a2bef2d757bd00cc195f5103b43108f7044f27 | |
parent | c01badb8037928186e05697b82c304e35c0dcae3 (diff) | |
download | eclipse.platform.ua-90661664f30d4e1225e4a68b179c6ee110cd7f75.tar.gz eclipse.platform.ua-90661664f30d4e1225e4a68b179c6ee110cd7f75.tar.xz eclipse.platform.ua-90661664f30d4e1225e4a68b179c6ee110cd7f75.zip |
569855: Fix for Eclipse live help.Y20210222-1000I20210222-1800
Use tokens
Change-Id: I09cee753dc24d55a2704b80ae13d392d233aac0d
Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=569855
Signed-off-by: Andrew Johnson <andrew_johnson@uk.ibm.com>
7 files changed, 118 insertions, 10 deletions
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 3a4716dcc..729a1b23d 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, 2020 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 @@ -16,6 +16,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.Platform; @@ -58,6 +59,7 @@ public final class BaseHelpSystem { private IBrowser browser; private IBrowser internalBrowser; private HelpDisplay helpDisplay = null; + private String liveHelpToken = null; private BaseHelpSystem() { super(); @@ -347,4 +349,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 2f282554f..db6b147e4 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, 2020 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 @@ -16,6 +16,7 @@ package org.eclipse.help.internal.base; 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; @@ -189,6 +190,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 6c98ded4b..cfce5cfd7 100644 --- a/org.eclipse.help.webapp/META-INF/MANIFEST.MF +++ b/org.eclipse.help.webapp/META-INF/MANIFEST.MF @@ -6,7 +6,7 @@ Bundle-Version: 3.10.200.qualifier Bundle-Activator: org.eclipse.help.internal.webapp.HelpWebappPlugin Bundle-Vendor: %providerName Bundle-Localization: plugin -Require-Bundle: org.eclipse.help.base;bundle-version="[4.0.0,5.0.0)", +Require-Bundle: org.eclipse.help.base;bundle-version="[4.3.200,5.0.0)", org.eclipse.core.runtime;bundle-version="[3.6.0,4.0.0)", org.eclipse.equinox.jsp.jasper.registry;bundle-version="1.0.100", org.eclipse.equinox.http.registry;bundle-version="1.0.200", 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 7233954e2..33c919254 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 @@ -14,10 +14,12 @@ <%@ page import="org.eclipse.help.internal.webapp.data.*" errorPage="/advanced/err.jsp" contentType="text/html; charset=UTF-8"%> <%@ page import="java.util.Scanner" %> <%@ page import="java.net.URL" %> +<%@ page import="java.util.UUID" %> <%@ page import="org.eclipse.core.runtime.Platform" %> +<%@ 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); @@ -37,6 +39,21 @@ </html> <% } 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$ + } + } + } // Experimental UI: see bug 501718 String experimentalUi = System.getProperty("org.eclipse.help.webapp.experimental.ui"); 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 61edeea9d..f9c1ad49f 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, 2020 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 @@ -48,6 +48,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); } /** * |