Merge branch 'roller-5.2.x'
# Conflicts:
# app/pom.xml
# app/src/main/resources/struts.xml
# assembly-release/pom.xml
# assembly-release/sign-release.sh
# it-selenium/pom.xml
# it-selenium/src/test/resources/roller-jettyrun.properties
# pom.xml
diff --git a/app/src/main/java/org/apache/roller/weblogger/ui/core/RollerContext.java b/app/src/main/java/org/apache/roller/weblogger/ui/core/RollerContext.java
index ec0d0c8..b4517a5 100644
--- a/app/src/main/java/org/apache/roller/weblogger/ui/core/RollerContext.java
+++ b/app/src/main/java/org/apache/roller/weblogger/ui/core/RollerContext.java
@@ -282,31 +282,6 @@
(LoginUrlAuthenticationEntryPoint) ctx.getBean("_formLoginEntryPoint");
entryPoint.setForceHttps(true);
}
-
- /*
- if (WebloggerConfig.getBooleanProperty("schemeenforcement.enabled")) {
-
- ChannelProcessingFilter procfilter =
- (ChannelProcessingFilter)ctx.getBean("channelProcessingFilter");
- ConfigAttributeDefinition secureDef = new ConfigAttributeDefinition();
- secureDef.addConfigAttribute(new SecurityConfig("REQUIRES_SECURE_CHANNEL"));
- ConfigAttributeDefinition insecureDef = new ConfigAttributeDefinition();
- insecureDef.addConfigAttribute(new SecurityConfig("REQUIRES_INSECURE_CHANNEL"));
- PathBasedFilterInvocationDefinitionMap defmap =
- (PathBasedFilterInvocationDefinitionMap)procfilter.getFilterInvocationDefinitionSource();
-
- // add HTTPS URL path patterns to Spring Security config
- String httpsUrlsProp = WebloggerConfig.getProperty("schemeenforcement.https.urls");
- if (httpsUrlsProp != null) {
- String[] httpsUrls = StringUtils.stripAll(StringUtils.split(httpsUrlsProp, ",") );
- for (int i=0; i<httpsUrls.length; i++) {
- defmap.addSecureUrl(httpsUrls[i], secureDef);
- }
- }
- // all other action URLs are non-HTTPS
- defmap.addSecureUrl("/**<!-- need to remove this when uncommenting -->/*.do*", insecureDef);
- }
- */
}
diff --git a/app/src/main/java/org/apache/roller/weblogger/ui/core/filters/SchemeEnforcementFilter.java b/app/src/main/java/org/apache/roller/weblogger/ui/core/filters/SchemeEnforcementFilter.java
deleted file mode 100644
index 0b0b394..0000000
--- a/app/src/main/java/org/apache/roller/weblogger/ui/core/filters/SchemeEnforcementFilter.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. 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. For additional information regarding
- * copyright in this work, please see the NOTICE file in the top level
- * directory of this distribution.
- */
-/*
- * SchemeEnforcementFilter.java
- *
- * Created on September 16, 2005, 3:17 PM
- */
-
-package org.apache.roller.weblogger.ui.core.filters;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.roller.weblogger.config.WebloggerConfig;
-
-/**
- * The SchemeEnforcementFilter is provided for Roller sites that enable secure
- * logins and want to ensure that login urls are used only under https.
- *
- * @author Allen Gilliland
- * @web.filter name="SchemeEnforcementFilter"
- */
-public class SchemeEnforcementFilter implements Filter {
-
- private static Log log = LogFactory.getLog(SchemeEnforcementFilter.class);
-
- private boolean schemeEnforcementEnabled = false;
- private boolean secureLoginEnabled = false;
- private int httpPort = 80;
- private int httpsPort = 443;
-
- private Set<String> allowedUrls = new HashSet<String>();
- private Set<String> ignored = new HashSet<String>();
-
- /**
- * Process filter.
- * <p/>
- * We'll take the incoming request and first determine if this is a secure
- * request. If the request is secure then we'll see if it matches one of the
- * allowed secure urls, if not then we will redirect back out of https.
- */
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException {
-
- if (this.schemeEnforcementEnabled && this.secureLoginEnabled) {
-
- HttpServletRequest req = (HttpServletRequest) request;
- HttpServletResponse res = (HttpServletResponse) response;
-
- if (log.isDebugEnabled()) {
- log.debug("checking path = " + req.getServletPath());
- }
-
- if (!request.isSecure()
- && allowedUrls.contains(req.getServletPath())) {
-
- // http insecure request that should be over https
- String redirect = "https://" + req.getServerName();
-
- if (this.httpsPort != 443) {
- redirect += ":" + this.httpsPort;
- }
-
- redirect += req.getRequestURI();
-
- if (req.getQueryString() != null) {
- redirect += "?" + req.getQueryString();
- }
-
- if (log.isDebugEnabled()) {
- log.debug("Redirecting to " + redirect);
- }
-
- res.sendRedirect(redirect);
- return;
-
- } else if (request.isSecure()
- && !isIgnoredURL(req.getServletPath())
- && !allowedUrls.contains(req.getServletPath())) {
-
- // https secure request that should be over http
- String redirect = "http://" + req.getServerName();
-
- if (this.httpPort != 80) {
- redirect += ":" + this.httpPort;
- }
-
- redirect += req.getRequestURI();
-
- if (req.getQueryString() != null) {
- redirect += "?" + req.getQueryString();
- }
-
- if (log.isDebugEnabled()) {
- log.debug("Redirecting to " + redirect);
- }
-
- res.sendRedirect(redirect);
- return;
- }
- }
-
- chain.doFilter(request, response);
- }
-
- /**
- * Checks if the url is to be ignored.
- *
- * @param theUrl the the url
- * @return true, if the url is to be ignored.
- */
- private boolean isIgnoredURL(String theUrl) {
-
- int i = theUrl.lastIndexOf('.');
-
- return i <= 0 || i == theUrl.length()-1 || ignored.contains(theUrl.substring(i + 1));
-
- }
-
- /**
- * @see javax.servlet.Filter#destroy()
- */
- public void destroy() {
- }
-
- /**
- * Filter init.
- * <p/>
- * We are just collecting init properties which we'll use for each request.
- */
- public void init(FilterConfig filterConfig) {
-
- // determine if we are doing scheme enforcement
- this.schemeEnforcementEnabled = WebloggerConfig
- .getBooleanProperty("schemeenforcement.enabled");
- this.secureLoginEnabled = WebloggerConfig
- .getBooleanProperty("securelogin.enabled");
-
- if (this.schemeEnforcementEnabled && this.secureLoginEnabled) {
- // gather some more properties
- String http_port = WebloggerConfig
- .getProperty("securelogin.http.port");
- String https_port = WebloggerConfig
- .getProperty("securelogin.https.port");
-
- try {
- this.httpPort = Integer.parseInt(http_port);
- this.httpsPort = Integer.parseInt(https_port);
- } catch (NumberFormatException nfe) {
- // ignored ... guess we'll have to use the defaults
- log.warn("error with secure login ports", nfe);
- }
-
- // finally, construct our list of allowable https urls and ignored
- // resources
- String cfgs = WebloggerConfig
- .getProperty("schemeenforcement.https.urls");
- String[] cfgsArray = cfgs.split(",");
- Collections.addAll(this.allowedUrls, cfgsArray);
-
- cfgs = WebloggerConfig
- .getProperty("schemeenforcement.https.ignored");
- cfgsArray = StringUtils.stripAll(StringUtils.split(cfgs, ","));
- Collections.addAll(this.ignored, cfgsArray);
-
- // some logging for the curious
- log.info("Scheme enforcement = enabled");
- if (log.isDebugEnabled()) {
- log.debug("allowed urls are:");
- for (String allowedUrl : allowedUrls) {
- log.debug(allowedUrl);
- }
- log.debug("ignored extensions are:");
- for (String ignore : ignored) {
- log.debug(ignore);
- }
- }
- }
- }
-
-}
diff --git a/app/src/main/java/org/apache/roller/weblogger/ui/core/security/RollerRememberMeAuthenticationProvider.java b/app/src/main/java/org/apache/roller/weblogger/ui/core/security/RollerRememberMeAuthenticationProvider.java
new file mode 100644
index 0000000..d805c58
--- /dev/null
+++ b/app/src/main/java/org/apache/roller/weblogger/ui/core/security/RollerRememberMeAuthenticationProvider.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. 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. For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.weblogger.ui.core.security;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.weblogger.config.WebloggerConfig;
+import org.springframework.security.authentication.RememberMeAuthenticationProvider;
+
+
+public class RollerRememberMeAuthenticationProvider extends RememberMeAuthenticationProvider {
+ private static final Log log = LogFactory.getLog(RollerRememberMeServices.class);
+
+
+ public RollerRememberMeAuthenticationProvider(String ignored) {
+
+ String key = WebloggerConfig.getProperty("rememberme.key", "springRocks");
+
+ if ("springRocks".equals(key)) {
+ throw new RuntimeException(
+ "If remember-me is to be enabled, rememberme.key must be specified in the roller " +
+ "properties file. Make sure it is a secret and make sure it is NOT be springRocks");
+ }
+ setKey(key);
+ }
+}
+
+
diff --git a/app/src/main/java/org/apache/roller/weblogger/ui/core/security/RollerRememberMeServices.java b/app/src/main/java/org/apache/roller/weblogger/ui/core/security/RollerRememberMeServices.java
new file mode 100644
index 0000000..72cfee4
--- /dev/null
+++ b/app/src/main/java/org/apache/roller/weblogger/ui/core/security/RollerRememberMeServices.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. 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. For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.weblogger.ui.core.security;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.weblogger.config.AuthMethod;
+import org.apache.roller.weblogger.config.WebloggerConfig;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.codec.Hex;
+import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+
+public class RollerRememberMeServices extends TokenBasedRememberMeServices {
+ private static final Log log = LogFactory.getLog(RollerRememberMeServices.class);
+
+
+ public RollerRememberMeServices() {
+ }
+
+ public RollerRememberMeServices(String key, UserDetailsService userDetailsService) {
+ super(key, userDetailsService);
+ }
+
+ /**
+ * Calculates the digital signature to be put in the cookie. Default value is
+ * MD5 ("username:tokenExpiryTime:password:key")
+ *
+ * If LDAP is enabled then a configurable dummy password is used in the calculation.
+ */
+ protected String makeTokenSignature(long tokenExpiryTime, String username, String password) {
+
+ boolean usingLDAP = WebloggerConfig.getAuthMethod() == AuthMethod.LDAP;
+ if (usingLDAP) {
+ log.debug("LDAP is enabled; using dummy password in remember me signature.");
+
+ // for LDAP we don't store its password in the roller_users table,
+ // just an string indicating external auth method being used.
+ password = WebloggerConfig.getProperty("users.passwords.externalAuthValue","<externalAuth>");
+ }
+
+ String data = username + ":" + tokenExpiryTime + ":" + password + ":" + getKey();
+ MessageDigest digest;
+ try {
+ digest = MessageDigest.getInstance("MD5");
+ } catch (NoSuchAlgorithmException e) {
+ throw new IllegalStateException("No MD5 algorithm available!");
+ }
+
+ return new String(Hex.encode(digest.digest(data.getBytes())));
+ }
+
+
+}
diff --git a/app/src/main/java/org/apache/roller/weblogger/ui/rendering/plugins/comments/MathCommentAuthenticator.java b/app/src/main/java/org/apache/roller/weblogger/ui/rendering/plugins/comments/MathCommentAuthenticator.java
index 33a2d5d..8f37859 100644
--- a/app/src/main/java/org/apache/roller/weblogger/ui/rendering/plugins/comments/MathCommentAuthenticator.java
+++ b/app/src/main/java/org/apache/roller/weblogger/ui/rendering/plugins/comments/MathCommentAuthenticator.java
@@ -37,7 +37,7 @@
public String getHtml(HttpServletRequest request) {
- String answer = "";
+ int answer = 0;
HttpSession session = request.getSession(true);
if (session.getAttribute("mathAnswer") == null) {
@@ -51,10 +51,12 @@
session.setAttribute("mathAnswer", sum);
} else {
// preserve user's answer
- answer = request.getParameter("answer");
- answer = (answer == null) ? "" : answer;
+ String answerString = request.getParameter("answer");
+ try {
+ answer = Integer.parseInt(answerString);
+ } catch (Throwable intentionallyIgnored) {}
}
-
+
// pull existing values out of session
Integer value1o = (Integer)request.getSession().getAttribute("mathValue1");
Integer value2o = (Integer)request.getSession().getAttribute("mathValue2");
diff --git a/app/src/main/resources/org/apache/roller/weblogger/config/roller.properties b/app/src/main/resources/org/apache/roller/weblogger/config/roller.properties
index 4a4eeb8..64cb222 100644
--- a/app/src/main/resources/org/apache/roller/weblogger/config/roller.properties
+++ b/app/src/main/resources/org/apache/roller/weblogger/config/roller.properties
@@ -604,8 +604,10 @@
# True to enable history in Atom feeds with next/prev links
site.newsfeeds.history.enabled=false
-# Some folks consider remember-me type functionality to be a security
-rememberme.enabled=true
+# Some folks consider remember-me type functionality to be a security risk
+# If you enable remember me you MUST define a unique secret key that is not 'springRocks'
+rememberme.enabled=false
+rememberme.key=
# You might want to disable GZIP if your app server already supports it
compression.gzipResponse.enabled=true
diff --git a/app/src/main/resources/sql/400-to-500-migration.vm b/app/src/main/resources/sql/400-to-500-migration.vm
index 98e1e44..8ff0fca 100644
--- a/app/src/main/resources/sql/400-to-500-migration.vm
+++ b/app/src/main/resources/sql/400-to-500-migration.vm
@@ -87,7 +87,6 @@
username varchar(48)
);
create index oc_username_idx on roller_oauthconsumer( username$!db.INDEXSIZE );
-create index oc_consumerkey_idx on roller_oauthconsumer( consumerkey$!db.INDEXSIZE );
-- each record is an OAuth accessor, always tied to just one user
create table roller_oauthaccessor (
diff --git a/app/src/main/resources/sql/createdb.vm b/app/src/main/resources/sql/createdb.vm
index 5e6092e..b870a3c 100644
--- a/app/src/main/resources/sql/createdb.vm
+++ b/app/src/main/resources/sql/createdb.vm
@@ -508,4 +508,3 @@
-- oauth indexes
create index oc_username_idx on roller_oauthconsumer( username$!db.INDEXSIZE );
-create index oc_consumerkey_idx on roller_oauthconsumer( consumerkey$!db.INDEXSIZE );
diff --git a/app/src/main/resources/struts.xml b/app/src/main/resources/struts.xml
index eb6f8ba..a910901 100644
--- a/app/src/main/resources/struts.xml
+++ b/app/src/main/resources/struts.xml
@@ -154,6 +154,7 @@
<global-allowed-methods>
execute,
create,
+ update,
upgrade,
bootstrap
</global-allowed-methods>
diff --git a/app/src/main/webapp/WEB-INF/security.xml b/app/src/main/webapp/WEB-INF/security.xml
index 73094b0..9e4ba88 100644
--- a/app/src/main/webapp/WEB-INF/security.xml
+++ b/app/src/main/webapp/WEB-INF/security.xml
@@ -41,7 +41,7 @@
authentication-failure-url="/roller-ui/login.rol?error=true"
login-processing-url="/roller_j_security_check"/>
- <remember-me user-service-ref="rollerUserService"
+ <remember-me services-ref="rollerRememberMeServices"
key="715F2448-3176-11DD-ABC6-9CD955D89593"/>
<custom-filter ref="openidAuthenticationProcessingFilter" position="OPENID_FILTER"/>
@@ -63,18 +63,27 @@
<!-- Read users from Roller API -->
<authentication-manager alias='rollerAuthenticationManager'>
<authentication-provider ref="rememberMeAuthenticationProvider"/>
+
<!-- Uncomment one of the three below, based on whether database, LDAP, or
OpenID authentication is desired. -->
<authentication-provider user-service-ref="rollerUserService"/>
- <!--authentication-provider ref="ldapAuthProvider"/>
- <authentication-provider ref="openIDAuthProvider"/-->
+ <!--
+ <authentication-provider ref="ldapAuthProvider" />
+ <authentication-provider ref="openIDAuthProvider"/>
+ -->
</authentication-manager>
<beans:bean id="rollerUserService"
class="org.apache.roller.weblogger.ui.core.security.RollerUserDetailsService"/>
+ <beans:bean id="rollerRememberMeServices"
+ class="org.apache.roller.weblogger.ui.core.security.RollerRememberMeServices">
+ <beans:property name="key" value="715F2448-3176-11DD-ABC6-9CD955D89593"/>
+ <beans:property name="userDetailsService" ref="rollerUserService"/>
+ </beans:bean>
+
<beans:bean id="rememberMeAuthenticationProvider"
- class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
+ class="org.apache.roller.weblogger.ui.core.security.RollerRememberMeAuthenticationProvider">
<beans:property name="key" value="springRocks"/>
</beans:bean>
@@ -113,10 +122,10 @@
</beans:property>
</beans:bean>
- <!-- Uncomment & customize below beans if using LDAP -->
- <!--beans:bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
- <beans:constructor-arg value="ldap://localhost:10389/dc=example,dc=com" />
- <beans:property name="userDn" value="uid=admin,ou=system" />
+ <!-- Uncomment & customize below beans if using LDAP
+ <beans:bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
+ <beans:constructor-arg value="ldap://localhost:389/dc=example,dc=com" />
+ <beans:property name="userDn" value="uid=admin" />
<beans:property name="password" value="secret" />
</beans:bean>
@@ -142,6 +151,7 @@
<beans:constructor-arg index="1" value="(uid={0})" />
<beans:constructor-arg index="2" ref="contextSource" />
<beans:property name="searchSubtree" value="true" />
- </beans:bean-->
-
+ </beans:bean>
+ -->
+
</beans:beans>
diff --git a/app/src/main/webapp/WEB-INF/web.xml b/app/src/main/webapp/WEB-INF/web.xml
index c4fc2b3..ba74375 100644
--- a/app/src/main/webapp/WEB-INF/web.xml
+++ b/app/src/main/webapp/WEB-INF/web.xml
@@ -56,11 +56,6 @@
</filter>
<filter>
- <filter-name>SchemeEnforcementFilter</filter-name>
- <filter-class>org.apache.roller.weblogger.ui.core.filters.SchemeEnforcementFilter</filter-class>
- </filter>
-
- <filter>
<filter-name>CharEncodingFilter</filter-name>
<filter-class>org.apache.roller.weblogger.ui.core.filters.CharEncodingFilter</filter-class>
</filter>
@@ -104,13 +99,6 @@
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
- <!-- Scheme enforcement. Only here until we get Spring Security scheme enforcement working -->
- <filter-mapping>
- <filter-name>SchemeEnforcementFilter</filter-name>
- <url-pattern>/*</url-pattern>
- <dispatcher>REQUEST</dispatcher>
- </filter-mapping>
-
<!-- Spring Security filters - controls secure access to different parts of Roller -->
<filter-mapping>
<filter-name>securityFilter</filter-name>