--- ./src/java/org/apache/wiki/auth/AuthenticationManager.java 2009-03-04 15:08:50.503427000 +1100
+++ new/src/com/ecyrd/jspwiki/auth/AuthenticationManager.java 2009-03-04 14:06:33.000000000 +1100
@@ -110,21 +110,30 @@
/** If this jspwiki.properties property is true, allow cookies to be used to assert identities. */
protected static final String PROP_ALLOW_COOKIE_ASSERTIONS = "jspwiki.cookieAssertions";
/** The {@link javax.security.auth.spi.LoginModule} to use for custom authentication. */
protected static final String PROP_LOGIN_MODULE = "jspwiki.loginModule.class";
+ /** Property specifying whether the LoginModule can change login names or passwords. */
+ protected static final String PROP_CHANGE_LOGIN = "jspwiki.loginModule.canChangeLoginName";
+ protected static final String PROP_CHANGE_PASSWORD = "jspwiki.loginModule.canChangePassword";
+
/** Empty Map passed to JAAS {@link #doJAASLogin(Class, CallbackHandler, Map)} method. */
protected static final Map EMPTY_MAP = Collections.unmodifiableMap( new HashMap() );
/** Class (of type LoginModule) to use for custom authentication. */
protected Class extends LoginModule> m_loginModuleClass = UserDatabaseLoginModule.class;
/** Options passed to {@link javax.security.auth.spi.LoginModule#initialize(Subject, CallbackHandler, Map, Map)};
* initialized by {@link #initialize(WikiEngine, Properties)}. */
protected Map m_loginModuleOptions = new HashMap();
+ /** Can this LoginModule change the username or password?
+ * initialized by {@link #initialize(WikiEngine, Properties)}. */
+ protected boolean m_canChangeLoginName = true;
+ protected boolean m_canChangePassword = true;
+
/** Just to provide compatibility with the old versions. The same
* as SECURITY_OFF.
*
* @deprecated use {@link #SECURITY_OFF} instead
*/
@@ -149,20 +158,52 @@
/** If true, logs the IP address of the editor */
private boolean m_storeIPAddress = true;
private boolean m_useJAAS = true;
/** Keeps a list of the usernames who have attempted a login recently. */
private TimedCounterList m_lastLoginAttempts = new TimedCounterList();
/**
+ * Returns true if the current Authentication manager is capable of
+ * changing the login name. Defaults to true for most LoginModules
+ * except when using container based authentication.
+ *
+ * @return true if it is possible to change the password,
+ * false otherwise.
+ */
+ public final boolean canChangeLoginName()
+ {
+ if (isContainerAuthenticated())
+ return false;
+ else
+ return m_canChangeLoginName;
+ }
+
+ /**
+ * Returns true if the current Authentication manager is capable of
+ * changing the password. Defaults to true for most LoginModules
+ * except when using container based authentication.
+ *
+ * @return true if it is possible to change the password,
+ * false otherwise.
+ */
+ public final boolean canChangePassword()
+ {
+ if (isContainerAuthenticated())
+ return false;
+ else
+ return m_canChangePassword;
+ }
+
+ /**
* Creates an AuthenticationManager instance for the given WikiEngine and
* the specified set of properties. All initialization for the modules is
* done here.
* @param engine the wiki engine
* @param props the properties used to initialize the wiki engine
* @throws WikiException if the AuthenticationManager cannot be initialized
*/
@SuppressWarnings("unchecked")
public final void initialize( WikiEngine engine, Properties props ) throws WikiException
{
@@ -192,18 +233,25 @@
try
{
m_loginModuleClass = (Class extends LoginModule>) Class.forName( loginModuleClassName );
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
throw new WikiException(e.getMessage());
}
+ // Can this LoginModule change names or passwords?
+ m_canChangeLoginName = TextUtil.getBooleanProperty( props,
+ PROP_CHANGE_LOGIN,
+ true );
+ m_canChangePassword = TextUtil.getBooleanProperty( props,
+ PROP_CHANGE_PASSWORD,
+ true );
// Initialize the LoginModule options
initLoginModuleOptions( props );
}
/**
* Returns true if this WikiEngine uses container-managed authentication.
* This method is used primarily for cosmetic purposes in the JSP tier, and
* performs no meaningful security function per se. Delegates to
@@ -637,21 +624,21 @@
// Try creating an absolute path first
File defaultFile = null;
if( engine.getRootPath() != null )
{
defaultFile = new File( engine.getRootPath() + "/WEB-INF/" + name );
}
if ( defaultFile != null && defaultFile.exists() )
{
try
{
- return defaultFile.toURL();
+ return defaultFile.toURI().toURL();
}
catch ( MalformedURLException e)
{
// Shouldn't happen, but log it if it does
log.warn( "Malformed URL: " + e.getMessage() );
}
}
// Ok, the absolute path didn't work; try other methods
--- ./src/java/org/apache/wiki/auth/UserManager.java 2009-03-04 15:08:50.487395000 +1100
+++ new/src/com/ecyrd/jspwiki/auth/UserManager.java 2009-03-04 14:22:51.000000000 +1100
@@ -444,12 +441,12 @@
loginName = InputValidator.isBlank( loginName ) ? null : loginName;
password = InputValidator.isBlank( password ) ? null : password;
fullname = InputValidator.isBlank( fullname ) ? null : fullname;
email = InputValidator.isBlank( email ) ? null : email;
- // A special case if we have container authentication
- if ( m_engine.getAuthenticationManager().isContainerAuthenticated() )
+ // A special case if we can't rename accounts
+ if ( !m_engine.getAuthenticationManager().canChangeLoginName() )
{
// If authenticated, login name is always taken from container
if ( context.getWikiSession().isAuthenticated() )
{
loginName = context.getWikiSession().getLoginPrincipal().getName();
@@ -500,23 +497,24 @@
}
break;
}
}
- // If container-managed auth and user not logged in, throw an error
- if ( m_engine.getAuthenticationManager().isContainerAuthenticated()
+ // If we can't change or create loginnames and user not logged in,
+ // throw an error
+ if ( !m_engine.getAuthenticationManager().canChangeLoginName()
&& !context.getWikiSession().isAuthenticated() )
{
session.addMessage( SESSION_MESSAGES, rb.getString("security.error.createprofilebeforelogin") );
}
validator.validateNotNull( profile.getLoginName(), rb.getString("security.user.loginname") );
validator.validateNotNull( profile.getFullname(), rb.getString("security.user.fullname") );
validator.validate( profile.getEmail(), rb.getString("security.user.email"), InputValidator.EMAIL );
// If new profile, passwords must match and can't be null
- if ( !m_engine.getAuthenticationManager().isContainerAuthenticated() )
+ if ( m_engine.getAuthenticationManager().canChangePassword() )
{
String password = profile.getPassword();
if ( password == null )
{
if ( isNew )
--- ./src/java/org/apache/wiki/tags/UserProfileTag.java 2009-03-04 15:08:46.789924000 +1100
+++ new/src/com/ecyrd/jspwiki/tags/UserProfileTag.java 2009-03-04 13:28:48.000000000 +1100
@@ -181,22 +180,34 @@
{
result = user.getName();
}
}
}
- else if ( CHANGE_PASSWORD.equals( m_prop ) || CHANGE_LOGIN_NAME.equals( m_prop ) )
+ else if ( CHANGE_LOGIN_NAME.equals( m_prop ) || NOT_CHANGE_LOGIN_NAME.equals( m_prop ) )
{
- AuthenticationManager authMgr = m_wikiContext.getEngine().getAuthenticationManager();
- if ( !authMgr.isContainerAuthenticated() )
+ boolean canChange = m_wikiContext.getEngine().getAuthenticationManager().canChangeLoginName();
+
+ // Cheap and nasty trick to check for boolean NOT
+ if ( m_prop.charAt(0) == '!' )
+ {
+ canChange = !canChange;
+ }
+ if ( canChange )
{
return EVAL_BODY_INCLUDE;
}
}
- else if ( NOT_CHANGE_PASSWORD.equals( m_prop ) || NOT_CHANGE_LOGIN_NAME.equals( m_prop ) )
+ else if ( CHANGE_PASSWORD.equals( m_prop ) || NOT_CHANGE_PASSWORD.equals( m_prop ) )
{
- AuthenticationManager authMgr = m_wikiContext.getEngine().getAuthenticationManager();
- if ( authMgr.isContainerAuthenticated() )
+ boolean canChange = m_wikiContext.getEngine().getAuthenticationManager().canChangePassword();
+
+ // Cheap and nasty trick to check for boolean NOT
+ if ( m_prop.charAt(0) == '!' )
+ {
+ canChange = !canChange;
+ }
+ if ( canChange )
{
return EVAL_BODY_INCLUDE;
}
}
--- ./etc/jspwiki.properties.tmpl 2009-03-04 15:09:52.481215000 +1100
+++ new/etc/jspwiki.properties.tmpl 2009-03-04 15:46:44.678536000 +1100
@@ -441,10 +441,17 @@
# The implementation MUST have a zero-argument constructor (as noted in the
# javax.security.auth.spi.LoginModule Javadocs).
jspwiki.loginModule.class = org.apache.wiki.auth.login.UserDatabaseLoginModule
#
+# Not all LoginModules allow you to change login names or passwords. Set these
+# options to false if you use a custom LoginModule which doesn't allow these
+# changes.
+#jspwiki.loginModule.canChangeLoginName = true
+#jspwiki.loginModule.canChangePassword = true
+
+#
# JAAS LoginContext parameters used to initialize the LoginModule. Note that 'param1'
# etc. should be replaced with the actual parameter names. The parameter names and
# values will be loaded to a Map and passed to the LoginModule as the 'options' parameter
# when its initialize() method is called. The default UserDatabaseLoginModule class does
# not need any options.
--- ./UPGRADING 2009-03-04 15:09:52.916210000 +1100
+++ new/UPGRADING 2009-03-04 15:50:52.712754000 +1100
@@ -111,10 +111,17 @@
in jspwiki.properties as follows:
jspwiki.loginModule.class = com.foo.login.MyLoginModule
If this property is not set, JSPWiki will default (as before) to the
UserDatabaseLoginModule implementation.
+
+ Unlike the default UserDatabaseLoginModule, some custom Login Modules do
+ not allow for login name or password changes. If that is the case with
+ your custom module, set the following properties to false (defualt
+ is true):
+ jspwiki.loginModule.canChangeLoginName = true
+ jspwiki.loginModule.canChangePassword = true
Note that parameters passed to your custom LoginModule are now expressed in
jspwiki.properties also, as key/value pairs, rather than in the JAAS config
file. The parameter names and values will be loaded to a Map and passed to
the LoginModule as the 'options' parameter when its initialize() method
@@ -317,6 +324,6 @@
-> For security reasons, class com.ecyrd.jspwiki.auth.user.DefaultUserProfile
was made final.
-> Class com.ecyrd.jspwiki.rpc.RPCManager's constructor is now protected.
- -> Class com.ecyrd.jspwiki.plugin.BugReportHandler had it's public parameter names changed to PARAM_xxx
\ No newline at end of file
+ -> Class com.ecyrd.jspwiki.plugin.BugReportHandler had it's public parameter names changed to PARAM_xxx