This is an automated email from the ASF dual-hosted git repository. juanpablo pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/jspwiki.git
commit f1b62ab54488614ac209b26ffa727504df5cf81d Author: juanpablo <[email protected]> AuthorDate: Thu Feb 20 18:43:16 2020 +0100 JSPWIKI-120: rename + extract interface from AuthorizationManager --- .../org/apache/wiki/auth/AuthorizationManager.java | 654 +++------------------ .../main/java/org/apache/wiki/auth/Authorizer.java | 10 +- .../wiki/auth/DefaultAuthorizationManager.java | 425 +++++++++++++ .../apache/wiki/auth/authorize/GroupDatabase.java | 4 +- .../apache/wiki/auth/authorize/GroupManager.java | 141 +++-- .../wiki/auth/authorize/JDBCGroupDatabase.java | 118 ++-- .../apache/wiki/auth/authorize/WebAuthorizer.java | 20 +- .../auth/authorize/WebContainerAuthorizer.java | 92 ++- .../wiki/auth/authorize/XMLGroupDatabase.java | 35 +- .../src/main/resources/ini/classmappings.xml | 2 +- .../wiki/auth/AuthenticationManagerTest.java | 103 ++-- .../java/org/apache/wiki/auth/TestAuthorizer.java | 42 +- 12 files changed, 774 insertions(+), 872 deletions(-) diff --git a/jspwiki-main/src/main/java/org/apache/wiki/auth/AuthorizationManager.java b/jspwiki-main/src/main/java/org/apache/wiki/auth/AuthorizationManager.java index 265cef2..a0ab560 100644 --- a/jspwiki-main/src/main/java/org/apache/wiki/auth/AuthorizationManager.java +++ b/jspwiki-main/src/main/java/org/apache/wiki/auth/AuthorizationManager.java @@ -18,382 +18,145 @@ */ package org.apache.wiki.auth; - -import org.apache.log4j.Logger; import org.apache.wiki.WikiContext; -import org.apache.wiki.WikiEngine; -import org.apache.wiki.WikiPage; import org.apache.wiki.WikiSession; -import org.apache.wiki.api.exceptions.NoRequiredPropertyException; +import org.apache.wiki.api.core.Engine; import org.apache.wiki.api.exceptions.WikiException; -import org.apache.wiki.auth.acl.Acl; -import org.apache.wiki.auth.acl.AclEntry; -import org.apache.wiki.auth.acl.UnresolvedPrincipal; import org.apache.wiki.auth.authorize.Role; -import org.apache.wiki.auth.permissions.AllPermission; -import org.apache.wiki.auth.permissions.PagePermission; -import org.apache.wiki.auth.user.UserDatabase; -import org.apache.wiki.auth.user.UserProfile; import org.apache.wiki.event.WikiEventListener; import org.apache.wiki.event.WikiEventManager; import org.apache.wiki.event.WikiSecurityEvent; -import org.apache.wiki.i18n.InternationalizationManager; -import org.apache.wiki.preferences.Preferences; -import org.apache.wiki.util.ClassUtil; -import org.freshcookies.security.policy.LocalPolicy; import javax.servlet.http.HttpServletResponse; -import java.io.File; import java.io.IOException; -import java.net.URL; -import java.security.AccessControlException; -import java.security.AccessController; -import java.security.CodeSource; import java.security.Permission; import java.security.Principal; -import java.security.PrivilegedAction; -import java.security.ProtectionDomain; -import java.security.cert.Certificate; -import java.text.MessageFormat; -import java.util.Arrays; -import java.util.Map; import java.util.Properties; -import java.util.ResourceBundle; -import java.util.WeakHashMap; + /** - * <p>Manages all access control and authorization; determines what authenticated - * users are allowed to do.</p> - * <p>Privileges in JSPWiki are expressed as Java-standard {@link java.security.Permission} - * classes. There are two types of permissions:</p> + * <p>Manages all access control and authorization; determines what authenticated users are allowed to do.</p> + * <p>Privileges in JSPWiki are expressed as Java-standard {@link java.security.Permission} classes. There are two types of permissions:</p> * <ul> - * <li>{@link org.apache.wiki.auth.permissions.WikiPermission} - privileges that apply - * to an entire wiki instance: <em>e.g.,</em> editing user profiles, creating pages, creating groups</li> - * <li>{@link org.apache.wiki.auth.permissions.PagePermission} - privileges that apply - * to a single wiki page or range of pages: <em>e.g.,</em> reading, editing, renaming + * <li>{@link org.apache.wiki.auth.permissions.WikiPermission} - privileges that apply to an entire wiki instance: <em>e.g.,</em> + * editing user profiles, creating pages, creating groups</li> + * <li>{@link org.apache.wiki.auth.permissions.PagePermission} - privileges that apply to a single wiki page or range of pages: + * <em>e.g.,</em> reading, editing, renaming * </ul> - * <p>Calling classes determine whether they are entitled to perform a particular action - * by constructing the appropriate permission first, then passing it and the current - * {@link org.apache.wiki.WikiSession} to the - * {@link #checkPermission(WikiSession, Permission)} method. If the session's - * Subject possesses the permission, the action is allowed.</p> - * <p>For WikiPermissions, the decision criteria is relatively simple: the caller either - * possesses the permission, as granted by the wiki security policy -- or not.</p> - * <p>For PagePermissions, the logic is exactly the same if the page being checked - * does not have an access control list. However, if the page does have an ACL, the - * authorization decision is made based the <em>union</em> of the permissions - * granted in the ACL and in the security policy. In other words, the user must - * be named in the ACL (or belong to a group or role that is named in the ACL) - * <em>and</em> be granted (at least) the same permission in the security policy. We - * do this to prevent a user from gaining more permissions than they already - * have, based on the security policy.</p> - * <p>See the {@link #checkPermission(WikiSession, Permission)} and - * {@link #hasRoleOrPrincipal(WikiSession, Principal)} methods for more information - * on the authorization logic.</p> + * <p>Calling classes determine whether they are entitled to perform a particular action by constructing the appropriate permission first, + * then passing it and the current {@link org.apache.wiki.WikiSession} to the {@link #checkPermission(WikiSession, Permission)} method. If + * the session's Subject possesses the permission, the action is allowed.</p> + * <p>For WikiPermissions, the decision criteria is relatively simple: the caller either possesses the permission, as granted by the wiki + * security policy -- or not.</p> + * <p>For PagePermissions, the logic is exactly the same if the page being checked does not have an access control list. However, if the + * page does have an ACL, the authorization decision is made based the <em>union</em> of the permissions granted in the ACL and in the + * security policy. In other words, the user must be named in the ACL (or belong to a group or role that is named in the ACL) <em>and</em> + * be granted (at least) the same permission in the security policy. We do this to prevent a user from gaining more permissions than they + * already have, based on the security policy.</p> + * <p>See the implementation on {@link #checkPermission(WikiSession, Permission)} method for more information on the authorization logic.</p> + * * @since 2.3 * @see AuthenticationManager */ -public class AuthorizationManager { +public interface AuthorizationManager { - private static final Logger log = Logger.getLogger( AuthorizationManager.class ); - /** - * The default external Authorizer is the {@link org.apache.wiki.auth.authorize.WebContainerAuthorizer} - */ - public static final String DEFAULT_AUTHORIZER = "org.apache.wiki.auth.authorize.WebContainerAuthorizer"; + /** The default external Authorizer is the {@link org.apache.wiki.auth.authorize.WebContainerAuthorizer} */ + String DEFAULT_AUTHORIZER = "org.apache.wiki.auth.authorize.WebContainerAuthorizer"; /** Property that supplies the security policy file name, in WEB-INF. */ - protected static final String POLICY = "jspwiki.policy.file"; + String POLICY = "jspwiki.policy.file"; /** Name of the default security policy file, in WEB-INF. */ - protected static final String DEFAULT_POLICY = "jspwiki.policy"; - - /** - * The property name in jspwiki.properties for specifying the external {@link Authorizer}. - */ - public static final String PROP_AUTHORIZER = "jspwiki.authorizer"; + String DEFAULT_POLICY = "jspwiki.policy"; - private Authorizer m_authorizer = null; - - /** Cache for storing ProtectionDomains used to evaluate the local policy. */ - private Map<Principal, ProtectionDomain> m_cachedPds = new WeakHashMap<>(); - - private WikiEngine m_engine = null; - - private LocalPolicy m_localPolicy = null; + /** The property name in jspwiki.properties for specifying the external {@link Authorizer}. */ + String PROP_AUTHORIZER = "jspwiki.authorizer"; /** - * Constructs a new AuthorizationManager instance. - */ - public AuthorizationManager() - { - } - - /** - * Returns <code>true</code> or <code>false</code>, depending on - * whether a Permission is allowed for the Subject associated with + * Returns <code>true</code> or <code>false</code>, depending on whether a Permission is allowed for the Subject associated with * a supplied WikiSession. The access control algorithm works this way: * <ol> * <li>The {@link org.apache.wiki.auth.acl.Acl} for the page is obtained</li> - * <li>The Subject associated with the current - * {@link org.apache.wiki.WikiSession} is obtained</li> - * <li>If the Subject's Principal set includes the Role Principal that is - * the administrator group, always allow the Permission</li> - * <li>For all permissions, check to see if the Permission is allowed according - * to the default security policy. If it isn't, deny the permission and halt - * further processing.</li> - * <li>If there is an Acl, get the list of Principals assigned this - * Permission in the Acl: these will be role, group or user Principals, or - * {@link org.apache.wiki.auth.acl.UnresolvedPrincipal}s (see below). - * Then iterate through the Subject's Principal set and determine whether - * the user (Subject) possesses any one of these specified Roles or - * Principals. The matching process delegates to - * {@link #hasRoleOrPrincipal(WikiSession, Principal)}. + * <li>The Subject associated with the current {@link org.apache.wiki.WikiSession} is obtained</li> + * <li>If the Subject's Principal set includes the Role Principal that is the administrator group, always allow the Permission</li> + * <li>For all permissions, check to see if the Permission is allowed according to the default security policy. If it isn't, deny + * the permission and halt further processing.</li> + * <li>If there is an Acl, get the list of Principals assigned this Permission in the Acl: these will be role, group or user Principals, + * or {@link org.apache.wiki.auth.acl.UnresolvedPrincipal}s (see below). Then iterate through the Subject's Principal set and determine + * whether the user (Subject) possesses any one of these specified Roles or Principals.</li> * </ol> * <p> - * Note that when iterating through the Acl's list of authorized Principals, - * it is possible that one or more of the Acl's Principal entries are of - * type <code>UnresolvedPrincipal</code>. This means that the last time - * the ACL was read, the Principal (user, built-in Role, authorizer Role, or - * wiki Group) could not be resolved: the Role was not valid, the user - * wasn't found in the UserDatabase, or the Group wasn't known to (e.g., - * cached) in the GroupManager. If an <code>UnresolvedPrincipal</code> is - * encountered, this method will attempt to resolve it first <em>before</em> - * checking to see if the Subject possesses this principal, by calling - * {@link #resolvePrincipal(String)}. If the (re-)resolution does not - * succeed, the access check for the principal will fail by definition (the - * Subject should never contain UnresolvedPrincipals). + * Note that when iterating through the Acl's list of authorized Principals, it is possible that one or more of the Acl's Principal + * entries are of type <code>UnresolvedPrincipal</code>. This means that the last time the ACL was read, the Principal (user, built-in + * Role, authorizer Role, or wiki Group) could not be resolved: the Role was not valid, the user wasn't found in the UserDatabase, or + * the Group wasn't known to (e.g., cached) in the GroupManager. If an <code>UnresolvedPrincipal</code> is encountered, this method + * will attempt to resolve it first <em>before</em> checking to see if the Subject possesses this principal, by calling + * {@link #resolvePrincipal(String)}. If the (re-)resolution does not succeed, the access check for the principal will fail by + * definition (the Subject should never contain UnresolvedPrincipals). * </p> * <p> * If security not set to JAAS, will return true. * </p> + * * @param session the current wiki session * @param permission the Permission being checked - * @see #hasRoleOrPrincipal(WikiSession, Principal) * @return the result of the Permission check */ - public boolean checkPermission( final WikiSession session, final Permission permission ) - { - // - // A slight sanity check. - // - if ( session == null || permission == null ) - { - fireEvent( WikiSecurityEvent.ACCESS_DENIED, null, permission ); - return false; - } - - final Principal user = session.getLoginPrincipal(); - - // Always allow the action if user has AllPermission - final Permission allPermission = new AllPermission( m_engine.getApplicationName() ); - final boolean hasAllPermission = checkStaticPermission( session, allPermission ); - if ( hasAllPermission ) - { - fireEvent( WikiSecurityEvent.ACCESS_ALLOWED, user, permission ); - return true; - } - - // If the user doesn't have *at least* the permission - // granted by policy, return false. - final boolean hasPolicyPermission = checkStaticPermission( session, permission ); - if ( !hasPolicyPermission ) - { - fireEvent( WikiSecurityEvent.ACCESS_DENIED, user, permission ); - return false; - } - - // If this isn't a PagePermission, it's allowed - if ( ! ( permission instanceof PagePermission ) ) - { - fireEvent( WikiSecurityEvent.ACCESS_ALLOWED, user, permission ); - return true; - } - - // - // If the page or ACL is null, it's allowed. - // - final String pageName = ((PagePermission)permission).getPage(); - final WikiPage page = m_engine.getPageManager().getPage( pageName ); - final Acl acl = ( page == null) ? null : m_engine.getAclManager().getPermissions( page ); - if ( page == null || acl == null || acl.isEmpty() ) - { - fireEvent( WikiSecurityEvent.ACCESS_ALLOWED, user, permission ); - return true; - } - - // - // Next, iterate through the Principal objects assigned - // this permission. If the context's subject possesses - // any of these, the action is allowed. - - final Principal[] aclPrincipals = acl.findPrincipals( permission ); - - log.debug( "Checking ACL entries..." ); - log.debug( "Acl for this page is: " + acl ); - log.debug( "Checking for principal: " + Arrays.toString( aclPrincipals ) ); - log.debug( "Permission: " + permission ); - - for( Principal aclPrincipal : aclPrincipals ) - { - // If the ACL principal we're looking at is unresolved, - // try to resolve it here & correct the Acl - if ( aclPrincipal instanceof UnresolvedPrincipal ) - { - final AclEntry aclEntry = acl.getEntry( aclPrincipal ); - aclPrincipal = resolvePrincipal( aclPrincipal.getName() ); - if ( aclEntry != null && !( aclPrincipal instanceof UnresolvedPrincipal ) ) - { - aclEntry.setPrincipal( aclPrincipal ); - } - } - - if ( hasRoleOrPrincipal( session, aclPrincipal ) ) - { - fireEvent( WikiSecurityEvent.ACCESS_ALLOWED, user, permission ); - return true; - } - } - fireEvent( WikiSecurityEvent.ACCESS_DENIED, user, permission ); - return false; - } + boolean checkPermission( WikiSession session, Permission permission ); /** - * <p>Determines if the Subject associated with a - * supplied WikiSession contains a desired Role or GroupPrincipal. - * The algorithm simply checks to see if the Subject possesses - * the Role or GroupPrincipal it in its Principal set. Note that - * any user (anonymous, asserted, authenticated) can possess - * a built-in role. But a user <em>must</em> be authenticated to - * possess a role other than one of the built-in ones. - * We do this to prevent privilege escalation.</p> + * <p>Determines if the Subject associated with a supplied WikiSession contains a desired Role or GroupPrincipal. The algorithm + * simply checks to see if the Subject possesses the Role or GroupPrincipal it in its Principal set. Note that any user (anonymous, + * asserted, authenticated) can possess a built-in role. But a user <em>must</em> be authenticated to possess a role other than one + * of the built-in ones. We do this to prevent privilege escalation.</p> * <p>For all other cases, this method returns <code>false</code>.</p> - * <p>Note that this method does <em>not</em> consult the external - * Authorizer or GroupManager; it relies on the Principals that - * have been injected into the user's Subject at login time, or - * after group creation/modification/deletion.</p> - * @param session the current wiki session, which must be non-null. If null, - * the result of this method always returns <code>false</code> - * @param principal the Principal (role or group principal) to look - * for, which must be non-<code>null</code>. If <code>null</code>, - * the result of this method always returns <code>false</code> - * @return <code>true</code> if the Subject supplied with the WikiContext - * posesses the Role or GroupPrincipal, <code>false</code> otherwise + * <p>Note that this method does <em>not</em> consult the external Authorizer or GroupManager; it relies on the Principals that + * have been injected into the user's Subject at login time, or after group creation/modification/deletion.</p> + * + * @param session the current wiki session, which must be non-null. If null, the result of this method always returns <code>false</code> + * @param principal the Principal (role or group principal) to look for, which must be non-<code>null</code>. If <code>null</code>, + * the result of this method always returns <code>false</code> + * @return <code>true</code> if the Subject supplied with the WikiContext posesses the Role or GroupPrincipal, <code>false</code> otherwise */ - public boolean isUserInRole( final WikiSession session, final Principal principal ) - { - if ( session == null || principal == null || - AuthenticationManager.isUserPrincipal( principal ) ) - { + default boolean isUserInRole( final WikiSession session, final Principal principal ) { + if ( session == null || principal == null || AuthenticationManager.isUserPrincipal( principal ) ) { return false; } // Any type of user can possess a built-in role - if ( principal instanceof Role && Role.isBuiltInRole( (Role)principal ) ) - { + if ( principal instanceof Role && Role.isBuiltInRole( (Role)principal ) ) { return session.hasPrincipal( principal ); } // Only authenticated users can possess groups or custom roles - if ( session.isAuthenticated() && AuthenticationManager.isRolePrincipal( principal ) ) - { + if ( session.isAuthenticated() && AuthenticationManager.isRolePrincipal( principal ) ) { return session.hasPrincipal( principal ); } return false; } /** - * Returns the current external {@link Authorizer} in use. This method - * is guaranteed to return a properly-initialized Authorizer, unless - * it could not be initialized. In that case, this method throws - * a {@link org.apache.wiki.auth.WikiSecurityException}. - * @throws org.apache.wiki.auth.WikiSecurityException if the Authorizer could - * not be initialized + * Returns the current external {@link Authorizer} in use. This method is guaranteed to return a properly-initialized Authorizer, unless + * it could not be initialized. In that case, this method throws a {@link org.apache.wiki.auth.WikiSecurityException}. + * + * @throws org.apache.wiki.auth.WikiSecurityException if the Authorizer could not be initialized * @return the current Authorizer */ - public Authorizer getAuthorizer() throws WikiSecurityException - { - if ( m_authorizer != null ) - { - return m_authorizer; - } - throw new WikiSecurityException( "Authorizer did not initialize properly. Check the logs." ); - } - - /** - * <p>Determines if the Subject associated with a supplied WikiSession contains - * a desired user Principal or built-in Role principal, OR is a member a - * Group or external Role. The rules are as follows:</p> - * <ol> - * <li>First, if desired Principal is a Role or GroupPrincipal, delegate to - * {@link #isUserInRole(WikiSession, Principal)} and - * return the result.</li> - * <li>Otherwise, we're looking for a user Principal, - * so iterate through the Principal set and see if - * any share the same name as the one we are looking for.</li> - * </ol> - * <p><em>Note: if the Principal parameter is a user principal, the session - * must be authenticated in order for the user to "possess it". Anonymous - * or asserted sessions will never posseess a named user principal.</em></p> - * @param session the current wiki session, which must be non-null. If null, - * the result of this method always returns <code>false</code> - * @param principal the Principal (role, group, or user principal) to look - * for, which must be non-null. If null, the result of this - * method always returns <code>false</code> - * @return <code>true</code> if the Subject supplied with the WikiContext - * posesses the Role, GroupPrincipal or desired - * user Principal, <code>false</code> otherwise - */ - protected boolean hasRoleOrPrincipal( final WikiSession session, final Principal principal ) - { - // If either parameter is null, always deny - if( session == null || principal == null ) - { - return false; - } - - // If principal is role, delegate to isUserInRole - if( AuthenticationManager.isRolePrincipal( principal ) ) - { - return isUserInRole( session, principal ); - } - - // We must be looking for a user principal, assuming that the user - // has been properly logged in. - // So just look for a name match. - if( session.isAuthenticated() && AuthenticationManager.isUserPrincipal( principal ) ) - { - final String principalName = principal.getName(); - final Principal[] userPrincipals = session.getPrincipals(); - for( final Principal userPrincipal : userPrincipals ) - { - if( userPrincipal.getName().equals( principalName ) ) - { - return true; - } - } - } - return false; - } + Authorizer getAuthorizer() throws WikiSecurityException; /** - * Checks whether the current user has access to the wiki context, - * by obtaining the required Permission ({@link WikiContext#requiredPermission()}) - * and delegating the access check to {@link #checkPermission(WikiSession, Permission)}. - * If the user is allowed, this method returns <code>true</code>; - * <code>false</code> otherwise. If access is allowed, - * the wiki context will be added to the request as an attribute - * with the key name {@link org.apache.wiki.WikiContext#ATTR_CONTEXT}. - * Note that this method will automatically redirect the user to - * a login or error page, as appropriate, if access fails. This is - * NOT guaranteed to be default behavior in the future. + * Checks whether the current user has access to the wiki context, by obtaining the required Permission ({@link WikiContext#requiredPermission()}) + * and delegating the access check to {@link #checkPermission(WikiSession, Permission)}. If the user is allowed, this method returns + * <code>true</code>; <code>false</code> otherwise. If access is allowed, the wiki context will be added to the request as an attribute + * with the key name {@link org.apache.wiki.WikiContext#ATTR_CONTEXT}. Note that this method will automatically redirect the user to + * a login or error page, as appropriate, if access fails. This is NOT guaranteed to be default behavior in the future. * * @param context wiki context to check if it is accesible * @param response the http response * @return the result of the access check * @throws IOException In case something goes wrong */ - public boolean hasAccess( final WikiContext context, final HttpServletResponse response ) throws IOException - { + default boolean hasAccess( final WikiContext context, final HttpServletResponse response ) throws IOException { return hasAccess( context, response, true ); } @@ -411,294 +174,63 @@ public class AuthorizationManager { * @return the result of the access check * @throws IOException If something goes wrong */ - public boolean hasAccess( final WikiContext context, final HttpServletResponse response, final boolean redirect ) throws IOException { - final boolean allowed = checkPermission( context.getWikiSession(), context.requiredPermission() ); - final ResourceBundle rb = Preferences.getBundle( context, InternationalizationManager.CORE_BUNDLE ); - - // Stash the wiki context - if ( context.getHttpRequest() != null && context.getHttpRequest().getAttribute( WikiContext.ATTR_CONTEXT ) == null ) { - context.getHttpRequest().setAttribute( WikiContext.ATTR_CONTEXT, context ); - } - - // If access not allowed, redirect - if( !allowed && redirect ) { - final Principal currentUser = context.getWikiSession().getUserPrincipal(); - final String pageurl = context.getPage().getName(); - if( context.getWikiSession().isAuthenticated() ) { - log.info("User "+currentUser.getName()+" has no access - forbidden (permission=" + context.requiredPermission() + ")" ); - context.getWikiSession().addMessage( MessageFormat.format( rb.getString( "security.error.noaccess.logged" ), - context.getName()) ); - } else { - log.info("User "+currentUser.getName()+" has no access - redirecting (permission=" + context.requiredPermission() + ")"); - context.getWikiSession().addMessage( MessageFormat.format( rb.getString("security.error.noaccess"), context.getName() ) ); - } - response.sendRedirect( m_engine.getURL(WikiContext.LOGIN, pageurl, null ) ); - } - return allowed; - } + boolean hasAccess( final WikiContext context, final HttpServletResponse response, final boolean redirect ) throws IOException; /** - * Initializes AuthorizationManager with an engine and set of properties. - * Expects to find property 'jspwiki.authorizer' with a valid Authorizer - * implementation name to take care of role lookup operations. + * Initializes AuthorizationManager with an engine and set of properties. Expects to find property 'jspwiki.authorizer' with a valid + * Authorizer implementation name to take care of role lookup operations. + * * @param engine the wiki engine * @param properties the set of properties used to initialize the wiki engine * @throws WikiException if the AuthorizationManager cannot be initialized */ - public void initialize( final WikiEngine engine, final Properties properties ) throws WikiException { - m_engine = engine; - - // - // JAAS authorization continues - // - m_authorizer = getAuthorizerImplementation( properties ); - m_authorizer.initialize( engine, properties ); - - // Initialize local security policy - try { - final String policyFileName = properties.getProperty( POLICY, DEFAULT_POLICY ); - final URL policyURL = engine.findConfigFile( policyFileName ); - - if (policyURL != null) { - final File policyFile = new File( policyURL.toURI().getPath() ); - log.info("We found security policy URL: " + policyURL + " and transformed it to file " + policyFile.getAbsolutePath()); - m_localPolicy = new LocalPolicy( policyFile, engine.getContentEncoding().displayName() ); - m_localPolicy.refresh(); - log.info( "Initialized default security policy: " + policyFile.getAbsolutePath() ); - } else { - final String sb = "JSPWiki was unable to initialize the default security policy (WEB-INF/jspwiki.policy) file. " + - "Please ensure that the jspwiki.policy file exists in the default location. " + - "This file should exist regardless of the existance of a global policy file. " + - "The global policy file is identified by the java.security.policy variable. "; - final WikiSecurityException wse = new WikiSecurityException( sb ); - log.fatal( sb, wse ); - throw wse; - } - } catch ( final Exception e) { - log.error("Could not initialize local security policy: " + e.getMessage() ); - throw new WikiException( "Could not initialize local security policy: " + e.getMessage(), e ); - } - } - - /** - * Attempts to locate and initialize a Authorizer to use with this manager. - * Throws a WikiException if no entry is found, or if one fails to - * initialize. - * @param props jspwiki.properties, containing a - * 'jspwiki.authorization.provider' class name - * @return a Authorizer used to get page authorization information - * @throws WikiException - */ - private Authorizer getAuthorizerImplementation( final Properties props ) throws WikiException { - final String authClassName = props.getProperty( PROP_AUTHORIZER, DEFAULT_AUTHORIZER ); - return ( Authorizer )locateImplementation( authClassName ); - } - - private Object locateImplementation( final String clazz ) throws WikiException { - if ( clazz != null ) { - try { - final Class< ? > authClass = ClassUtil.findClass( "org.apache.wiki.auth.authorize", clazz ); - final Object impl = authClass.newInstance(); - return impl; - } catch( final ClassNotFoundException e ) { - log.fatal( "Authorizer " + clazz + " cannot be found", e ); - throw new WikiException( "Authorizer " + clazz + " cannot be found", e ); - } catch( final InstantiationException e ) { - log.fatal( "Authorizer " + clazz + " cannot be created", e ); - throw new WikiException( "Authorizer " + clazz + " cannot be created", e ); - } catch( final IllegalAccessException e ) { - log.fatal( "You are not allowed to access this authorizer class", e ); - throw new WikiException( "You are not allowed to access this authorizer class", e ); - } - } - - throw new NoRequiredPropertyException( "Unable to find a " + PROP_AUTHORIZER + " entry in the properties.", - PROP_AUTHORIZER ); - } - - /** - * Checks to see if the local security policy allows a particular static Permission. - * Do not use this method for normal permission checks; use - * {@link #checkPermission(WikiSession, Permission)} instead. - * @param principals the Principals to check - * @param permission the Permission - * @return the result - */ - protected boolean allowedByLocalPolicy( final Principal[] principals, final Permission permission ) - { - for ( final Principal principal : principals ) - { - // Get ProtectionDomain for this Principal from cache, or create new one - ProtectionDomain pd = m_cachedPds.get( principal ); - if ( pd == null ) - { - final ClassLoader cl = this.getClass().getClassLoader(); - final CodeSource cs = new CodeSource( null, (Certificate[])null ); - pd = new ProtectionDomain( cs, null, cl, new Principal[]{ principal } ); - m_cachedPds.put( principal, pd ); - } - - // Consult the local policy and get the answer - if ( m_localPolicy.implies( pd, permission ) ) - { - return true; - } - } - return false; - } + void initialize( final Engine engine, final Properties properties ) throws WikiException; /** - * Determines whether a Subject possesses a given "static" Permission as - * defined in the security policy file. This method uses standard Java 2 - * security calls to do its work. Note that the current access control - * context's <code>codeBase</code> is effectively <em>this class</em>, - * not that of the caller. Therefore, this method will work best when what - * matters in the policy is <em>who</em> makes the permission check, not - * what the caller's code source is. Internally, this method works by - * executing <code>Subject.doAsPrivileged</code> with a privileged action - * that simply calls {@link java.security.AccessController#checkPermission(Permission)}. - * @see AccessController#checkPermission(java.security.Permission) . A - * caught exception (or lack thereof) determines whether the privilege - * is absent (or present). - * @param session the WikiSession whose permission status is being queried - * @param permission the Permission the Subject must possess - * @return <code>true</code> if the Subject possesses the permission, - * <code>false</code> otherwise - */ - protected boolean checkStaticPermission( final WikiSession session, final Permission permission ) - { - final Boolean allowed = (Boolean) WikiSession.doPrivileged( session, new PrivilegedAction<Boolean>() - { - @Override public Boolean run() - { - try - { - // Check the JVM-wide security policy first - AccessController.checkPermission( permission ); - return Boolean.TRUE; - } - catch( final AccessControlException e ) - { - // Global policy denied the permission - } - - // Try the local policy - check each Role/Group and User Principal - if ( allowedByLocalPolicy( session.getRoles(), permission ) || - allowedByLocalPolicy( session.getPrincipals(), permission ) ) - { - return Boolean.TRUE; - } - return Boolean.FALSE; - } - } ); - return allowed.booleanValue(); - } - - /** - * <p>Given a supplied string representing a Principal's name from an Acl, this - * method resolves the correct type of Principal (role, group, or user). - * This method is guaranteed to always return a Principal. - * The algorithm is straightforward:</p> + * <p>Given a supplied string representing a Principal's name from an Acl, this method resolves the correct type of Principal (role, + * group, or user). This method is guaranteed to always return a Principal. The algorithm is straightforward:</p> * <ol> - * <li>If the name matches one of the built-in {@link org.apache.wiki.auth.authorize.Role} names, - * return that built-in Role</li> - * <li>If the name matches one supplied by the current - * {@link org.apache.wiki.auth.Authorizer}, return that Role</li> - * <li>If the name matches a group managed by the - * current {@link org.apache.wiki.auth.authorize.GroupManager}, return that Group</li> - * <li>Otherwise, assume that the name represents a user - * principal. Using the current {@link org.apache.wiki.auth.user.UserDatabase}, find the - * first user who matches the supplied name by calling - * {@link org.apache.wiki.auth.user.UserDatabase#find(String)}.</li> - * <li>Finally, if a user cannot be found, manufacture - * and return a generic {@link org.apache.wiki.auth.acl.UnresolvedPrincipal}</li> + * <li>If the name matches one of the built-in {@link org.apache.wiki.auth.authorize.Role} names, return that built-in Role</li> + * <li>If the name matches one supplied by the current {@link org.apache.wiki.auth.Authorizer}, return that Role</li> + * <li>If the name matches a group managed by the current {@link org.apache.wiki.auth.authorize.GroupManager}, return that Group</li> + * <li>Otherwise, assume that the name represents a user principal. Using the current {@link org.apache.wiki.auth.user.UserDatabase}, + * find the first user who matches the supplied name by calling {@link org.apache.wiki.auth.user.UserDatabase#find(String)}.</li> + * <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 * @return the fully-resolved Principal */ - public Principal resolvePrincipal( final String name ) - { - // Check built-in Roles first - final Role role = new Role(name); - if ( Role.isBuiltInRole( role ) ) - { - return role; - } - - // Check Authorizer Roles - Principal principal = m_authorizer.findRole( name ); - if ( principal != null ) - { - return principal; - } - - // Check Groups - principal = m_engine.getGroupManager().findRole( name ); - if ( principal != null ) - { - return principal; - } - - // Ok, no luck---this must be a user principal - Principal[] principals = null; - UserProfile profile = null; - final UserDatabase db = m_engine.getUserManager().getUserDatabase(); - try - { - profile = db.find( name ); - principals = db.getPrincipals( profile.getLoginName() ); - for (int i = 0; i < principals.length; i++) - { - principal = principals[i]; - if ( principal.getName().equals( name ) ) - { - return principal; - } - } - } - catch( final NoSuchPrincipalException e ) - { - // We couldn't find the user... - } - // Ok, no luck---mark this as unresolved and move on - return new UnresolvedPrincipal( name ); - } + Principal resolvePrincipal( final String name ); // events processing ....................................................... /** * Registers a WikiEventListener with this instance. + * * @param listener the event listener */ - public synchronized void addWikiEventListener( final WikiEventListener listener ) - { - WikiEventManager.addWikiEventListener( this, listener ); - } + void addWikiEventListener( WikiEventListener listener ); /** * Un-registers a WikiEventListener with this instance. + * * @param listener the event listener */ - public synchronized void removeWikiEventListener( final WikiEventListener listener ) - { - WikiEventManager.removeWikiEventListener( this, listener ); - } + void removeWikiEventListener( final WikiEventListener listener ); /** - * Fires a WikiSecurityEvent of the provided type, user, - * and permission to all registered listeners. + * Fires a WikiSecurityEvent of the provided type, user, and permission to all registered listeners. * * @see org.apache.wiki.event.WikiSecurityEvent * @param type the event type to be fired * @param user the user associated with the event * @param permission the permission the subject must possess */ - protected void fireEvent( final int type, final Principal user, final Object permission ) - { - if ( WikiEventManager.isListening(this) ) - { - WikiEventManager.fireEvent(this,new WikiSecurityEvent(this,type,user,permission)); + default void fireEvent( final int type, final Principal user, final Object permission ) { + if( WikiEventManager.isListening( this ) ) { + WikiEventManager.fireEvent( this, new WikiSecurityEvent( this, type, user, permission ) ); } } diff --git a/jspwiki-main/src/main/java/org/apache/wiki/auth/Authorizer.java b/jspwiki-main/src/main/java/org/apache/wiki/auth/Authorizer.java index 36d44c2..13f82c2 100644 --- a/jspwiki-main/src/main/java/org/apache/wiki/auth/Authorizer.java +++ b/jspwiki-main/src/main/java/org/apache/wiki/auth/Authorizer.java @@ -18,11 +18,12 @@ */ package org.apache.wiki.auth; +import org.apache.wiki.WikiSession; +import org.apache.wiki.api.core.Engine; + import java.security.Principal; import java.util.Properties; -import org.apache.wiki.WikiEngine; -import org.apache.wiki.WikiSession; /** * Interface for service providers of authorization information. After a user @@ -43,8 +44,7 @@ import org.apache.wiki.WikiSession; * * @since 2.3 */ -public interface Authorizer -{ +public interface Authorizer { /** * Returns an array of role Principals this Authorizer knows about. This @@ -74,7 +74,7 @@ public interface Authorizer * @param props the wiki engine initialization properties * @throws WikiSecurityException if the Authorizer could not be initialized */ - void initialize( WikiEngine engine, Properties props ) throws WikiSecurityException; + void initialize( Engine engine, Properties props ) throws WikiSecurityException; /** * Determines whether the Subject associated with a WikiSession is in a diff --git a/jspwiki-main/src/main/java/org/apache/wiki/auth/DefaultAuthorizationManager.java b/jspwiki-main/src/main/java/org/apache/wiki/auth/DefaultAuthorizationManager.java new file mode 100644 index 0000000..a388a08 --- /dev/null +++ b/jspwiki-main/src/main/java/org/apache/wiki/auth/DefaultAuthorizationManager.java @@ -0,0 +1,425 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. 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. + */ +package org.apache.wiki.auth; + +import org.apache.log4j.Logger; +import org.apache.wiki.WikiContext; +import org.apache.wiki.WikiPage; +import org.apache.wiki.WikiSession; +import org.apache.wiki.api.core.Engine; +import org.apache.wiki.api.exceptions.NoRequiredPropertyException; +import org.apache.wiki.api.exceptions.WikiException; +import org.apache.wiki.auth.acl.Acl; +import org.apache.wiki.auth.acl.AclEntry; +import org.apache.wiki.auth.acl.AclManager; +import org.apache.wiki.auth.acl.UnresolvedPrincipal; +import org.apache.wiki.auth.authorize.GroupManager; +import org.apache.wiki.auth.authorize.Role; +import org.apache.wiki.auth.permissions.AllPermission; +import org.apache.wiki.auth.permissions.PagePermission; +import org.apache.wiki.auth.user.UserDatabase; +import org.apache.wiki.auth.user.UserProfile; +import org.apache.wiki.event.WikiEventListener; +import org.apache.wiki.event.WikiEventManager; +import org.apache.wiki.event.WikiSecurityEvent; +import org.apache.wiki.i18n.InternationalizationManager; +import org.apache.wiki.pages.PageManager; +import org.apache.wiki.preferences.Preferences; +import org.apache.wiki.util.ClassUtil; +import org.freshcookies.security.policy.LocalPolicy; + +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.security.AccessControlException; +import java.security.AccessController; +import java.security.CodeSource; +import java.security.Permission; +import java.security.Principal; +import java.security.PrivilegedAction; +import java.security.ProtectionDomain; +import java.security.cert.Certificate; +import java.text.MessageFormat; +import java.util.Arrays; +import java.util.Map; +import java.util.Properties; +import java.util.ResourceBundle; +import java.util.WeakHashMap; + + +/** + * <p>Default implementation for {@link AuthorizationManager}</p> + * {@inheritDoc} + * + * <p>See the {@link #checkPermission(WikiSession, Permission)} and {@link #hasRoleOrPrincipal(WikiSession, Principal)} methods for more + * information on the authorization logic.</p> + * @since 2.3 + * @see AuthenticationManager + */ +public class DefaultAuthorizationManager implements AuthorizationManager { + + private static final Logger log = Logger.getLogger( DefaultAuthorizationManager.class ); + + private Authorizer m_authorizer = null; + + /** Cache for storing ProtectionDomains used to evaluate the local policy. */ + private Map< Principal, ProtectionDomain > m_cachedPds = new WeakHashMap<>(); + + private Engine m_engine = null; + + private LocalPolicy m_localPolicy = null; + + /** + * Constructs a new DefaultAuthorizationManager instance. + */ + public DefaultAuthorizationManager() { + } + + /** {@inheritDoc} */ + @Override + public boolean checkPermission( final WikiSession session, final Permission permission ) { + // A slight sanity check. + if( session == null || permission == null ) { + fireEvent( WikiSecurityEvent.ACCESS_DENIED, null, permission ); + return false; + } + + final Principal user = session.getLoginPrincipal(); + + // Always allow the action if user has AllPermission + final Permission allPermission = new AllPermission( m_engine.getApplicationName() ); + final boolean hasAllPermission = checkStaticPermission( session, allPermission ); + if( hasAllPermission ) { + fireEvent( WikiSecurityEvent.ACCESS_ALLOWED, user, permission ); + return true; + } + + // If the user doesn't have *at least* the permission granted by policy, return false. + final boolean hasPolicyPermission = checkStaticPermission( session, permission ); + if( !hasPolicyPermission ) { + fireEvent( WikiSecurityEvent.ACCESS_DENIED, user, permission ); + return false; + } + + // If this isn't a PagePermission, it's allowed + if( !( permission instanceof PagePermission ) ) { + fireEvent( WikiSecurityEvent.ACCESS_ALLOWED, user, permission ); + return true; + } + + // If the page or ACL is null, it's allowed. + final String pageName = ((PagePermission)permission).getPage(); + final WikiPage page = m_engine.getManager( PageManager.class ).getPage( pageName ); + final Acl acl = ( page == null) ? null : m_engine.getManager( AclManager.class ).getPermissions( page ); + if( page == null || acl == null || acl.isEmpty() ) { + fireEvent( WikiSecurityEvent.ACCESS_ALLOWED, user, permission ); + return true; + } + + // Next, iterate through the Principal objects assigned this permission. If the context's subject possesses + // any of these, the action is allowed. + final Principal[] aclPrincipals = acl.findPrincipals( permission ); + + log.debug( "Checking ACL entries..." ); + log.debug( "Acl for this page is: " + acl ); + log.debug( "Checking for principal: " + Arrays.toString( aclPrincipals ) ); + log.debug( "Permission: " + permission ); + + for( Principal aclPrincipal : aclPrincipals ) { + // If the ACL principal we're looking at is unresolved, try to resolve it here & correct the Acl + if ( aclPrincipal instanceof UnresolvedPrincipal ) { + final AclEntry aclEntry = acl.getEntry( aclPrincipal ); + aclPrincipal = resolvePrincipal( aclPrincipal.getName() ); + if ( aclEntry != null && !( aclPrincipal instanceof UnresolvedPrincipal ) ) { + aclEntry.setPrincipal( aclPrincipal ); + } + } + + if ( hasRoleOrPrincipal( session, aclPrincipal ) ) { + fireEvent( WikiSecurityEvent.ACCESS_ALLOWED, user, permission ); + return true; + } + } + fireEvent( WikiSecurityEvent.ACCESS_DENIED, user, permission ); + return false; + } + + /** {@inheritDoc} */ + @Override + public Authorizer getAuthorizer() throws WikiSecurityException { + if ( m_authorizer != null ) { + return m_authorizer; + } + throw new WikiSecurityException( "Authorizer did not initialize properly. Check the logs." ); + } + + /** + * <p>Determines if the Subject associated with a supplied WikiSession contains a desired user Principal or built-in Role principal, + * OR is a member a Group or external Role. The rules are as follows:</p> + * <ol> + * <li>First, if desired Principal is a Role or GroupPrincipal, delegate to {@link #isUserInRole(WikiSession, Principal)} and + * return the result.</li> + * <li>Otherwise, we're looking for a user Principal, so iterate through the Principal set and see if any share the same name as the + * one we are looking for.</li> + * </ol> + * <p><em>Note: if the Principal parameter is a user principal, the session must be authenticated in order for the user to "possess it". + * Anonymous or asserted sessions will never posseess a named user principal.</em></p> + * + * @param session the current wiki session, which must be non-null. If null, the result of this method always returns <code>false</code> + * @param principal the Principal (role, group, or user principal) to look for, which must be non-null. If null, the result of this + * method always returns <code>false</code> + * @return <code>true</code> if the Subject supplied with the WikiContext posesses the Role, GroupPrincipal or desired + * user Principal, <code>false</code> otherwise + */ + protected boolean hasRoleOrPrincipal( final WikiSession session, final Principal principal ) { + // If either parameter is null, always deny + if( session == null || principal == null ) { + return false; + } + + // If principal is role, delegate to isUserInRole + if( AuthenticationManager.isRolePrincipal( principal ) ) { + return isUserInRole( session, principal ); + } + + // We must be looking for a user principal, assuming that the user has been properly logged in. So just look for a name match. + if( session.isAuthenticated() && AuthenticationManager.isUserPrincipal( principal ) ) { + final String principalName = principal.getName(); + final Principal[] userPrincipals = session.getPrincipals(); + for( final Principal userPrincipal : userPrincipals ) { + if( userPrincipal.getName().equals( principalName ) ) { + return true; + } + } + } + return false; + } + + /** {@inheritDoc} */ + @Override + public boolean hasAccess( final WikiContext context, final HttpServletResponse response, final boolean redirect ) throws IOException { + final boolean allowed = checkPermission( context.getWikiSession(), context.requiredPermission() ); + final ResourceBundle rb = Preferences.getBundle( context, InternationalizationManager.CORE_BUNDLE ); + + // Stash the wiki context + if ( context.getHttpRequest() != null && context.getHttpRequest().getAttribute( WikiContext.ATTR_CONTEXT ) == null ) { + context.getHttpRequest().setAttribute( WikiContext.ATTR_CONTEXT, context ); + } + + // If access not allowed, redirect + if( !allowed && redirect ) { + final Principal currentUser = context.getWikiSession().getUserPrincipal(); + final String pageurl = context.getPage().getName(); + if( context.getWikiSession().isAuthenticated() ) { + log.info( "User " + currentUser.getName() + " has no access - forbidden (permission=" + context.requiredPermission() + ")" ); + context.getWikiSession().addMessage( MessageFormat.format( rb.getString( "security.error.noaccess.logged" ), + context.getName()) ); + } else { + log.info( "User " + currentUser.getName() + " has no access - redirecting (permission=" + context.requiredPermission() + ")" ); + context.getWikiSession().addMessage( MessageFormat.format( rb.getString("security.error.noaccess"), context.getName() ) ); + } + response.sendRedirect( m_engine.getURL(WikiContext.LOGIN, pageurl, null ) ); + } + return allowed; + } + + /** {@inheritDoc} */ + @Override + public void initialize( final Engine engine, final Properties properties ) throws WikiException { + m_engine = engine; + + // JAAS authorization continues + m_authorizer = getAuthorizerImplementation( properties ); + m_authorizer.initialize( engine, properties ); + + // Initialize local security policy + try { + final String policyFileName = properties.getProperty( POLICY, DEFAULT_POLICY ); + final URL policyURL = engine.findConfigFile( policyFileName ); + + if (policyURL != null) { + final File policyFile = new File( policyURL.toURI().getPath() ); + log.info("We found security policy URL: " + policyURL + " and transformed it to file " + policyFile.getAbsolutePath()); + m_localPolicy = new LocalPolicy( policyFile, engine.getContentEncoding().displayName() ); + m_localPolicy.refresh(); + log.info( "Initialized default security policy: " + policyFile.getAbsolutePath() ); + } else { + final String sb = "JSPWiki was unable to initialize the default security policy (WEB-INF/jspwiki.policy) file. " + + "Please ensure that the jspwiki.policy file exists in the default location. " + + "This file should exist regardless of the existance of a global policy file. " + + "The global policy file is identified by the java.security.policy variable. "; + final WikiSecurityException wse = new WikiSecurityException( sb ); + log.fatal( sb, wse ); + throw wse; + } + } catch ( final Exception e) { + log.error("Could not initialize local security policy: " + e.getMessage() ); + throw new WikiException( "Could not initialize local security policy: " + e.getMessage(), e ); + } + } + + /** + * Attempts to locate and initialize a Authorizer to use with this manager. Throws a WikiException if no entry is found, or if one + * fails to initialize. + * + * @param props jspwiki.properties, containing a 'jspwiki.authorization.provider' class name. + * @return a Authorizer used to get page authorization information. + * @throws WikiException if there are problems finding the authorizer implementation. + */ + private Authorizer getAuthorizerImplementation( final Properties props ) throws WikiException { + final String authClassName = props.getProperty( PROP_AUTHORIZER, DEFAULT_AUTHORIZER ); + return ( Authorizer )locateImplementation( authClassName ); + } + + private Object locateImplementation( final String clazz ) throws WikiException { + if ( clazz != null ) { + try { + final Class< ? > authClass = ClassUtil.findClass( "org.apache.wiki.auth.authorize", clazz ); + return authClass.newInstance(); + } catch( final ClassNotFoundException e ) { + log.fatal( "Authorizer " + clazz + " cannot be found", e ); + throw new WikiException( "Authorizer " + clazz + " cannot be found", e ); + } catch( final InstantiationException e ) { + log.fatal( "Authorizer " + clazz + " cannot be created", e ); + throw new WikiException( "Authorizer " + clazz + " cannot be created", e ); + } catch( final IllegalAccessException e ) { + log.fatal( "You are not allowed to access this authorizer class", e ); + throw new WikiException( "You are not allowed to access this authorizer class", e ); + } + } + + throw new NoRequiredPropertyException( "Unable to find a " + PROP_AUTHORIZER + " entry in the properties.", PROP_AUTHORIZER ); + } + + /** + * Checks to see if the local security policy allows a particular static Permission. + * Do not use this method for normal permission checks; use {@link #checkPermission(WikiSession, Permission)} instead. + * + * @param principals the Principals to check + * @param permission the Permission + * @return the result + */ + protected boolean allowedByLocalPolicy( final Principal[] principals, final Permission permission ) { + for ( final Principal principal : principals ) { + // Get ProtectionDomain for this Principal from cache, or create new one + ProtectionDomain pd = m_cachedPds.get( principal ); + if ( pd == null ) { + final ClassLoader cl = this.getClass().getClassLoader(); + final CodeSource cs = new CodeSource( null, (Certificate[])null ); + pd = new ProtectionDomain( cs, null, cl, new Principal[]{ principal } ); + m_cachedPds.put( principal, pd ); + } + + // Consult the local policy and get the answer + if ( m_localPolicy.implies( pd, permission ) ) { + return true; + } + } + return false; + } + + /** + * Determines whether a Subject possesses a given "static" Permission as defined in the security policy file. This method uses standard + * Java 2 security calls to do its work. Note that the current access control context's <code>codeBase</code> is effectively <em>this + * class</em>, not that of the caller. Therefore, this method will work best when what matters in the policy is <em>who</em> makes the + * permission check, not what the caller's code source is. Internally, this method works by executing <code>Subject.doAsPrivileged</code> + * with a privileged action that simply calls {@link AccessController#checkPermission(Permission)}. + * + * @see AccessController#checkPermission(Permission) . A caught exception (or lack thereof) determines whether the + * privilege is absent (or present). + * @param session the WikiSession whose permission status is being queried + * @param permission the Permission the Subject must possess + * @return <code>true</code> if the Subject possesses the permission, <code>false</code> otherwise + */ + protected boolean checkStaticPermission( final WikiSession session, final Permission permission ) { + return ( Boolean )WikiSession.doPrivileged( session, ( PrivilegedAction< Boolean > )() -> { + try { + // Check the JVM-wide security policy first + AccessController.checkPermission( permission ); + return Boolean.TRUE; + } catch( final AccessControlException e ) { + // Global policy denied the permission + } + + // Try the local policy - check each Role/Group and User Principal + if ( allowedByLocalPolicy( session.getRoles(), permission ) || allowedByLocalPolicy( session.getPrincipals(), permission ) ) { + return Boolean.TRUE; + } + return Boolean.FALSE; + } ); + } + + /** {@inheritDoc} */ + @Override + public Principal resolvePrincipal( final String name ) { + // Check built-in Roles first + final Role role = new Role(name); + if ( Role.isBuiltInRole( role ) ) { + return role; + } + + // Check Authorizer Roles + Principal principal = m_authorizer.findRole( name ); + if ( principal != null ) { + return principal; + } + + // Check Groups + principal = m_engine.getManager( GroupManager.class ).findRole( name ); + if ( principal != null ) { + 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; + } + } + } catch( final NoSuchPrincipalException e ) { + // We couldn't find the user... + } + // Ok, no luck---mark this as unresolved and move on + return new UnresolvedPrincipal( name ); + } + + + // events processing ....................................................... + + /** {@inheritDoc} */ + @Override + public synchronized void addWikiEventListener( final WikiEventListener listener ) { + WikiEventManager.addWikiEventListener( this, listener ); + } + + /** {@inheritDoc} */ + @Override + public synchronized void removeWikiEventListener( final WikiEventListener listener ) { + WikiEventManager.removeWikiEventListener( this, listener ); + } + +} diff --git a/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/GroupDatabase.java b/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/GroupDatabase.java index ca03266..579036a 100644 --- a/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/GroupDatabase.java +++ b/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/GroupDatabase.java @@ -18,7 +18,7 @@ */ package org.apache.wiki.auth.authorize; -import org.apache.wiki.WikiEngine; +import org.apache.wiki.api.core.Engine; import org.apache.wiki.api.exceptions.NoRequiredPropertyException; import org.apache.wiki.auth.WikiSecurityException; @@ -50,7 +50,7 @@ public interface GroupDatabase { * @throws WikiSecurityException if the database could not be initialized successfully * @throws NoRequiredPropertyException if a required property is not present */ - void initialize( WikiEngine engine, Properties props ) throws NoRequiredPropertyException, WikiSecurityException; + void initialize( Engine engine, Properties props ) throws NoRequiredPropertyException, WikiSecurityException; /** * Saves a Group to the group database. Note that this method <em>must</em> diff --git a/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/GroupManager.java b/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/GroupManager.java index 1f3bc60..37e3c33 100644 --- a/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/GroupManager.java +++ b/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/GroupManager.java @@ -21,14 +21,15 @@ package org.apache.wiki.auth.authorize; import org.apache.commons.lang3.ArrayUtils; import org.apache.log4j.Logger; import org.apache.wiki.WikiContext; -import org.apache.wiki.WikiEngine; import org.apache.wiki.WikiSession; +import org.apache.wiki.api.core.Engine; import org.apache.wiki.api.exceptions.NoRequiredPropertyException; import org.apache.wiki.api.exceptions.WikiException; import org.apache.wiki.auth.AuthenticationManager; import org.apache.wiki.auth.Authorizer; import org.apache.wiki.auth.GroupPrincipal; import org.apache.wiki.auth.NoSuchPrincipalException; +import org.apache.wiki.auth.UserManager; import org.apache.wiki.auth.WikiPrincipal; import org.apache.wiki.auth.WikiSecurityException; import org.apache.wiki.auth.user.UserProfile; @@ -67,38 +68,33 @@ import java.util.StringTokenizer; public class GroupManager implements Authorizer, WikiEventListener { /** Key used for adding UI messages to a user's WikiSession. */ - public static final String MESSAGES_KEY = "group"; + public static final String MESSAGES_KEY = "group"; private static final String PROP_GROUPDATABASE = "jspwiki.groupdatabase"; - static final Logger log = Logger.getLogger( GroupManager.class ); + private static final Logger log = Logger.getLogger( GroupManager.class ); - protected WikiEngine m_engine; + protected Engine m_engine; protected WikiEventListener m_groupListener; private GroupDatabase m_groupDatabase = null; /** Map with GroupPrincipals as keys, and Groups as values */ - private final Map<Principal, Group> m_groups = new HashMap<Principal, Group>(); + private final Map< Principal, Group > m_groups = new HashMap<>(); /** * <p> - * Returns a GroupPrincipal matching a given name. If a group cannot be - * found, return <code>null</code>. + * Returns a GroupPrincipal matching a given name. If a group cannot be found, return <code>null</code>. * </p> * @param name Name of the group. This is case-sensitive. * @return A DefaultGroup instance. */ - public Principal findRole( String name ) - { - try - { - Group group = getGroup( name ); + @Override public Principal findRole( final String name ) { + try { + final Group group = getGroup( name ); return group.getPrincipal(); - } - catch( NoSuchPrincipalException e ) - { + } catch( final NoSuchPrincipalException e ) { return null; } } @@ -110,9 +106,9 @@ public class GroupManager implements Authorizer, WikiEventListener { * @return the group * @throws NoSuchPrincipalException if the group cannot be found */ - public Group getGroup( String name ) throws NoSuchPrincipalException + public Group getGroup( final String name ) throws NoSuchPrincipalException { - Group group = m_groups.get( new GroupPrincipal( name ) ); + final Group group = m_groups.get( new GroupPrincipal( name ) ); if ( group != null ) { return group; @@ -143,37 +139,37 @@ public class GroupManager implements Authorizer, WikiEventListener { Throwable cause = null; try { - Properties props = m_engine.getWikiProperties(); + final Properties props = m_engine.getWikiProperties(); dbClassName = props.getProperty( PROP_GROUPDATABASE ); if ( dbClassName == null ) { dbClassName = XMLGroupDatabase.class.getName(); } log.info( "Attempting to load group database class " + dbClassName ); - Class<?> dbClass = ClassUtil.findClass( "org.apache.wiki.auth.authorize", dbClassName ); + final Class<?> dbClass = ClassUtil.findClass( "org.apache.wiki.auth.authorize", dbClassName ); m_groupDatabase = (GroupDatabase) dbClass.newInstance(); m_groupDatabase.initialize( m_engine, m_engine.getWikiProperties() ); log.info( "Group database initialized." ); } - catch( ClassNotFoundException e ) + catch( final ClassNotFoundException e ) { log.error( "GroupDatabase class " + dbClassName + " cannot be found.", e ); dbInstantiationError = "Failed to locate GroupDatabase class " + dbClassName; cause = e; } - catch( InstantiationException e ) + catch( final InstantiationException e ) { log.error( "GroupDatabase class " + dbClassName + " cannot be created.", e ); dbInstantiationError = "Failed to create GroupDatabase class " + dbClassName; cause = e; } - catch( IllegalAccessException e ) + catch( final IllegalAccessException e ) { log.error( "You are not allowed to access group database class " + dbClassName + ".", e ); dbInstantiationError = "Access GroupDatabase class " + dbClassName + " denied"; cause = e; } - catch( NoRequiredPropertyException e ) + catch( final NoRequiredPropertyException e ) { log.error( "Missing property: " + e.getMessage() + "." ); dbInstantiationError = "Missing property: " + e.getMessage(); @@ -195,7 +191,7 @@ public class GroupManager implements Authorizer, WikiEventListener { * defensive copy of an internally stored hashmap. * @return an array of Principals representing the roles */ - public Principal[] getRoles() + @Override public Principal[] getRoles() { return m_groups.keySet().toArray( new Principal[m_groups.size()] ); } @@ -205,12 +201,11 @@ public class GroupManager implements Authorizer, WikiEventListener { * obtaining a list of all of the groups it stores. * @param engine the wiki engine * @param props the properties used to initialize the wiki engine - * @see GroupDatabase#initialize(org.apache.wiki.WikiEngine, - * java.util.Properties) + * @see GroupDatabase#initialize(org.apache.wiki.api.core.Engine, java.util.Properties) * @see GroupDatabase#groups() * @throws WikiSecurityException if GroupManager cannot be initialized */ - public void initialize( WikiEngine engine, Properties props ) throws WikiSecurityException + @Override public void initialize( final Engine engine, final Properties props ) throws WikiSecurityException { m_engine = engine; @@ -218,16 +213,16 @@ public class GroupManager implements Authorizer, WikiEventListener { { m_groupDatabase = getGroupDatabase(); } - catch ( WikiException e ) + catch ( final WikiException e ) { throw new WikiSecurityException( e.getMessage(), e ); } // Load all groups from the database into the cache - Group[] groups = m_groupDatabase.groups(); + final Group[] groups = m_groupDatabase.groups(); synchronized( m_groups ) { - for( Group group : groups ) + for( final Group group : groups ) { // Add new group to cache; fire GROUP_ADD event m_groups.put( group.getPrincipal(), group ); @@ -236,7 +231,7 @@ public class GroupManager implements Authorizer, WikiEventListener { } // Make the GroupManager listen for WikiEvents (WikiSecurityEvents for changed user profiles) - engine.getUserManager().addWikiEventListener( this ); + engine.getManager( UserManager.class ).addWikiEventListener( this ); // Success! log.info( "Authorizer GroupManager initialized successfully; loaded " + groups.length + " group(s)." ); @@ -264,7 +259,7 @@ public class GroupManager implements Authorizer, WikiEventListener { * @return <code>true</code> if the user is considered to be in the role, * <code>false</code> otherwise */ - public boolean isUserInRole( WikiSession session, Principal role ) + @Override public boolean isUserInRole( final WikiSession session, final Principal role ) { // Always return false if session/role is null, or if // role isn't a GroupPrincipal @@ -274,14 +269,14 @@ public class GroupManager implements Authorizer, WikiEventListener { } // Get the group we're examining - Group group = m_groups.get( role ); + final Group group = m_groups.get( role ); if ( group == null ) { return false; } // Check each user principal to see if it belongs to the group - for ( Principal principal : session.getPrincipals() ) + for ( final Principal principal : session.getPrincipals() ) { if ( AuthenticationManager.isUserPrincipal( principal ) && group.isMember( principal ) ) { @@ -321,7 +316,7 @@ public class GroupManager implements Authorizer, WikiEventListener { * <code>create</code> is <code>false</code> * and the Group named <code>name</code> does not exist */ - public Group parseGroup( String name, String memberLine, boolean create ) throws WikiSecurityException + public Group parseGroup( String name, String memberLine, final boolean create ) throws WikiSecurityException { // If null name parameter, it's because someone's creating a new group if ( name == null ) @@ -350,22 +345,22 @@ public class GroupManager implements Authorizer, WikiEventListener { memberLine = memberLine.trim(); // Create or retrieve the group (may have been previously cached) - Group group = new Group( name, m_engine.getApplicationName() ); + final Group group = new Group( name, m_engine.getApplicationName() ); try { - Group existingGroup = getGroup( name ); + final Group existingGroup = getGroup( name ); // If existing, clone it group.setCreator( existingGroup.getCreator() ); group.setCreated( existingGroup.getCreated() ); group.setModifier( existingGroup.getModifier() ); group.setLastModified( existingGroup.getLastModified() ); - for( Principal existingMember : existingGroup.members() ) + for( final Principal existingMember : existingGroup.members() ) { group.add( existingMember ); } } - catch( NoSuchPrincipalException e ) + catch( final NoSuchPrincipalException e ) { // It's a new group.... throw error if we don't create new ones if ( !create ) @@ -375,11 +370,11 @@ public class GroupManager implements Authorizer, WikiEventListener { } // If passed members not empty, overwrite - String[] members = extractMembers( memberLine ); + final String[] members = extractMembers( memberLine ); if ( members.length > 0 ) { group.clear(); - for( String member : members ) + for( final String member : members ) { group.add( new WikiPrincipal( member ) ); } @@ -416,16 +411,16 @@ public class GroupManager implements Authorizer, WikiEventListener { * <code>create</code> is <code>false</code> * and the Group does not exist */ - public Group parseGroup( WikiContext context, boolean create ) throws WikiSecurityException + public Group parseGroup( final WikiContext context, final boolean create ) throws WikiSecurityException { // Extract parameters - HttpServletRequest request = context.getHttpRequest(); - String name = request.getParameter( "group" ); - String memberLine = request.getParameter( "members" ); + final HttpServletRequest request = context.getHttpRequest(); + final String name = request.getParameter( "group" ); + final String memberLine = request.getParameter( "members" ); // Create the named group; we pass on any NoSuchPrincipalExceptions // that may be thrown if create == false, or WikiSecurityExceptions - Group group = parseGroup( name, memberLine, create ); + final Group group = parseGroup( name, memberLine, create ); // If no members, add the current user by default if ( group.members().length == 0 ) @@ -449,14 +444,14 @@ public class GroupManager implements Authorizer, WikiEventListener { * the back-end * @see org.apache.wiki.auth.authorize.GroupDatabase#delete(Group) */ - public void removeGroup( String index ) throws WikiSecurityException + public void removeGroup( final String index ) throws WikiSecurityException { if ( index == null ) { throw new IllegalArgumentException( "Group cannot be null." ); } - Group group = m_groups.get( new GroupPrincipal( index ) ); + final Group group = m_groups.get( new GroupPrincipal( index ) ); if ( group == null ) { throw new NoSuchPrincipalException( "Group " + index + " not found" ); @@ -512,12 +507,12 @@ public class GroupManager implements Authorizer, WikiEventListener { * @param group the Group, which may not be <code>null</code> * @throws WikiSecurityException if the Group cannot be saved by the back-end */ - public void setGroup( WikiSession session, Group group ) throws WikiSecurityException + public void setGroup( final WikiSession session, final Group group ) throws WikiSecurityException { // TODO: check for appropriate permissions // If group already exists, delete it; fire GROUP_REMOVE event - Group oldGroup = m_groups.get( group.getPrincipal() ); + final Group oldGroup = m_groups.get( group.getPrincipal() ); if ( oldGroup != null ) { fireEvent( WikiSecurityEvent.GROUP_REMOVE, oldGroup ); @@ -552,7 +547,7 @@ public class GroupManager implements Authorizer, WikiEventListener { } // We got an exception! Roll back... - catch( WikiSecurityException e ) + catch( final WikiSecurityException e ) { if ( oldGroup != null ) { @@ -577,22 +572,22 @@ public class GroupManager implements Authorizer, WikiEventListener { * @param context the current wiki context * @param group the supplied Group */ - public void validateGroup( WikiContext context, Group group ) + public void validateGroup( final WikiContext context, final Group group ) { - InputValidator validator = new InputValidator( MESSAGES_KEY, context ); + final InputValidator validator = new InputValidator( MESSAGES_KEY, context ); // Name cannot be null or one of the restricted names try { checkGroupName( context, group.getName() ); } - catch( WikiSecurityException e ) + catch( final WikiSecurityException e ) { } // Member names must be "safe" strings - Principal[] members = group.members(); + final Principal[] members = group.members(); for( int i = 0; i < members.length; i++ ) { validator.validateNotNull( members[i].getName(), "Full name", InputValidator.ID ); @@ -604,15 +599,15 @@ public class GroupManager implements Authorizer, WikiEventListener { * @param memberLine the list of members * @return the list of members */ - protected String[] extractMembers( String memberLine ) + protected String[] extractMembers( final String memberLine ) { - Set<String> members = new HashSet<String>(); + final Set<String> members = new HashSet<>(); if ( memberLine != null ) { - StringTokenizer tok = new StringTokenizer( memberLine, "\n" ); + final StringTokenizer tok = new StringTokenizer( memberLine, "\n" ); while( tok.hasMoreTokens() ) { - String uid = tok.nextToken().trim(); + final String uid = tok.nextToken().trim(); if ( uid != null && uid.length() > 0 ) { members.add( uid ); @@ -631,12 +626,12 @@ public class GroupManager implements Authorizer, WikiEventListener { * <code>null</code> or the Group name is illegal * @see Group#RESTRICTED_GROUPNAMES */ - protected void checkGroupName( WikiContext context, String name ) throws WikiSecurityException + protected void checkGroupName( final WikiContext context, final String name ) throws WikiSecurityException { //TODO: groups cannot have the same name as a user // Name cannot be null - InputValidator validator = new InputValidator( MESSAGES_KEY, context ); + final InputValidator validator = new InputValidator( MESSAGES_KEY, context ); validator.validateNotNull( name, "Group name" ); // Name cannot be one of the restricted names either @@ -654,7 +649,7 @@ public class GroupManager implements Authorizer, WikiEventListener { * This is a convenience method. * @param listener the event listener */ - public synchronized void addWikiEventListener( WikiEventListener listener ) + public synchronized void addWikiEventListener( final WikiEventListener listener ) { WikiEventManager.addWikiEventListener( this, listener ); } @@ -664,7 +659,7 @@ public class GroupManager implements Authorizer, WikiEventListener { * This is a convenience method. * @param listener the event listener */ - public synchronized void removeWikiEventListener( WikiEventListener listener ) + public synchronized void removeWikiEventListener( final WikiEventListener listener ) { WikiEventManager.removeWikiEventListener( this, listener ); } @@ -677,7 +672,7 @@ public class GroupManager implements Authorizer, WikiEventListener { * @param type the event type to be fired * @param target the changed Object, which may be <code>null</code> */ - protected void fireEvent( int type, Object target ) + protected void fireEvent( final int type, final Object target ) { if ( WikiEventManager.isListening(this) ) { @@ -693,32 +688,32 @@ public class GroupManager implements Authorizer, WikiEventListener { * only the representations of the names within that are changing. * @param event the incoming event */ - public void actionPerformed(WikiEvent event) + @Override public void actionPerformed( final WikiEvent event) { if (! ( event instanceof WikiSecurityEvent ) ) { return; } - WikiSecurityEvent se = (WikiSecurityEvent)event; + final WikiSecurityEvent se = (WikiSecurityEvent)event; if ( se.getType() == WikiSecurityEvent.PROFILE_NAME_CHANGED ) { - WikiSession session = se.getSrc(); - UserProfile[] profiles = (UserProfile[])se.getTarget(); - Principal[] oldPrincipals = new Principal[] { + final WikiSession session = se.getSrc(); + final UserProfile[] profiles = (UserProfile[])se.getTarget(); + final Principal[] oldPrincipals = new Principal[] { new WikiPrincipal( profiles[0].getLoginName() ), new WikiPrincipal( profiles[0].getFullname() ), new WikiPrincipal( profiles[0].getWikiName() ) }; - Principal newPrincipal = new WikiPrincipal( profiles[1].getFullname() ); + final Principal newPrincipal = new WikiPrincipal( profiles[1].getFullname() ); // Examine each group int groupsChanged = 0; try { - for ( Group group : m_groupDatabase.groups() ) + for ( final Group group : m_groupDatabase.groups() ) { boolean groupChanged = false; - for ( Principal oldPrincipal : oldPrincipals ) + for ( final Principal oldPrincipal : oldPrincipals ) { if ( group.isMember( oldPrincipal ) ) { @@ -734,7 +729,7 @@ public class GroupManager implements Authorizer, WikiEventListener { } } } - catch ( WikiException e ) + catch ( final WikiException e ) { // Oooo! This is really bad... log.error( "Could not change user name in Group lists because of GroupDatabase error:" + e.getMessage() ); diff --git a/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/JDBCGroupDatabase.java b/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/JDBCGroupDatabase.java index d5ac0d2..1f22cf6 100644 --- a/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/JDBCGroupDatabase.java +++ b/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/JDBCGroupDatabase.java @@ -18,23 +18,29 @@ */ package org.apache.wiki.auth.authorize; -import java.security.Principal; -import java.sql.*; -import java.util.*; -import java.util.Date; - -import javax.naming.Context; -import javax.naming.InitialContext; -import javax.naming.NamingException; -import javax.sql.DataSource; - import org.apache.log4j.Logger; -import org.apache.wiki.WikiEngine; +import org.apache.wiki.api.core.Engine; import org.apache.wiki.api.exceptions.NoRequiredPropertyException; import org.apache.wiki.auth.NoSuchPrincipalException; import org.apache.wiki.auth.WikiPrincipal; import org.apache.wiki.auth.WikiSecurityException; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.sql.DataSource; +import java.security.Principal; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.Date; +import java.util.HashSet; +import java.util.Properties; +import java.util.Set; + /** * <p> * Implementation of GroupDatabase that persists {@link Group} objects to a JDBC @@ -121,13 +127,8 @@ import org.apache.wiki.auth.WikiSecurityException; * </p> * <p> * JDBCGroupDatabase commits changes as transactions if the back-end database - * supports them. If the database supports transactions, group changes are saved - * to permanent storage only when the {@link #commit()} method is called. If the - * database does <em>not</em> support transactions, then changes are made - * immediately (during the {@link #save(Group, Principal)} method), and the - * {@linkplain #commit()} method no-ops. Thus, callers should always call the - * {@linkplain #commit()} method after saving a profile to guarantee that - * changes are applied. + * supports them. Changes are made + * immediately (during the {@link #save(Group, Principal)} method). * </p> * * @since 2.3 @@ -222,7 +223,7 @@ public class JDBCGroupDatabase implements GroupDatabase { private boolean m_supportsCommits = false; - private WikiEngine m_engine = null; + private Engine m_engine = null; /** * Looks up and deletes a {@link Group} from the group database. If the @@ -235,14 +236,14 @@ public class JDBCGroupDatabase implements GroupDatabase { * supplied group (thrown as {@link NoSuchPrincipalException}) * or if the commit did not succeed */ - public void delete( Group group ) throws WikiSecurityException + @Override public void delete( final Group group ) throws WikiSecurityException { if( !exists( group ) ) { throw new NoSuchPrincipalException( "Not in database: " + group.getName() ); } - String groupName = group.getName(); + final String groupName = group.getName(); Connection conn = null; PreparedStatement ps = null; try @@ -269,7 +270,7 @@ public class JDBCGroupDatabase implements GroupDatabase { conn.commit(); } } - catch( SQLException e ) + catch( final SQLException e ) { closeQuietly( conn, ps, null ); throw new WikiSecurityException( "Could not delete group " + groupName + ": " + e.getMessage(), e ); @@ -291,9 +292,9 @@ public class JDBCGroupDatabase implements GroupDatabase { * @throws WikiSecurityException if the groups cannot be returned by the * back-end */ - public Group[] groups() throws WikiSecurityException + @Override public Group[] groups() throws WikiSecurityException { - Set<Group> groups = new HashSet<Group>(); + final Set<Group> groups = new HashSet<>(); Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; @@ -306,14 +307,14 @@ public class JDBCGroupDatabase implements GroupDatabase { rs = ps.executeQuery(); while ( rs.next() ) { - String groupName = rs.getString( m_name ); + final String groupName = rs.getString( m_name ); if( groupName == null ) { log.warn( "Detected null group name in JDBCGroupDataBase. Check your group database." ); } else { - Group group = new Group( groupName, m_engine.getApplicationName() ); + final Group group = new Group( groupName, m_engine.getApplicationName() ); group.setCreated( rs.getTimestamp( m_created ) ); group.setCreator( rs.getString( m_creator ) ); group.setLastModified( rs.getTimestamp( m_modified ) ); @@ -323,7 +324,7 @@ public class JDBCGroupDatabase implements GroupDatabase { } } } - catch( SQLException e ) + catch( final SQLException e ) { closeQuietly( conn, ps, rs ); throw new WikiSecurityException( e.getMessage(), e ); @@ -346,17 +347,16 @@ public class JDBCGroupDatabase implements GroupDatabase { * * @param group the Group to save * @param modifier the user who saved the Group - * @throws WikiSecurityException if the Group could not be saved - * successfully + * @throws WikiSecurityException if the Group could not be saved successfully */ - public void save( Group group, Principal modifier ) throws WikiSecurityException + @Override public void save( final Group group, final Principal modifier ) throws WikiSecurityException { if( group == null || modifier == null ) { throw new IllegalArgumentException( "Group or modifier cannot be null." ); } - boolean exists = exists( group ); + final boolean exists = exists( group ); Connection conn = null; PreparedStatement ps = null; try @@ -368,8 +368,8 @@ public class JDBCGroupDatabase implements GroupDatabase { conn.setAutoCommit( false ); } - Timestamp ts = new Timestamp( System.currentTimeMillis() ); - Date modDate = new Date( ts.getTime() ); + final Timestamp ts = new Timestamp( System.currentTimeMillis() ); + final Date modDate = new Date( ts.getTime() ); if( !exists ) { // Group is new: insert new group record @@ -410,10 +410,10 @@ public class JDBCGroupDatabase implements GroupDatabase { // Insert group member records ps = conn.prepareStatement( m_insertGroupMembers ); - Principal[] members = group.members(); + final Principal[] members = group.members(); for( int i = 0; i < members.length; i++ ) { - Principal member = members[i]; + final Principal member = members[i]; ps.setString( 1, group.getName() ); ps.setString( 2, member.getName() ); ps.execute(); @@ -425,7 +425,7 @@ public class JDBCGroupDatabase implements GroupDatabase { conn.commit(); } } - catch( SQLException e ) + catch( final SQLException e ) { closeQuietly(conn, ps, null ); throw new WikiSecurityException( e.getMessage(), e ); @@ -445,18 +445,18 @@ public class JDBCGroupDatabase implements GroupDatabase { * successfully * @throws NoRequiredPropertyException if a required property is not present */ - public void initialize( WikiEngine engine, Properties props ) throws NoRequiredPropertyException, WikiSecurityException + @Override public void initialize( final Engine engine, final Properties props ) throws NoRequiredPropertyException, WikiSecurityException { - String table; - String memberTable; + final String table; + final String memberTable; m_engine = engine; - String jndiName = props.getProperty( PROP_GROUPDB_DATASOURCE, DEFAULT_GROUPDB_DATASOURCE ); + final String jndiName = props.getProperty( PROP_GROUPDB_DATASOURCE, DEFAULT_GROUPDB_DATASOURCE ); try { - Context initCtx = new InitialContext(); - Context ctx = (Context) initCtx.lookup( "java:comp/env" ); + final Context initCtx = new InitialContext(); + final Context ctx = (Context) initCtx.lookup( "java:comp/env" ); m_ds = (DataSource) ctx.lookup( jndiName ); // Prepare the SQL selectors @@ -485,7 +485,7 @@ public class JDBCGroupDatabase implements GroupDatabase { m_deleteGroup = "DELETE FROM " + table + " WHERE " + m_name + "=?"; m_deleteGroupMembers = "DELETE FROM " + memberTable + " WHERE " + m_name + "=?"; } - catch( NamingException e ) + catch( final NamingException e ) { log.error( "JDBCGroupDatabase initialization error: " + e ); throw new NoRequiredPropertyException( PROP_GROUPDB_DATASOURCE, "JDBCGroupDatabase initialization error: " + e); @@ -501,7 +501,7 @@ public class JDBCGroupDatabase implements GroupDatabase { ps.executeQuery(); ps.close(); } - catch( SQLException e ) + catch( final SQLException e ) { closeQuietly( conn, ps, null ); log.error( "DB connectivity error: " + e.getMessage() ); @@ -517,7 +517,7 @@ public class JDBCGroupDatabase implements GroupDatabase { try { conn = m_ds.getConnection(); - DatabaseMetaData dmd = conn.getMetaData(); + final DatabaseMetaData dmd = conn.getMetaData(); if( dmd.supportsTransactions() ) { m_supportsCommits = true; @@ -525,7 +525,7 @@ public class JDBCGroupDatabase implements GroupDatabase { log.info( "JDBCGroupDatabase supports transactions. Good; we will use them." ); } } - catch( SQLException e ) + catch( final SQLException e ) { closeQuietly( conn, null, null ); log.warn( "JDBCGroupDatabase warning: user database doesn't seem to support transactions. Reason: " + e); @@ -542,15 +542,15 @@ public class JDBCGroupDatabase implements GroupDatabase { * @param group the Group to look for * @return the result of the search */ - private boolean exists( Group group ) + private boolean exists( final Group group ) { - String index = group.getName(); + final String index = group.getName(); try { findGroup( index ); return true; } - catch( NoSuchPrincipalException e ) + catch( final NoSuchPrincipalException e ) { return false; } @@ -565,7 +565,7 @@ public class JDBCGroupDatabase implements GroupDatabase { * @throws NoSuchPrincipalException if the Group cannot be found * @throws SQLException if the database query returns an error */ - private Group findGroup( String index ) throws NoSuchPrincipalException + private Group findGroup( final String index ) throws NoSuchPrincipalException { Group group = null; boolean found = false; @@ -597,7 +597,7 @@ public class JDBCGroupDatabase implements GroupDatabase { found = true; } } - catch( SQLException e ) + catch( final SQLException e ) { closeQuietly( conn, ps, rs ); throw new NoSuchPrincipalException( e.getMessage() ); @@ -624,7 +624,7 @@ public class JDBCGroupDatabase implements GroupDatabase { * @param group the group to populate * @return the populated Group */ - private Group populateGroup( Group group ) + private Group populateGroup( final Group group ) { ResultSet rs = null; PreparedStatement ps = null; @@ -639,15 +639,15 @@ public class JDBCGroupDatabase implements GroupDatabase { rs = ps.executeQuery(); while ( rs.next() ) { - String memberName = rs.getString( m_member ); + final String memberName = rs.getString( m_member ); if( memberName != null ) { - WikiPrincipal principal = new WikiPrincipal( memberName, WikiPrincipal.UNSPECIFIED ); + final WikiPrincipal principal = new WikiPrincipal( memberName, WikiPrincipal.UNSPECIFIED ); group.add( principal ); } } } - catch( SQLException e ) + catch( final SQLException e ) { // I guess that means there aren't any principals... } @@ -658,23 +658,23 @@ public class JDBCGroupDatabase implements GroupDatabase { return group; } - void closeQuietly( Connection conn, PreparedStatement ps, ResultSet rs ) { + void closeQuietly( final Connection conn, final PreparedStatement ps, final ResultSet rs ) { if( conn != null ) { try { conn.close(); - } catch( Exception e ) { + } catch( final Exception e ) { } } if( ps != null ) { try { ps.close(); - } catch( Exception e ) { + } catch( final Exception e ) { } } if( rs != null ) { try { rs.close(); - } catch( Exception e ) { + } catch( final Exception e ) { } } } diff --git a/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/WebAuthorizer.java b/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/WebAuthorizer.java index d55569e..dd6cf08 100644 --- a/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/WebAuthorizer.java +++ b/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/WebAuthorizer.java @@ -18,29 +18,25 @@ */ package org.apache.wiki.auth.authorize; -import java.security.Principal; +import org.apache.wiki.auth.Authorizer; import javax.servlet.http.HttpServletRequest; +import java.security.Principal; -import org.apache.wiki.auth.Authorizer; /** - * Extends the {@link org.apache.wiki.auth.Authorizer} interface by - * including a delgate method for + * Extends the {@link org.apache.wiki.auth.Authorizer} interface by including a delgate method for * {@link javax.servlet.http.HttpServletRequest#isUserInRole(String)}. */ -public interface WebAuthorizer extends Authorizer -{ +public interface WebAuthorizer extends Authorizer { /** - * Determines whether a user associated with an HTTP request possesses - * a particular role. This method simply delegates to - * {@link javax.servlet.http.HttpServletRequest#isUserInRole(String)} - * by converting the Principal's name to a String. + * Determines whether a user associated with an HTTP request possesses a particular role. This method simply delegates to + * {@link javax.servlet.http.HttpServletRequest#isUserInRole(String)} by converting the Principal's name to a String. + * * @param request the HTTP request * @param role the role to check - * @return <code>true</code> if the user is considered to be in the role, - * <code>false</code> otherwise + * @return <code>true</code> if the user is considered to be in the role, <code>false</code> otherwise */ boolean isUserInRole( HttpServletRequest request, Principal role ); diff --git a/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/WebContainerAuthorizer.java b/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/WebContainerAuthorizer.java index cfb78b3..a4c4968 100644 --- a/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/WebContainerAuthorizer.java +++ b/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/WebContainerAuthorizer.java @@ -20,8 +20,8 @@ package org.apache.wiki.auth.authorize; import org.apache.log4j.Logger; import org.apache.wiki.InternalWikiException; -import org.apache.wiki.WikiEngine; import org.apache.wiki.WikiSession; +import org.apache.wiki.api.core.Engine; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.JDOMException; @@ -56,9 +56,9 @@ public class WebContainerAuthorizer implements WebAuthorizer { private static final String J2EE_SCHEMA_25_NAMESPACE = "http://xmlns.jcp.org/xml/ns/javaee"; - protected static final Logger log = Logger.getLogger( WebContainerAuthorizer.class ); + private static final Logger log = Logger.getLogger( WebContainerAuthorizer.class ); - protected WikiEngine m_engine; + protected Engine m_engine; /** * A lazily-initialized array of Roles that the container knows about. These @@ -68,15 +68,15 @@ public class WebContainerAuthorizer implements WebAuthorizer { * that we have no direct way of querying the web container about which * roles it manages. */ - protected Role[] m_containerRoles = new Role[0]; + protected Role[] m_containerRoles = new Role[0]; /** * Lazily-initialized boolean flag indicating whether the web container * protects JSPWiki resources. */ - protected boolean m_containerAuthorized = false; + protected boolean m_containerAuthorized = false; - private Document m_webxml = null; + private Document m_webxml = null; /** * Constructs a new instance of the WebContainerAuthorizer class. @@ -92,49 +92,36 @@ public class WebContainerAuthorizer implements WebAuthorizer { * @param props the wiki engine initialization properties */ @Override - public void initialize( WikiEngine engine, Properties props ) - { + public void initialize( final Engine engine, final Properties props ) { m_engine = engine; m_containerAuthorized = false; // FIXME: Error handling here is not very verbose - try - { + try { m_webxml = getWebXml(); - if ( m_webxml != null ) - { + if( m_webxml != null ) { // Add the J2EE 2.4 schema namespace m_webxml.getRootElement().setNamespace( Namespace.getNamespace( J2EE_SCHEMA_25_NAMESPACE ) ); - m_containerAuthorized = isConstrained( "/Delete.jsp", Role.ALL ) - && isConstrained( "/Login.jsp", Role.ALL ); + m_containerAuthorized = isConstrained( "/Delete.jsp", Role.ALL ) && isConstrained( "/Login.jsp", Role.ALL ); } - if ( m_containerAuthorized ) - { + if( m_containerAuthorized ) { m_containerRoles = getRoles( m_webxml ); log.info( "JSPWiki is using container-managed authentication." ); - } - else - { + } else { log.info( "JSPWiki is using custom authentication." ); } - } - catch ( IOException e ) - { - log.error("Initialization failed: ",e); - throw new InternalWikiException( e.getClass().getName()+": "+e.getMessage() , e); - } - catch ( JDOMException e ) - { - log.error("Malformed XML in web.xml",e); - throw new InternalWikiException( e.getClass().getName()+": "+e.getMessage() , e); + } catch( final IOException e ) { + log.error( "Initialization failed: ", e ); + throw new InternalWikiException( e.getClass().getName() + ": " + e.getMessage(), e ); + } catch( final JDOMException e ) { + log.error( "Malformed XML in web.xml", e ); + throw new InternalWikiException( e.getClass().getName() + ": " + e.getMessage(), e ); } - if ( m_containerRoles.length > 0 ) - { + if( m_containerRoles.length > 0 ) { String roles = ""; - for( Role containerRole : m_containerRoles ) - { + for( final Role containerRole : m_containerRoles ) { roles = roles + containerRole + " "; } log.info( " JSPWiki determined the web container manages these roles: " + roles ); @@ -153,7 +140,7 @@ public class WebContainerAuthorizer implements WebAuthorizer { * <code>false</code> otherwise */ @Override - public boolean isUserInRole( HttpServletRequest request, Principal role ) + public boolean isUserInRole( final HttpServletRequest request, final Principal role ) { return request.isUserInRole( role.getName() ); } @@ -182,10 +169,8 @@ public class WebContainerAuthorizer implements WebAuthorizer { * @see org.apache.wiki.auth.Authorizer#isUserInRole(org.apache.wiki.WikiSession, java.security.Principal) */ @Override - public boolean isUserInRole( WikiSession session, Principal role ) - { - if ( session == null || role == null ) - { + public boolean isUserInRole( final WikiSession session, final Principal role ) { + if ( session == null || role == null ) { return false; } return session.hasPrincipal( role ); @@ -197,15 +182,12 @@ public class WebContainerAuthorizer implements WebAuthorizer { * initialization, this method returns <code>null</code>. * @param role the name of the Role to retrieve * @return a Role Principal, or <code>null</code> - * @see org.apache.wiki.auth.Authorizer#initialize(WikiEngine, Properties) + * @see org.apache.wiki.auth.Authorizer#initialize(Engine, Properties) */ @Override - public Principal findRole( String role ) - { - for( Role containerRole : m_containerRoles ) - { - if ( containerRole.getName().equals( role ) ) - { + public Principal findRole( final String role ) { + for( final Role containerRole : m_containerRoles ) { + if ( containerRole.getName().equals( role ) ) { return containerRole; } } @@ -266,9 +248,9 @@ public class WebContainerAuthorizer implements WebAuthorizer { } // If a constraint is contained in both lists, we must be constrained - for ( Iterator< Element > c = constraints.iterator(); c.hasNext(); ) { + for ( final Iterator< Element > c = constraints.iterator(); c.hasNext(); ) { final Element constraint = c.next(); - for ( Iterator< Element > r = roles.iterator(); r.hasNext(); ) { + for ( final Iterator< Element > r = roles.iterator(); r.hasNext(); ) { final Element roleConstraint = r.next(); if ( constraint.equals( roleConstraint ) ) { return true; @@ -362,14 +344,14 @@ public class WebContainerAuthorizer implements WebAuthorizer { */ protected Document getWebXml() throws JDOMException, IOException { - URL url; - SAXBuilder builder = new SAXBuilder(); + final URL url; + final SAXBuilder builder = new SAXBuilder(); builder.setXMLReaderFactory( XMLReaders.NONVALIDATING ); builder.setEntityResolver( new LocalEntityResolver() ); Document doc = null; if ( m_engine.getServletContext() == null ) { - ClassLoader cl = WebContainerAuthorizer.class.getClassLoader(); + final ClassLoader cl = WebContainerAuthorizer.class.getClassLoader(); url = cl.getResource( "WEB-INF/web.xml" ); if( url != null ) log.info( "Examining " + url.toExternalForm() ); @@ -414,13 +396,13 @@ public class WebContainerAuthorizer implements WebAuthorizer { * @throws IOException if the resource cannot be opened */ @Override - public InputSource resolveEntity( String publicId, String systemId ) throws SAXException, IOException + public InputSource resolveEntity( final String publicId, final String systemId ) throws SAXException, IOException { - String file = systemId.substring( systemId.lastIndexOf( '/' ) + 1 ); - URL url; + final String file = systemId.substring( systemId.lastIndexOf( '/' ) + 1 ); + final URL url; if ( m_engine.getServletContext() == null ) { - ClassLoader cl = WebContainerAuthorizer.class.getClassLoader(); + final ClassLoader cl = WebContainerAuthorizer.class.getClassLoader(); url = cl.getResource( "WEB-INF/dtd/" + file ); } else @@ -430,7 +412,7 @@ public class WebContainerAuthorizer implements WebAuthorizer { if( url != null ) { - InputSource is = new InputSource( url.openStream() ); + final InputSource is = new InputSource( url.openStream() ); log.debug( "Resolved systemID=" + systemId + " using local file " + url ); return is; } diff --git a/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/XMLGroupDatabase.java b/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/XMLGroupDatabase.java index 153a2d6..6b0ec1d 100644 --- a/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/XMLGroupDatabase.java +++ b/jspwiki-main/src/main/java/org/apache/wiki/auth/authorize/XMLGroupDatabase.java @@ -20,7 +20,7 @@ package org.apache.wiki.auth.authorize; import org.apache.commons.text.StringEscapeUtils; import org.apache.log4j.Logger; -import org.apache.wiki.WikiEngine; +import org.apache.wiki.api.core.Engine; import org.apache.wiki.api.exceptions.NoRequiredPropertyException; import org.apache.wiki.auth.NoSuchPrincipalException; import org.apache.wiki.auth.WikiPrincipal; @@ -73,14 +73,11 @@ import java.util.concurrent.ConcurrentHashMap; * </code></blockquote> * @since 2.4.17 */ -public class XMLGroupDatabase implements GroupDatabase -{ - protected static final Logger log = Logger.getLogger( XMLGroupDatabase.class ); +public class XMLGroupDatabase implements GroupDatabase { - /** - * The jspwiki.properties property specifying the file system location of - * the group database. - */ + private static final Logger log = Logger.getLogger( XMLGroupDatabase.class ); + + /** The jspwiki.properties property specifying the file system location of the group database. */ public static final String PROP_DATABASE = "jspwiki.xmlGroupDatabaseFile"; private static final String DEFAULT_DATABASE = "groupdatabase.xml"; @@ -109,7 +106,7 @@ public class XMLGroupDatabase implements GroupDatabase private File m_file = null; - private WikiEngine m_engine = null; + private Engine m_engine = null; private Map<String, Group> m_groups = new ConcurrentHashMap<>(); @@ -124,10 +121,10 @@ public class XMLGroupDatabase implements GroupDatabase * the commit did not succeed */ @Override - public void delete( Group group ) throws WikiSecurityException + public void delete( final Group group ) throws WikiSecurityException { - String index = group.getName(); - boolean exists = m_groups.containsKey( index ); + final String index = group.getName(); + final boolean exists = m_groups.containsKey( index ); if ( !exists ) { @@ -153,7 +150,7 @@ public class XMLGroupDatabase implements GroupDatabase public Group[] groups() throws WikiSecurityException { buildDOM(); - Collection<Group> groups = m_groups.values(); + final Collection<Group> groups = m_groups.values(); return groups.toArray( new Group[groups.size()] ); } @@ -168,7 +165,7 @@ public class XMLGroupDatabase implements GroupDatabase * @throws WikiSecurityException if the database could not be initialized successfully */ @Override - public void initialize( WikiEngine engine, Properties props ) throws NoRequiredPropertyException, WikiSecurityException + public void initialize( final Engine engine, final Properties props ) throws NoRequiredPropertyException, WikiSecurityException { m_engine = engine; @@ -184,7 +181,7 @@ public class XMLGroupDatabase implements GroupDatabase } // Get database file location - String file = TextUtil.getStringProperty(props, PROP_DATABASE , defaultFile.getAbsolutePath()); + final String file = TextUtil.getStringProperty(props, PROP_DATABASE , defaultFile.getAbsolutePath()); if ( file == null ) { log.warn( "XML group database property " + PROP_DATABASE + " not found; trying " + defaultFile ); @@ -213,16 +210,16 @@ public class XMLGroupDatabase implements GroupDatabase * @throws WikiSecurityException if the Group could not be saved successfully */ @Override - public void save( Group group, Principal modifier ) throws WikiSecurityException { + public void save( final Group group, final Principal modifier ) throws WikiSecurityException { if ( group == null || modifier == null ) { throw new IllegalArgumentException( "Group or modifier cannot be null." ); } checkForRefresh(); - String index = group.getName(); - boolean isNew = !( m_groups.containsKey( index ) ); - Date modDate = new Date( System.currentTimeMillis() ); + final String index = group.getName(); + final boolean isNew = !( m_groups.containsKey( index ) ); + final Date modDate = new Date( System.currentTimeMillis() ); if ( isNew ) { // If new, set created info diff --git a/jspwiki-main/src/main/resources/ini/classmappings.xml b/jspwiki-main/src/main/resources/ini/classmappings.xml index ff4ad5a..b419955 100644 --- a/jspwiki-main/src/main/resources/ini/classmappings.xml +++ b/jspwiki-main/src/main/resources/ini/classmappings.xml @@ -73,7 +73,7 @@ </mapping> <mapping> <requestedClass>org.apache.wiki.auth.AuthorizationManager</requestedClass> - <mappedClass>org.apache.wiki.auth.AuthorizationManager</mappedClass> + <mappedClass>org.apache.wiki.auth.DefaultAuthorizationManager</mappedClass> </mapping> <mapping> <requestedClass>org.apache.wiki.auth.UserManager</requestedClass> diff --git a/jspwiki-main/src/test/java/org/apache/wiki/auth/AuthenticationManagerTest.java b/jspwiki-main/src/test/java/org/apache/wiki/auth/AuthenticationManagerTest.java index 803f1fd..0c1a106 100644 --- a/jspwiki-main/src/test/java/org/apache/wiki/auth/AuthenticationManagerTest.java +++ b/jspwiki-main/src/test/java/org/apache/wiki/auth/AuthenticationManagerTest.java @@ -17,16 +17,12 @@ under the License. */ package org.apache.wiki.auth; -import java.security.Principal; -import java.util.Map; -import java.util.Properties; - -import javax.servlet.http.HttpServletRequest; import org.apache.wiki.TestEngine; import org.apache.wiki.WikiEngine; import org.apache.wiki.WikiSession; import org.apache.wiki.WikiSessionTest; +import org.apache.wiki.api.core.Engine; import org.apache.wiki.auth.authorize.Group; import org.apache.wiki.auth.authorize.GroupManager; import org.apache.wiki.auth.authorize.Role; @@ -36,45 +32,42 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import javax.servlet.http.HttpServletRequest; +import java.security.Principal; +import java.util.Map; +import java.util.Properties; + /** * Tests the AuthorizationManager class. * */ -public class AuthenticationManagerTest -{ - public static class DummyAuthorizer implements WebAuthorizer - { +public class AuthenticationManagerTest { + + public static class DummyAuthorizer implements WebAuthorizer { private static Principal[] m_roles = new Principal[] { new Role( "ContainerRole" ), new Role( "AuthorizerRole" ), new Role( "DummyRole" ) }; - public Principal findRole( String role ) - { - for( Principal principal : m_roles ) - { - if( principal.getName().equals( role ) ) - { + @Override public Principal findRole( final String role ) { + for( final Principal principal : m_roles ) { + if( principal.getName().equals( role ) ) { return principal; } } return null; } - public Principal[] getRoles() - { + @Override public Principal[] getRoles() { return m_roles; } - public void initialize( WikiEngine engine, Properties props ) throws WikiSecurityException - { + @Override public void initialize( final Engine engine, final Properties props ) throws WikiSecurityException { } - public boolean isUserInRole( HttpServletRequest request, Principal role ) - { + @Override public boolean isUserInRole( final HttpServletRequest request, final Principal role ) { return request != null && "ContainerRole".equals( role.getName() ); } - public boolean isUserInRole( WikiSession session, Principal role ) - { + @Override public boolean isUserInRole( final WikiSession session, final Principal role ) { return session != null && "AuthorizerRole".equals( role.getName() ); } } @@ -88,9 +81,8 @@ public class AuthenticationManagerTest private WikiSession m_session; @BeforeEach - public void setUp() throws Exception - { - Properties props = TestEngine.getTestProperties(); + public void setUp() throws Exception { + final Properties props = TestEngine.getTestProperties(); m_engine = new TestEngine( props ); m_auth = m_engine.getAuthenticationManager(); m_groupMgr = m_engine.getGroupManager(); @@ -98,15 +90,13 @@ public class AuthenticationManagerTest } /** - * Tests a dummy WebAuthorizer that is guaranteed to return true for one - * role for each of the two <code>isInRole</code> methods. + * Tests a dummy WebAuthorizer that is guaranteed to return true for one role for each of the two <code>isInRole</code> methods. * * @throws Exception */ @Test - public void testCustomAuthorizer() throws Exception - { - Properties props = TestEngine.getTestProperties(); + public void testCustomAuthorizer() throws Exception { + final Properties props = TestEngine.getTestProperties(); props.put( AuthorizationManager.PROP_AUTHORIZER, "org.apache.wiki.auth.AuthenticationManagerTest$DummyAuthorizer" ); m_engine = new TestEngine( props ); @@ -134,24 +124,22 @@ public class AuthenticationManagerTest } @Test - public void testCustomJAASLoginModule() throws Exception - { - Properties props = TestEngine.getTestProperties(); + public void testCustomJAASLoginModule() throws Exception { + final Properties props = TestEngine.getTestProperties(); // Supply a custom LoginModule class props.put( "jspwiki.loginModule.class", "org.apache.wiki.auth.login.CookieAssertionLoginModule" ); // Init the engine and verify that we initialized with a custom auth // login module - WikiEngine engine = new TestEngine( props ); - AuthenticationManager authMgr = engine.getAuthenticationManager(); + final WikiEngine engine = new TestEngine( props ); + final DefaultAuthenticationManager authMgr = ( DefaultAuthenticationManager )engine.getAuthenticationManager(); Assertions.assertEquals( CookieAssertionLoginModule.class, authMgr.m_loginModuleClass ); } @Test - public void testCustomJAASLoginModuleOptions() throws Exception - { - Properties props = TestEngine.getTestProperties(); + public void testCustomJAASLoginModuleOptions() throws Exception { + final Properties props = TestEngine.getTestProperties(); // Supply a custom LoginModule options props.put( "jspwiki.loginModule.options.key1", "value1" ); @@ -160,9 +148,9 @@ public class AuthenticationManagerTest // Init the engine and verify that we initialized with the correct // options - WikiEngine engine = new TestEngine( props ); - AuthenticationManager authMgr = engine.getAuthenticationManager(); - Map<String, String> options = authMgr.m_loginModuleOptions; + final WikiEngine engine = new TestEngine( props ); + final DefaultAuthenticationManager authMgr = ( DefaultAuthenticationManager )engine.getAuthenticationManager(); + final Map<String, String> options = authMgr.m_loginModuleOptions; Assertions.assertEquals( 3, options.size() ); Assertions.assertTrue( options.containsKey( "key1" ) ); Assertions.assertTrue( options.containsKey( "key2" ) ); @@ -173,8 +161,7 @@ public class AuthenticationManagerTest } @Test - public void testIsUserPrincipal() - { + public void testIsUserPrincipal() { Assertions.assertTrue( AuthenticationManager.isUserPrincipal( new WikiPrincipal( "Foo" ) ) ); Assertions.assertFalse( AuthenticationManager.isUserPrincipal( new GroupPrincipal( "Group1" ) ) ); Assertions.assertFalse( AuthenticationManager.isUserPrincipal( new Role( "Role1" ) ) ); @@ -182,9 +169,8 @@ public class AuthenticationManagerTest } @Test - public void testLoginCustom() throws Exception - { - WikiSession session = WikiSessionTest.authenticatedSession( m_engine, Users.JANNE, Users.JANNE_PASS ); + public void testLoginCustom() throws Exception { + final WikiSession session = WikiSessionTest.authenticatedSession( m_engine, Users.JANNE, Users.JANNE_PASS ); Assertions.assertTrue( session.hasPrincipal( Role.ALL ) ); Assertions.assertTrue( session.hasPrincipal( Role.AUTHENTICATED ) ); Assertions.assertTrue( session.hasPrincipal( new WikiPrincipal( Users.JANNE, WikiPrincipal.LOGIN_NAME ) ) ); @@ -193,43 +179,38 @@ public class AuthenticationManagerTest } @Test - public void testLoginCustomWithGroup() throws Exception - { - // Flush any pre-existing groups (left over from previous Assertions.failures, - // perhaps) - try - { + public void testLoginCustomWithGroup() throws Exception { + // Flush any pre-existing groups (left over from previous Assertions.failures, perhaps) + try { m_groupMgr.removeGroup( "Test1" ); m_groupMgr.removeGroup( "Test2" ); - } - catch( NoSuchPrincipalException e ) - { + } catch( final NoSuchPrincipalException e ) { } // Log in 'janne' and verify there are 5 principals in the subject // (ALL, AUTHENTICATED, login, fullname, wikiname Principals) - WikiSession session = WikiSession.guestSession( m_engine ); + final WikiSession session = WikiSession.guestSession( m_engine ); m_auth.login( session, null, Users.JANNE, Users.JANNE_PASS ); Assertions.assertEquals( 3, session.getPrincipals().length ); Assertions.assertEquals( 2, session.getRoles().length ); Assertions.assertTrue( session.hasPrincipal( new WikiPrincipal( "JanneJalkanen", WikiPrincipal.WIKI_NAME ) ) ); // Listen for any manager group-add events - GroupManager manager = m_engine.getGroupManager(); - SecurityEventTrap trap = new SecurityEventTrap(); + final GroupManager manager = m_engine.getGroupManager(); + final SecurityEventTrap trap = new SecurityEventTrap(); manager.addWikiEventListener( trap ); // Create two groups; one with Janne in it, and one without Group groupTest1 = m_groupMgr.parseGroup( "Test1", "JanneJalkanen \n Bob \n Charlie", true ); m_groupMgr.setGroup( m_session, groupTest1 ); groupTest1 = m_groupMgr.getGroup( "Test1" ); - Principal principalTest1 = groupTest1.getPrincipal(); + final Principal principalTest1 = groupTest1.getPrincipal(); Group groupTest2 = m_groupMgr.parseGroup( "Test2", "Alice \n Bob \n Charlie", true ); m_groupMgr.setGroup( m_session, groupTest2 ); groupTest2 = m_groupMgr.getGroup( "Test2" ); - Principal principalTest2 = groupTest2.getPrincipal(); + final Principal principalTest2 = groupTest2.getPrincipal(); // We should see two security events (one for each group create) // We should also see a GroupPrincipal for group Test1, but not Test2 diff --git a/jspwiki-main/src/test/java/org/apache/wiki/auth/TestAuthorizer.java b/jspwiki-main/src/test/java/org/apache/wiki/auth/TestAuthorizer.java index c0761e9..5b272e7 100644 --- a/jspwiki-main/src/test/java/org/apache/wiki/auth/TestAuthorizer.java +++ b/jspwiki-main/src/test/java/org/apache/wiki/auth/TestAuthorizer.java @@ -18,24 +18,23 @@ */ package org.apache.wiki.auth; -import java.security.Principal; -import java.util.Properties; - -import javax.servlet.http.HttpServletRequest; - -import org.apache.wiki.WikiEngine; import org.apache.wiki.WikiSession; +import org.apache.wiki.api.core.Engine; import org.apache.wiki.auth.authorize.Role; import org.apache.wiki.auth.authorize.WebAuthorizer; +import javax.servlet.http.HttpServletRequest; +import java.security.Principal; +import java.util.Properties; + /** - * A very fast authorizer that does almost nothing. The WebContainerAuthorizer module - * is very slow, as it parses the web.xml each time, so we use this for most of - * the different tests. + * A very fast authorizer that does almost nothing. The WebContainerAuthorizer module is very slow, as it parses the web.xml each time, + * so we use this for most of the different tests. + * * @since 2.3 */ -public class TestAuthorizer implements WebAuthorizer -{ +public class TestAuthorizer implements WebAuthorizer { + private Role[] m_roles = new Role[]{ new Role( "Admin" ), Role.AUTHENTICATED, @@ -48,33 +47,28 @@ public class TestAuthorizer implements WebAuthorizer super(); } - public Principal findRole( String role ) + @Override public Principal findRole( final String role ) { return null; } - public void initialize( WikiEngine engine, Properties props ) - { + @Override public void initialize( final Engine engine, final Properties props ) { } /** - * Returns an array of Principal objects containing five elements: - * Role "Admin", Role.AUTHENTICATED, Role "IT", Role "Finance" and + * Returns an array of Principal objects containing five elements: Role "Admin", Role.AUTHENTICATED, Role "IT", Role "Finance" and * Role "Engineering." */ - public Principal[] getRoles() + @Override public Principal[] getRoles() { return m_roles; } /** - * Returns <code>true</code> if the WikiSession's Subject contains - * a particular role principal. + * Returns <code>true</code> if the WikiSession's Subject contains a particular role principal. */ - public boolean isUserInRole( WikiSession session, Principal role ) - { - if ( session == null || role == null ) - { + @Override public boolean isUserInRole( final WikiSession session, final Principal role ) { + if ( session == null || role == null ) { return false; } @@ -87,7 +81,7 @@ public class TestAuthorizer implements WebAuthorizer * {@link javax.servlet.http.HttpServletRequest#isUserInRole(String)}. * @see org.apache.wiki.auth.authorize.WebAuthorizer#isUserInRole(javax.servlet.http.HttpServletRequest, java.security.Principal) */ - public boolean isUserInRole( HttpServletRequest request, Principal role ) + @Override public boolean isUserInRole( final HttpServletRequest request, final Principal role ) { return request.isUserInRole( role.getName() ); }
