Commit 23ef575f authored by Guus der Kinderen's avatar Guus der Kinderen Committed by daryl herzmann

OF-1313: Add CSRF protection to the MoTD plugin. (#773)

In an annoying quest to reproduce a bug related to JSTL and plugins I completely redid the MoTD plugin admin console page. I added CSRF protection to justify my changes.

Never did reproduce that bug...
parent 89b37591
......@@ -42,6 +42,12 @@
<h1>MotD Plugin Changelog</h1>
<p><b>1.2.1</b> -- April 14, 2017</p>
<ul>
<li>Added Cross-Site Request Forgery protection in the admin console page.</li>
<li>Minor visual changed on the admin console page.</li>
</ul>
<p><b>1.2.0</b> -- October 12, 2015</p>
<ul>
<li>[<a href='http://www.igniterealtime.org/issues/browse/OF-953'>OF-953</a>] - Updated JSP libraries.</li>
......
......@@ -5,8 +5,8 @@
<name>MotD (Message of the Day)</name>
<description>Allows admins to have a message sent to users each time they log in.</description>
<author>Ryan Graham</author>
<version>1.2.0</version>
<date>10/12/2015</date>
<version>1.2.1</version>
<date>04/14/2017</date>
<minServerVersion>4.0.0</minServerVersion>
<adminconsole>
......
......@@ -3,6 +3,7 @@ login.title=Admin Console
motd.title=MotD (Message of the Day)
motd.options=MotD Options
motd.saved.success=Settings saved successfully.
motd.required=Required fields.
motd.enable=Enable MotD message.
motd.directions=Enter the message that will be sent to users when they sign-in.
motd.subject=Subject
......
......@@ -62,7 +62,7 @@ public class MotDPlugin implements Plugin {
}
public void setEnabled(boolean enable) {
JiveGlobals.setProperty(ENABLED, enable ? Boolean.toString(true) : Boolean.toString(false));
JiveGlobals.setProperty(ENABLED, Boolean.toString(enable));
}
public boolean isEnabled() {
......
<%@ page
import="org.jivesoftware.openfire.XMPPServer,
org.jivesoftware.openfire.plugin.MotDPlugin,
org.jivesoftware.util.CookieUtils,
org.jivesoftware.util.ParamUtils,
java.util.HashMap,
java.util.Map"
errorPage="error.jsp"%>
org.jivesoftware.util.StringUtils,
java.util.HashMap"
errorPage="error.jsp"%>
<%@ page import="java.util.Map" %>
<%@ taglib uri="admin" prefix="admin" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%
boolean save = request.getParameter("save") != null;
boolean motdEnabled = ParamUtils.getBooleanParameter(request, "motdenabled", false);
String motdSubject = ParamUtils.getParameter(request, "motdSubject");
String motdMessage = ParamUtils.getParameter(request, "motdMessage");
MotDPlugin plugin = (MotDPlugin) XMPPServer.getInstance().getPluginManager().getPlugin("motd");
Map<String, String> errors = new HashMap<String, String>();
if (save) {
if (motdSubject == null || motdSubject.trim().length() < 1) {
errors.put("missingMotdSubject", "missingMotdSubject");
}
if (motdMessage == null || motdMessage.trim().length() < 1) {
errors.put("missingMotdMessage", "missingMotdMessage");
}
if (errors.size() == 0) {
plugin.setEnabled(motdEnabled);
plugin.setSubject(motdSubject);
plugin.setMessage(motdMessage);
response.sendRedirect("motd-form.jsp?settingsSaved=true");
return;
}
}
motdEnabled = plugin.isEnabled();
motdSubject = plugin.getSubject();
motdMessage = plugin.getMessage();
final boolean save = request.getParameter( "save" ) != null;
final boolean motdEnabled = ParamUtils.getBooleanParameter( request, "motdenabled", false );
final String motdSubject = ParamUtils.getParameter( request, "motdSubject" );
final String motdMessage = ParamUtils.getParameter( request, "motdMessage" );
final Cookie csrfCookie = CookieUtils.getCookie( request, "csrf" );
final String csrfParam = ParamUtils.getParameter( request, "csrf" );
final MotDPlugin plugin = (MotDPlugin) XMPPServer.getInstance().getPluginManager().getPlugin( "motd" );
final Map<String, String> errors = new HashMap<>();
if ( save )
{
if ( csrfCookie == null || csrfParam == null || !csrfCookie.getValue().equals( csrfParam ) )
{
errors.put( "csrf", "CSRF Failure!" );
}
if ( motdSubject == null || motdSubject.trim().length() < 1 )
{
errors.put( "missingMotdSubject", "missingMotdSubject" );
}
if ( motdMessage == null || motdMessage.trim().length() < 1 )
{
errors.put( "missingMotdMessage", "missingMotdMessage" );
}
if ( errors.isEmpty() )
{
plugin.setEnabled( motdEnabled );
plugin.setSubject( motdSubject );
plugin.setMessage( motdMessage );
response.sendRedirect( "motd-form.jsp?settingsSaved=true" );
return;
}
}
final String csrf = StringUtils.randomString( 15 );
CookieUtils.setCookie( request, response, "csrf", csrf, -1 );
pageContext.setAttribute( "csrf", csrf );
pageContext.setAttribute( "errors", errors );
pageContext.setAttribute( "motdEnabled", plugin.isEnabled() );
pageContext.setAttribute( "motdSubject", plugin.getSubject() );
pageContext.setAttribute( "motdMessage", plugin.getMessage() );
%>
<html>
......@@ -49,59 +69,60 @@
</head>
<body>
<form action="motd-form.jsp?save" method="post">
<div class="jive-contentBoxHeader"><fmt:message key="motd.options" /></div>
<div class="jive-contentBox">
<% if (ParamUtils.getBooleanParameter(request, "settingsSaved")) { %>
<div class="jive-success">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td class="jive-icon"><img src="images/success-16x16.gif" width="16" height="16" border="0"></td>
<td class="jive-icon-label"><fmt:message key="motd.saved.success" /></td>
</tr>
</tbody>
</table>
</div>
<% } %>
<table cellpadding="3" cellspacing="0" border="0" width="100%">
<tbody>
<tr>
<td width="1%" align="center" nowrap><input type="checkbox" name="motdenabled" <%=motdEnabled ? "checked" : "" %>></td>
<td width="99%" align="left"><fmt:message key="motd.enable" /></td>
</tr>
</tbody>
</table>
<br><br>
<c:choose>
<c:when test="${not empty param.settingsSaved and empty errors}">
<admin:infoBox type="success"><fmt:message key="motd.saved.success" /></admin:infoBox>
</c:when>
<c:otherwise>
<c:forEach var="err" items="${errors}">
<admin:infobox type="error">
<c:choose>
<c:when test="${err.key eq 'missingMotdSubject'}"><fmt:message key="motd.subject.missing"/></c:when>
<c:when test="${err.key eq 'missingMotdMessage'}"><fmt:message key="motd.message.missing"/></c:when>
<c:otherwise>
<c:if test="${not empty err.value}">
<c:out value="${err.value}"/>
</c:if>
(<c:out value="${err.key}"/>)
</c:otherwise>
</c:choose>
</admin:infobox>
</c:forEach>
</c:otherwise>
</c:choose>
<p><fmt:message key="motd.directions" /></p>
<table cellpadding="3" cellspacing="0" border="0" width="100%">
<tbody>
<tr>
<td width="5%" valign="top"><fmt:message key="motd.subject" />:&nbsp;</td>
<td width="95%"><input type="text" name="motdSubject" value="<%= motdSubject %>"></td>
<% if (errors.containsKey("missingMotdSubject")) { %>
<span class="jive-error-text"><fmt:message key="motd.subject.missing" /></span>
<% } %>
</tr>
<tr>
<td width="5%" valign="top"><fmt:message key="motd.message" />:&nbsp;</td>
<td width="95%"><textarea cols="45" rows="5" wrap="virtual" name="motdMessage"><%= motdMessage %></textarea></td>
<% if (errors.containsKey("missingMotdMessage")) { %>
<span class="jive-error-text"><fmt:message key="motd.message.missing" /></span>
<% } %>
</tr>
</tbody>
</table>
</div>
<input type="submit" value="<fmt:message key="motd.button.save" />"/>
</form>
<form action="motd-form.jsp?save" method="post">
<fmt:message key="motd.options" var="boxtitle"/>
<admin:contentBox title="${boxtitle}">
<p><input type="checkbox" name="motdenabled" id="motdenabled" ${ motdEnabled ? 'checked' : '' }/> <label for="motdenabled"><fmt:message key="motd.enable" /></label></p>
<table cellpadding="3" cellspacing="0" border="0" width="100%">
<tr>
<td width="5%" valign="top"><fmt:message key="motd.subject" />:&nbsp;*</td>
<td width="95%"><input type="text" name="motdSubject" value="${motdSubject}"></td>
</tr>
<tr>
<td width="5%" valign="top"><fmt:message key="motd.message" />:&nbsp;*</td>
<td width="95%"><textarea cols="45" rows="5" wrap="virtual" name="motdMessage"><c:out value="${motdMessage}"/></textarea></td>
</tr>
<tr>
<td colspan="2" style="padding-top: 10px"><input type="submit" value="<fmt:message key="motd.button.save" />"/></td>
</tr>
</table>
</admin:contentBox>
<span class="jive-description">
* <fmt:message key="motd.required" />
</span>
<input type="hidden" name="csrf" value="${csrf}">
</form>
</body>
</html>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment