Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion UPGRADING
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

Apache JSPWiki 2.12.0 - Upgrading Notes
Apache JSPWiki 3.0.0 - Upgrading Notes
==================================================

Licensed to the Apache Software Foundation (ASF) under one
Expand All @@ -21,6 +21,26 @@ Apache JSPWiki 2.12.0 - Upgrading Notes

The license file can be found in LICENSE.


Upgrading JSPWiki to 3.0.0
---------------------------
Please see https://jspwiki-wiki.apache.org/Wiki.jsp?page=NewIn3.0.0 for details

1. New requirements
* Java 17 needed to run JSPWiki

2. Backwards incompatible changes:
* Page level access controls (i.e. [ALLOW edit/view/etc User/Role] ) logic has been changed including the IF plugin.
See details with JSPWIKI-130.

To maintain the behavior of JSPWiki 2.X use the following setting in jspwiki-custom.properties.
jspwiki.security.useOldPageAccessControlLogic=true
This is not recommended.

3. Many new security features have been added and enabled by default. Please review the default
jspwiki.properties file


Upgrading JSPWiki to 2.12.0
---------------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,12 @@ Licensed to the Apache Software Foundation (ASF) under one
* {@code Context#getEngine()} method or through {@code Wiki.engine().find(..)} DSL methods.
*/
public interface Engine {

/**
* see JSPWIKI-130
* @since 3.0.0
*/
String PROP_USE_2_X_ACL_LOGIC = "jspwiki.security.useOldPageAccessControlLogic";

/** The default inlining pattern. Currently "*.png" */
String DEFAULT_INLINEPATTERN = "*.png";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ public Principal getCurrentUser() {
// This shouldn't happen, really...
return WikiPrincipal.GUEST;
}
return m_session.getUserPrincipal();
return m_session.getLoginPrincipal();
}

/**
Expand Down
1 change: 1 addition & 0 deletions jspwiki-main/src/main/java/org/apache/wiki/WikiPage.java
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ public int compareTo( final Page page ) {
*
* {@inheritDoc}
*/
@Override
public boolean equals( final Object o ) {
if( o instanceof WikiPage ) {
final WikiPage wp = ( WikiPage )o;
Expand Down
8 changes: 7 additions & 1 deletion jspwiki-main/src/main/java/org/apache/wiki/WikiSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ protected void injectUserProfilePrincipals() {
throw new IllegalStateException( "User database cannot be null." );
}
try {
final UserProfile profile = database.find( searchId );
final UserProfile profile = database.findByLoginName( searchId );
final Principal[] principals = database.getPrincipals( profile.getLoginName() );
for( final Principal principal : principals ) {
// Add the Principal to the Subject
Expand All @@ -428,6 +428,12 @@ protected void injectUserProfilePrincipals() {
// Set the user principal if needed; we prefer FullName, but the WikiName will also work
final boolean isFullNamePrincipal = ( principal instanceof WikiPrincipal &&
( ( WikiPrincipal )principal ).getType().equals( WikiPrincipal.FULL_NAME ) );
if (( principal instanceof WikiPrincipal &&
( ( WikiPrincipal )principal ).getType().equals( WikiPrincipal.LOGIN_NAME )) ){
m_loginPrincipal = principal;
}


if ( isFullNamePrincipal ) {
m_userPrincipal = principal;
} else if ( !( m_userPrincipal instanceof WikiPrincipal ) ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,8 @@ default boolean hasAccess( final Context context, final HttpServletResponse resp
* <li>Finally, if a user cannot be found, manufacture and return a generic {@link org.apache.wiki.auth.acl.UnresolvedPrincipal}</li>
* </ol>
*
* @param name the name of the Principal to resolve
* @param name the name of the Principal to resolve. Note: as of v3.0.0, the
* underlying behavior has changed. Principals can be resolved via login names only.
* @return the fully-resolved Principal
*/
Principal resolvePrincipal( final String name );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,13 @@ Licensed to the Apache Software Foundation (ASF) under one
import jakarta.servlet.http.HttpSession;
import java.security.Principal;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.apache.wiki.WikiContext;
import org.apache.wiki.api.core.Context;
import org.apache.wiki.auth.user.DefaultUserProfile;
import org.apache.wiki.auth.user.UserProfile;


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,37 +335,35 @@ public Principal resolvePrincipal( final String name ) {
// Check built-in Roles first
final Role role = new Role(name);
if ( Role.isBuiltInRole( role ) ) {
return role;
return role;
}

// Check Authorizer Roles
Principal principal = m_authorizer.findRole( name );
if ( principal != null ) {
return principal;
return principal;
}

// Check Groups
principal = m_engine.getManager( GroupManager.class ).findRole( name );
if ( principal != null ) {
return principal;
return principal;
}

// Ok, no luck---this must be a user principal
final Principal[] principals;
final UserProfile profile;
final UserDatabase db = m_engine.getManager( UserManager.class ).getUserDatabase();
try {
profile = db.find( name );
principals = db.getPrincipals( profile.getLoginName() );
for( final Principal value : principals ) {
principal = value;
if( principal.getName().equals( name ) ) {
return principal;
}
}
principals = db.getPrincipals( name );
for( final Principal value : principals ) {
principal = value;
if( principal.getName().equals( name ) ) {
return principal;
}
}
} catch( final NoSuchPrincipalException e ) {
// We couldn't find the user...
LOG.debug(e.getMessage(), e);
// We couldn't find the user...
LOG.debug(e.getMessage(), e);
}
// Ok, no luck---mark this as unresolved and move on
return new UnresolvedPrincipal( name );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ Licensed to the Apache Software Foundation (ASF) under one
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.WeakHashMap;
import org.apache.wiki.auth.authorize.Group;
import org.apache.wiki.auth.authorize.GroupManager;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.node.ObjectNode;

Expand Down Expand Up @@ -156,7 +158,7 @@ public UserProfile getUserProfile( final Session session ) {
if ( session.isAuthenticated() ) {
user = session.getUserPrincipal();
try {
profile = getUserDatabase().find( user.getName() );
profile = getUserDatabase().findByWikiName( user.getName());
newProfile = false;
} catch( final NoSuchPrincipalException e ) {
LOG.debug(e.getMessage(), e);
Expand All @@ -167,6 +169,8 @@ public UserProfile getUserProfile( final Session session ) {
profile = getUserDatabase().newProfile();
if ( user != null ) {
profile.setLoginName( user.getName() );
} else {
LOG.warn("new profile however the user principal is null. this shouldn't happen");
}
if ( !profile.isNew() ) {
throw new IllegalStateException( "New profile should be marked 'new'. Check your UserProfile implementation." );
Expand Down Expand Up @@ -202,7 +206,8 @@ public void setUserProfile( final Context context, final UserProfile profile ) t
if( otherProfile != null && !otherProfile.equals( oldProfile ) ) {
throw new DuplicateUserException( "security.error.login.taken", profile.getLoginName() );
}
} catch( final NoSuchPrincipalException e ) {
} catch (final NoSuchPrincipalException e) {
LOG.debug(e.getMessage(), e);
}
try {
otherProfile = getUserDatabase().findByFullName( profile.getFullname() );
Expand Down Expand Up @@ -249,6 +254,7 @@ public void setUserProfile( final Context context, final UserProfile profile ) t
fireEvent( WikiSecurityEvent.PROFILE_SAVE, session, profile );
}
}
m_profiles.put( session, profile );
}

/** {@inheritDoc} */
Expand Down Expand Up @@ -390,31 +396,88 @@ public void validateProfile( final Context context, final UserProfile profile )
UserProfile otherProfile;
final String fullName = profile.getFullname();
final String loginName = profile.getLoginName();
final String wikiName = profile.getWikiName();
final String email = profile.getEmail();

// It's illegal to use as a full name someone else's login name
try {
otherProfile = getUserDatabase().findByFullName(fullName );
if( otherProfile != null && !profile.equals( otherProfile ) && !fullName.equals( otherProfile.getFullname() ) ) {
final Object[] args = { fullName };
session.addMessage( SESSION_MESSAGES, MessageFormat.format( rb.getString( "security.error.illegalfullname" ), args ) );

if ("true".equalsIgnoreCase(m_engine.getWikiProperties().getProperty(Engine.PROP_USE_2_X_ACL_LOGIC, "false"))) {
// It's illegal to use as a full name someone else's login name
try {
otherProfile = getUserDatabase().findByFullName(fullName );
if( otherProfile != null && !profile.equals( otherProfile ) && !fullName.equals( otherProfile.getFullname() ) ) {
final Object[] args = { fullName };
session.addMessage( SESSION_MESSAGES, MessageFormat.format( rb.getString( "security.error.illegalfullname" ), args ) );
}
} catch( final NoSuchPrincipalException e ) {
LOG.debug(e.getMessage(), e);
/* It's clean */
}
} catch( final NoSuchPrincipalException e ) {
LOG.debug(e.getMessage(), e);
/* It's clean */
}

// It's illegal to use as a login name someone else's full name
try {
otherProfile = getUserDatabase().findByLoginName(loginName );
if( otherProfile != null && !profile.equals( otherProfile ) && !loginName.equals( otherProfile.getLoginName() ) ) {
final Object[] args = { loginName };
session.addMessage( SESSION_MESSAGES, MessageFormat.format( rb.getString( "security.error.illegalloginname" ), args ) );
// It's illegal to use as a login name someone else's full name
try {
otherProfile = getUserDatabase().findByLoginName(loginName );
if( otherProfile != null && !profile.equals( otherProfile ) && !loginName.equals( otherProfile.getLoginName() ) ) {
final Object[] args = { loginName };
session.addMessage( SESSION_MESSAGES, MessageFormat.format( rb.getString( "security.error.illegalloginname" ), args ) );
}
} catch( final NoSuchPrincipalException e ) {
LOG.debug(e.getMessage(), e);
/* It's clean */
}
} else {
//JSPWIKI-130, v3+ behavior
// It is legal to use as a full name someone else's login name

// It's illegal to use as a login name someone else's full name
try {
otherProfile = getUserDatabase().findByLoginName(loginName );
if( otherProfile != null && !profile.equals( otherProfile ) && !loginName.equals( otherProfile.getLoginName() ) ) {
final Object[] args = { loginName };
session.addMessage( SESSION_MESSAGES, MessageFormat.format(
rb.getString( "security.error.illegalloginname" ), args ) );
}
} catch( final NoSuchPrincipalException e ) {
LOG.debug(e.getMessage(), e);
/* It's clean */
}
//it's illegal to use a username, email or wiki name as a group name
try {
Group[] groups = m_engine.getManager(GroupManager.class).getGroupDatabase().groups();
for (Group grp : groups) {
if (grp.getName().equals(loginName)) {
final Object[] args = {loginName};
session.addMessage(SESSION_MESSAGES,
MessageFormat.format(rb.getString("security.error.illegalloginname"), args));
}
if (grp.getName().equals(wikiName)) {
final Object[] args = {wikiName};
session.addMessage(SESSION_MESSAGES,
MessageFormat.format(rb.getString("security.error.illegalloginname"), args));
}
if (grp.getName().equals(email)) {
final Object[] args = {email};
session.addMessage(SESSION_MESSAGES,
MessageFormat.format(rb.getString("security.error.illegalloginname"), args));
}
}
} catch (WikiSecurityException ex) {
session.addMessage(SESSION_MESSAGES,
"Processing failed. see log for details.");
LOG.error("failed to query for groups", ex);
}
//wiki names must be unique as well.
try {
otherProfile = getUserDatabase().findByWikiName(wikiName );
if( otherProfile != null && !profile.equals( otherProfile ) && !loginName.equals( otherProfile.getLoginName() ) ) {
final Object[] args = { loginName };
session.addMessage( SESSION_MESSAGES, MessageFormat.format( rb.getString( "security.error.illegalloginname" ), args ) );
}
} catch( final NoSuchPrincipalException e ) {
LOG.debug(e.getMessage(), e);
/* It's clean */
}
} catch( final NoSuchPrincipalException e ) {
LOG.debug(e.getMessage(), e);
/* It's clean */
}


// It's illegal to use multiple accounts with the same email
if (email != null && email.trim().length() > 0) {
Expand Down Expand Up @@ -515,7 +578,7 @@ public void service( final HttpServletRequest req, final HttpServletResponse res
*/
public UserProfile getUserInfo( final String uid ) throws NoSuchPrincipalException {
if( m_manager != null ) {
return m_manager.getUserDatabase().findByWikiName( uid );
return m_manager.getUserDatabase().findByUid( uid );
}

throw new IllegalStateException( "The manager is offline." );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ public Group parseGroup( String name, String memberLine, final boolean create )
if( create ) {
name = "MyGroup";
} else {
//TODO i18n
throw new WikiSecurityException( "Group name cannot be blank." );
}
} else if( ArrayUtils.contains( Group.RESTRICTED_GROUPNAMES, name ) ) {
Expand Down Expand Up @@ -224,6 +225,7 @@ public Group parseGroup( String name, String memberLine, final boolean create )
} catch( final NoSuchPrincipalException e ) {
// It's a new group.... throw error if we don't create new ones
if( !create ) {
//TODO i18n
throw new NoSuchPrincipalException( "Group '" + name + "' does not exist." );
}
}
Expand All @@ -236,6 +238,26 @@ public Group parseGroup( String name, String memberLine, final boolean create )
group.add( new WikiPrincipal( member ) );
}
}

if ("false".equalsIgnoreCase(m_engine.getWikiProperties().getProperty(Engine.PROP_USE_2_X_ACL_LOGIC, "false"))) {
//check to ensure that the group name does not conflict with any existing user account login, email or wiki name
UserManager userManger = m_engine.getManager(UserManager.class);
try { userManger.getUserDatabase().findByEmail(name);
throw new WikiSecurityException( "Group name conflicts with a user account" );
}catch (NoSuchPrincipalException e) {
//no issues here
}
try { userManger.getUserDatabase().findByLoginName(name);
throw new WikiSecurityException( "Group name conflicts with a user account" );
}catch (NoSuchPrincipalException e) {
//no issues here
}
try { userManger.getUserDatabase().findByWikiName(name);
throw new WikiSecurityException( "Group name conflicts with a user account" );
}catch (NoSuchPrincipalException e) {
//no issues here
}
}

return group;
}
Expand Down
Loading
Loading