This is an automated email from the ASF dual-hosted git repository. solomax pushed a commit to branch csp in repository https://gitbox.apache.org/repos/asf/openmeetings.git
commit f943a896362d59ca11be3c7f85ce5293f6e760fd Author: Maxim Solodovnik <[email protected]> AuthorDate: Wed Jan 22 23:09:15 2020 +0700 Initial work on CSP --- .../apache/openmeetings/web/app/Application.java | 46 ++++++++++++++++------ .../apache/openmeetings/web/common/Captcha.html | 4 +- .../openmeetings/web/pages/AccessDeniedPage.html | 6 +-- .../apache/openmeetings/web/pages/BasePage.html | 37 +---------------- .../apache/openmeetings/web/pages/BasePage.java | 10 ++++- .../web/pages/auth/ForgetPasswordDialog.html | 2 +- .../web/pages/auth/RegisterDialog.html | 2 +- .../openmeetings/web/pages/auth/SignInPage.html | 15 ------- .../org/apache/openmeetings/web/pages/loader.css | 32 +++++++++++++++ .../src/main/webapp/css/raw-general.css | 24 +++++++++++ pom.xml | 4 +- 11 files changed, 108 insertions(+), 74 deletions(-) diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java index 2db7503..402a675 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java @@ -21,10 +21,8 @@ package org.apache.openmeetings.web.app; import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_EXT_PROCESS_TTL; import static org.apache.openmeetings.util.OpenmeetingsVariables.getApplicationName; import static org.apache.openmeetings.util.OpenmeetingsVariables.getBaseUrl; -import static org.apache.openmeetings.util.OpenmeetingsVariables.getContentSecurityPolicy; import static org.apache.openmeetings.util.OpenmeetingsVariables.getExtProcessTtl; import static org.apache.openmeetings.util.OpenmeetingsVariables.getWicketApplicationName; -import static org.apache.openmeetings.util.OpenmeetingsVariables.getxFrameOptions; import static org.apache.openmeetings.util.OpenmeetingsVariables.isInitComplete; import static org.apache.openmeetings.util.OpenmeetingsVariables.setExtProcessTtl; import static org.apache.openmeetings.util.OpenmeetingsVariables.setInitComplete; @@ -36,6 +34,8 @@ import static org.wicketstuff.dashboard.DashboardContextInitializer.DASHBOARD_CO import java.io.File; import java.net.UnknownHostException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; @@ -102,6 +102,7 @@ import org.apache.wicket.ThreadContext; import org.apache.wicket.WicketRuntimeException; import org.apache.wicket.authroles.authentication.AbstractAuthenticatedWebSession; import org.apache.wicket.authroles.authentication.AuthenticatedWebApplication; +import org.apache.wicket.core.random.ISecureRandomSupplier; import org.apache.wicket.core.request.handler.BookmarkableListenerRequestHandler; import org.apache.wicket.core.request.handler.ListenerRequestHandler; import org.apache.wicket.core.request.mapper.MountedMapper; @@ -109,7 +110,6 @@ import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.pageStore.IPageStore; import org.apache.wicket.pageStore.SerializingPageStore; import org.apache.wicket.protocol.ws.WebSocketAwareCsrfPreventionRequestCycleListener; -import org.apache.wicket.protocol.ws.api.WebSocketResponse; import org.apache.wicket.request.IRequestHandler; import org.apache.wicket.request.Response; import org.apache.wicket.request.Url; @@ -235,21 +235,41 @@ public class Application extends AuthenticatedWebApplication implements IApplica //chain of Resource Loaders, if not found it will search in Wicket's internal //Resource Loader for a the property key getResourceSettings().getStringResourceLoaders().add(0, new LabelResourceLoader()); + getSecuritySettings().setRandomSupplier(new ISecureRandomSupplier() { + private SecureRandom rnd = null; + + { + try { + rnd = SecureRandom.getInstance("SHA1PRNG"); + } catch (NoSuchAlgorithmException e) { + log.error("Failed to init secure random {}", e); + } + } + + @Override + public SecureRandom getRandom() { + return rnd; + } + }); + getCsp().blocking().strict(); getRequestCycleListeners().add(new WebSocketAwareCsrfPreventionRequestCycleListener() { @Override public void onEndRequest(RequestCycle cycle) { Response resp = cycle.getResponse(); - if (resp instanceof WebResponse && !(resp instanceof WebSocketResponse)) { + if (resp instanceof WebResponse) { WebResponse wresp = (WebResponse)resp; - wresp.setHeader("X-XSS-Protection", "1; mode=block"); - wresp.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload"); - wresp.setHeader("X-Content-Type-Options", "nosniff"); - Url reqUrl = cycle.getRequest().getUrl(); - wresp.setHeader("Content-Security-Policy" - , String.format("%s; connect-src 'self' %s; frame-src %s;" - , getContentSecurityPolicy(), getWsUrl(reqUrl) - , getxFrameOptions() - )); + if (wresp.isHeaderSupported()) { + wresp.setHeader("X-XSS-Protection", "1; mode=block"); + wresp.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload"); + wresp.setHeader("X-Content-Type-Options", "nosniff"); + /*Url reqUrl = cycle.getRequest().getUrl(); + wresp.setHeader("Content-Security-Policy" + , String.format("%s; connect-src 'self' %s; frame-src %s;" + , getContentSecurityPolicy(), getWsUrl(reqUrl) + , getxFrameOptions() + )); + */ + } } } }); diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/Captcha.html b/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/Captcha.html index f4b8d96..d83bf40 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/Captcha.html +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/Captcha.html @@ -21,8 +21,8 @@ <!DOCTYPE html> <html xmlns:wicket="http://wicket.apache.org"> <wicket:panel> - <input type="text" wicket:id="captchaText" wicket:message="placeholder:captcha.text,title:captcha.text" style="margin-bottom: 5px;"/><br/> - <img wicket:id="captcha" style="vertical-align: bottom;"/> + <input type="text" wicket:id="captchaText" wicket:message="placeholder:captcha.text,title:captcha.text" class="captcha-text"/><br/> + <img wicket:id="captcha" class="captcha-img"/> <span wicket:id="refresh" wicket:message="alt:lbl.refresh,title:lbl.refresh"><wicket:message key="lbl.refresh"/></span> </wicket:panel> </html> diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/AccessDeniedPage.html b/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/AccessDeniedPage.html index f8b095e..3fb13ca 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/AccessDeniedPage.html +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/AccessDeniedPage.html @@ -20,12 +20,12 @@ <!DOCTYPE html> <html xmlns:wicket="http://wicket.apache.org" wicket:id="html"> <wicket:extend> - <div class="ui-widget ui-corner-all ui-widget-shadow" style="margin: 4em;"> - <div class="ui-widget-content ui-corner-all ui-state-error" style="padding: 2em;"> + <div class="ui-widget ui-corner-all ui-widget-shadow access-denied outer"> + <div class="ui-widget-content ui-corner-all ui-state-error inner"> <div> <h2><wicket:message key="access.denied.header"/></h2> </div> - <div style="text-align: center;"> + <div class="centered"> <form wicket:id="form"> <button class="ui-state-error" wicket:id="home"><wicket:message key="124"/></button> <button class="ui-state-error" wicket:id="logout"><wicket:message key="310"/></button> diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/BasePage.html b/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/BasePage.html index 130684a..650c1fb 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/BasePage.html +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/BasePage.html @@ -23,47 +23,12 @@ <head> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/> <link rel="shortcut icon" href="public/favicon.png" type="image/png"/> - <style type="text/css"> - .sk-chasing-dots { - margin: 20% auto; - width: 80px; - height: 80px; - position: relative; - text-align: center; - -webkit-animation: sk-chasingDotsRotate 2s infinite linear; - animation: sk-chasingDotsRotate 2s infinite linear; - } - .sk-chasing-dots .sk-child { - width: 40%; - height: 40%; - display: inline-block; - position: absolute; - top: 0; - background-color: #333; - border-radius: 100%; - -webkit-animation: sk-chasingDotsBounce 2s infinite ease-in-out; - animation: sk-chasingDotsBounce 2s infinite ease-in-out; - } - .sk-chasing-dots .sk-dot2 { - top: auto; - bottom: 0; - -webkit-animation-delay: -1s; - animation-delay: -1s; - } - @keyframes sk-chasingDotsRotate { - 100% { transform: rotate(360deg); } - } - @keyframes sk-chasingDotsBounce { - 0%, 100% { transform: scale(0); } - 50% { transform: scale(1); } - } - </style> <wicket:header-items/> <title wicket:id="pageTitle">[title]</title> <link rel="stylesheet" type="text/css" href="css/custom.css"/> </head> <body> - <div wicket:id="main-loader" style="height: 100%;" class="ui-widget-header"> + <div wicket:id="main-loader" class="main-loader ui-widget-header"> <div class="sk-chasing-dots"> <div class="sk-child sk-dot1"></div> <div class="sk-child sk-dot2"></div> diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/BasePage.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/BasePage.java index 971c6a7..40236b7 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/BasePage.java +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/BasePage.java @@ -43,6 +43,7 @@ import org.apache.wicket.markup.html.TransparentWebMarkupContainer; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.request.IRequestParameters; +import org.apache.wicket.request.resource.CssResourceReference; import org.apache.wicket.request.resource.JavaScriptResourceReference; import org.apache.wicket.util.string.StringValue; import org.apache.wicket.util.string.Strings; @@ -54,7 +55,14 @@ public abstract class BasePage extends AsyncUrlFragmentAwarePage { public static final String ALIGN_RIGHT = "align-right "; private final Map<String, String> options; private final HeaderPanel header; - private final WebMarkupContainer loader = new WebMarkupContainer("main-loader"); + private final WebMarkupContainer loader = new WebMarkupContainer("main-loader") { + private static final long serialVersionUID = 1L; + + @Override + public void renderHead(IHeaderResponse response) { + response.render(CssHeaderItem.forReference(new CssResourceReference(BasePage.class, "loader.css"))); + } + }; public BasePage() { if (isInitComplete()) { diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/auth/ForgetPasswordDialog.html b/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/auth/ForgetPasswordDialog.html index 19266a2..3f5411d 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/auth/ForgetPasswordDialog.html +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/auth/ForgetPasswordDialog.html @@ -39,7 +39,7 @@ </tr> <tr> <td colspan="2"> - <div wicket:id="captcha" style="text-align: center;"></div> + <div wicket:id="captcha" class="centered"></div> </td> </tr> </table> diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/auth/RegisterDialog.html b/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/auth/RegisterDialog.html index 641feea..dafe6c8 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/auth/RegisterDialog.html +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/auth/RegisterDialog.html @@ -37,7 +37,7 @@ </tr> <tr> <td colspan="2"> - <div wicket:id="captcha" style="text-align: center;"></div> + <div wicket:id="captcha" class="centered"></div> </td> </tr> </table> diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/auth/SignInPage.html b/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/auth/SignInPage.html index b8522e4..55174ff 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/auth/SignInPage.html +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/auth/SignInPage.html @@ -20,22 +20,7 @@ --> <!DOCTYPE html> <html xmlns:wicket="http://wicket.apache.org"> -<wicket:head> - <style> - input:not([type='checkbox']):not([type='radio']), select { - width: 170px; - } - td.desc { - width: 200px; - } - </style> -</wicket:head> <wicket:extend> - <script type="text/javascript"> - $(function(){ - $('#area').val(location.hash); - }); - </script> <div wicket:id="signin"></div> <div wicket:id="register"></div> <div wicket:id="forget"></div> diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/loader.css b/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/loader.css new file mode 100644 index 0000000..47ad920 --- /dev/null +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/loader.css @@ -0,0 +1,32 @@ +/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */ +.sk-chasing-dots { + margin: 20% auto; + width: 80px; + height: 80px; + position: relative; + text-align: center; + animation: sk-chasingDotsRotate 2s infinite linear; +} +.sk-chasing-dots .sk-child { + width: 40%; + height: 40%; + display: inline-block; + position: absolute; + top: 0; + background-color: #333; + border-radius: 100%; + animation: sk-chasingDotsBounce 2s infinite ease-in-out; +} +.sk-chasing-dots .sk-dot2 { + top: auto; + bottom: 0; + -webkit-animation-delay: -1s; + animation-delay: -1s; +} +@keyframes sk-chasingDotsRotate { + 100% { transform: rotate(360deg); } +} +@keyframes sk-chasingDotsBounce { + 0%, 100% { transform: scale(0); } + 50% { transform: scale(1); } +} diff --git a/openmeetings-web/src/main/webapp/css/raw-general.css b/openmeetings-web/src/main/webapp/css/raw-general.css index 17aad56..51292ff 100644 --- a/openmeetings-web/src/main/webapp/css/raw-general.css +++ b/openmeetings-web/src/main/webapp/css/raw-general.css @@ -5,6 +5,9 @@ html, body { font-family: Arial, Helvetica, sans-serif; overflow-y: hidden; } +.main-loader { + height: 100%; +} .main-container { height: calc(100% - var(--header-height)); } @@ -18,6 +21,12 @@ html, body { box-sizing: content-box; /* IE */ box-sizing: initial; /*reset bootstrap box sizing*/ } +.signin input:not([type='checkbox']):not([type='radio']), .signin select { + width: 170px; +} +.signin td.desc { + width: 200px; +} .signin .oauth-section { border-left: 2px dotted; padding-left: 5px; @@ -141,6 +150,9 @@ html, body { display: inline; float: none; } +.centered { + text-align: center; +} .goto, .goto :link, .goto :hover { font-size: 14px; line-height: 14px; @@ -726,3 +738,15 @@ form .input { .om-tbl .om-tbl-row .om-tbl-cell { display: table-cell; } +.access-denied.outer { + margin: 4em; +} +.access-denied.outer .inner { + padding: 2em; +} +.captcha-text { + margin-bottom: 5px; +} +.captcha-img { + vertical-align: bottom; +} diff --git a/pom.xml b/pom.xml index 95b5d61..7b1b35e 100644 --- a/pom.xml +++ b/pom.xml @@ -74,8 +74,8 @@ <forbiddenapis.version>2.7</forbiddenapis.version> <!-- dependency versions --> <junit.version>5.5.2</junit.version> - <wicket.version>9.0.0-M4</wicket.version> - <wicketju.version>9.0.0-M4</wicketju.version> + <wicket.version>9.0.0-M5-SNAPSHOT</wicket.version> + <wicketju.version>9.0.0-SNAPSHOT</wicketju.version> <wickets.version>9.0.0-M4</wickets.version> <red5-client.version>1.2.3</red5-client.version> <spring.version>5.2.3.RELEASE</spring.version>
