Return-Path: X-Original-To: apmail-incubator-jspwiki-dev-archive@minotaur.apache.org Delivered-To: apmail-incubator-jspwiki-dev-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 999A5D41C for ; Thu, 27 Sep 2012 08:32:58 +0000 (UTC) Received: (qmail 97938 invoked by uid 500); 27 Sep 2012 08:32:58 -0000 Delivered-To: apmail-incubator-jspwiki-dev-archive@incubator.apache.org Received: (qmail 97793 invoked by uid 500); 27 Sep 2012 08:32:56 -0000 Mailing-List: contact jspwiki-dev-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: jspwiki-dev@incubator.apache.org Delivered-To: mailing list jspwiki-dev@incubator.apache.org Received: (qmail 97749 invoked by uid 99); 27 Sep 2012 08:32:54 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 27 Sep 2012 08:32:54 +0000 X-ASF-Spam-Status: No, hits=0.0 required=5.0 tests=SPF_PASS,UNPARSEABLE_RELAY X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: local policy) Received: from [195.246.221.32] (HELO webmail2.mercurio.it) (195.246.221.32) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 27 Sep 2012 08:32:49 +0000 Received: by webmail2.mercurio.it (Postfix, from userid 33) id 35AF56DC4F; Thu, 27 Sep 2012 10:32:21 +0200 (CEST) Received: from ( [unknown]) by webmail.mercurio.it (Horde Framework) with HTTP; Thu, 27 Sep 2012 10:32:21 +0200 Message-ID: <20120927103221.43185whg9muvga9s@webmail.mercurio.it> Date: Thu, 27 Sep 2012 10:32:21 +0200 From: "Roberto Venturi" To: jspwiki-dev@incubator.apache.org, "Juan Pablo Santos =?utf-8?b?Um9kcsOtZ3Vleg==?=" Subject: Re: [VOTE] Release JSPWiki version 2.9.0-incubating References: In-Reply-To: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=_5vtokqkf32m8" Content-Transfer-Encoding: 7bit User-Agent: Internet Messaging Program (IMP) H3 (4.2) X-Virus-Checked: Checked by ClamAV on apache.org --=_5vtokqkf32m8 Content-Type: text/plain; charset=UTF-8; DelSp="Yes"; format="flowed" Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Hi, here is my one month experience with the 2_9_0 release of jspwiki and =20 WebSphere containers with the hope it will be usefull and not making =20 noise. All sources recompiled with "IBM Rational=C2=AE Application Developer=E2=84= =A2 for =20 WebSphere=C2=AE Software 7.5.5.5" and .EAR file deployed on a WebSphere 6.1 = =20 and on a WebSphere 7.0 server. Application works well on both container and I'am using it since last =20 month (I make a compare of sources file and the only difference =20 between voting version and the one I downloaded last month are on =20 comments and package.html files). It's not a "standard" test so my +1 vote is just an "It works well and =20 I like it" :-) Regards, Roberto P.S. the two Websphere environment I used did not honor jspwiki.policy =20 file until I add a property in the jspwiki.properties file and a test =20 in the code of - org.apache.wiki.auth.Authorization.Manager.java - org.apache.wiki.auth.SecurityVerifier.java Nothing changes if the property is not present (back compatibility). The problems was not present deploying the .ear file on Apache Tomcat =20 container so i suppose it's a different handling of WebSphere. Codes attached. Quoting "Juan Pablo Santos Rodr=C3=ADguez" : > This is an incubator release for Apache JSPWiki, version 2.9.0-incubating. > > It fixes the following issues: > https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=3D1231073= 2&version=3D12319521 > > *** Please download, test and vote by 72 hours from now. > > Note that we are voting upon the source (tag), binaries are provided for > convenience. > > Source and binary files: > http://people.apache.org/~jalkanen/JSPWiki/2.9.0/ > > The tag to be voted upon: > https://svn.apache.org/repos/asf/incubator/jspwiki/tags/jspwiki_2_9_0_incu= bating_rc3 > > JSPWiki's KEYS file containing PGP keys we use to sign the release: > http://www.apache.org/dist/incubator/jspwiki/KEYS > > > regards, > juan pablo > -- Messaggio inviato da WebMail - http://www.mercurio.it ------------------------------------------------------- --=_5vtokqkf32m8 Content-Type: text/plain; charset=UTF-8; name="AuthorizationManager.java" Content-Disposition: attachment; filename="AuthorizationManager.java" Content-Transfer-Encoding: quoted-printable /*=20 JSPWiki - a JSP-based WikiWiki clone. 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. =20 */ package org.apache.wiki.auth; import java.io.File; import java.net.URL; import java.security.*; import java.security.cert.Certificate; import java.util.Map; import java.util.Properties; import java.util.WeakHashMap; import org.apache.log4j.Logger; import org.freshcookies.security.policy.LocalPolicy; import org.freshcookies.security.policy.PolicyException; import org.apache.wiki.NoRequiredPropertyException; import org.apache.wiki.WikiEngine; import org.apache.wiki.WikiException; import org.apache.wiki.WikiPage; import org.apache.wiki.WikiSession; 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.GroupPermission; import org.apache.wiki.auth.permissions.PagePermission; import org.apache.wiki.auth.permissions.WikiPermission; 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.util.ClassUtil; /** *

Manages all access control and authorization; determines what authenti= cated * users are allowed to do.

*

Privileges in JSPWiki are expressed as Java-standard {@link java.secur= ity.Permission} * classes. There are two types of permissions:

*
    *
  • {@link org.apache.wiki.auth.permissions.WikiPermission} - privilege= s that apply * to an entire wiki instance: e.g., editing user profiles, creat= ing pages, creating groups
  • *
  • {@link org.apache.wiki.auth.permissions.PagePermission} - privilege= s that apply * to a single wiki page or range of pages: e.g., reading, editin= g, renaming *
*

Calling classes determine whether they are entitled to perform a parti= cular 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.

*

For WikiPermissions, the decision criteria is relatively simple: the c= aller either * possesses the permission, as granted by the wiki security policy -- or no= t.

*

For PagePermissions, the logic is exactly the same if the page being c= hecked * does not have an access control list. However, if the page does have an A= CL, the * authorization decision is made based the union of the permission= s * granted in the ACL and in the security policy. In other words, the user m= ust * be named in the ACL (or belong to a group or role that is named in the AC= L) * and be granted (at least) the same permission in the security po= licy. We * do this to prevent a user from gaining more permissions than they already * have, based on the security policy.

*

See the {@link #checkPermission(WikiSession, Permission)} and * {@link #hasRoleOrPrincipal(WikiSession, Principal)} methods for more info= rmation * on the authorization logic.

* @since 2.3 * @see AuthenticationManager */ public final class AuthorizationManager { private static final Logger log =3D Logger.getLogger( AuthorizationManag= er.class ); /** * The default external Authorizer is the {@link org.apache.wiki.auth.au= thorize.WebContainerAuthorizer} */ public static final String DEFAULT_AUTHORIZER =3D "org.ap= ache.wiki.auth.authorize.WebContainerAuthorizer"; /** Property that supplies the security policy file name, in WEB-INF. */ protected static final String POLICY =3D "jspwiki.polic= y.file"; =20 /** Name of the default security policy file, in WEB-INF. */ protected static final String DEFAULT_POLICY =3D "jspwi= ki.policy"; /** * The property name in jspwiki.properties for specifying the external {= @link Authorizer}. */ public static final String PROP_AUTHORIZER =3D "jspwiki= .authorizer"; private Authorizer m_authorizer =3D null; /** Cache for storing ProtectionDomains used to evaluate the local polic= y. */ private Map m= _cachedPds =3D new WeakHashMap(); private WikiEngine m_engine =3D null; private LocalPolicy m_localPolicy =3D null; private boolean m_useJAAS =3D true; =20 /** Usually permissions are checked by JVMwide security * before than by internal security. * In IBM WebSphere (and may be other web container) * ther check against Wiki permissions (Group, Page All & Wiki) * always returns true. * In this case it must be disabled to have jspwiki.policy work as aspe= cted * Roven 2012-08-10 **/ =20 private boolean m_useJVMPermTest =3D true; /** * Constructs a new AuthorizationManager instance. */ public AuthorizationManager() { } /** * Returns true or false, depending on * whether a Permission is allowed for the Subject associated with * a supplied WikiSession. The access control algorithm works this way: *
    *
  1. The {@link org.apache.wiki.auth.acl.Acl} for the page is obtained=
  2. *
  3. The Subject associated with the current * {@link org.apache.wiki.WikiSession} is obtained
  4. *
  5. If the Subject's Principal set includes the Role Principal that i= s * the administrator group, always allow the Permission
  6. *
  7. For all permissions, check to see if the Permission is allowed ac= cording * to the default security policy. If it isn't, deny the permission and = halt * further processing.
  8. *
  9. 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 whethe= r * the user (Subject) posesses any one of these specified Roles or * Principals. The matching process delegates to * {@link #hasRoleOrPrincipal(WikiSession, Principal)}. *
*

* Note that when iterating through the Acl's list of authorized Princip= als, * it is possible that one or more of the Acl's Principal entries are of * type UnresolvedPrincipal. 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 UnresolvedPrincipal i= s * encountered, this method will attempt to resolve it first 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). *

*

* If security not set to JAAS, will return true. *

* @param session the current wiki session * @param permission the Permission being checked * @see #hasRoleOrPrincipal(WikiSession, Principal) * @return the result of the Permission check */ public final boolean checkPermission( WikiSession session, Permission pe= rmission ) { if( !m_useJAAS ) { // // Nobody can login, if JAAS is turned off. // if( permission =3D=3D null || "login".equals( permission.getActi= ons() ) ) return false; return true; } // // A slight sanity check. // if ( session =3D=3D null || permission =3D=3D null ) { fireEvent( WikiSecurityEvent.ACCESS_DENIED, null, permission ); return false; } Principal user =3D session.getLoginPrincipal(); // Always allow the action if user has AllPermission Permission allPermission =3D new AllPermission( m_engine.getApplicat= ionName() ); boolean hasAllPermission =3D checkStaticPermission( session, allPerm= ission ); 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. boolean hasPolicyPermission =3D checkStaticPermission( session, perm= ission ); 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. // String pageName =3D ((PagePermission)permission).getPage(); WikiPage page =3D m_engine.getPage( pageName ); Acl acl =3D ( page =3D=3D null) ? null : m_engine.getAclManager().ge= tPermissions( page ); if ( page =3D=3D null || acl =3D=3D 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. Principal[] aclPrincipals =3D acl.findPrincipals( permission ); log.debug( "Checking ACL entries..." ); log.debug( "Acl for this page is: " + acl ); log.debug( "Checking for principal: " + String.valueOf( aclPrincipal= s ) ); 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 ) { AclEntry aclEntry =3D acl.getEntry( aclPrincipal ); aclPrincipal =3D resolvePrincipal( aclPrincipal.getName() ); if ( aclEntry !=3D null && !( aclPrincipal instanceof Unreso= lvedPrincipal ) ) { aclEntry.setPrincipal( aclPrincipal ); } } if ( hasRoleOrPrincipal( session, aclPrincipal ) ) { fireEvent( WikiSecurityEvent.ACCESS_ALLOWED, user, permissio= n ); return true; } } fireEvent( WikiSecurityEvent.ACCESS_DENIED, user, permission ); return false; } /** *

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 (anyonymous, asserted, authenticated) can possess * a built-in role. But a user must be authenticated to * possess a role other than one of the built-in ones. * We do this to prevent privilege escalation.

*

For all other cases, this method returns false.

*

Note that this method does not 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.

* @param session the current wiki session, which must be non-null. If n= ull, * the result of this method always returns false * @param principal the Principal (role or group principal) to look * for, which must be non-null. If null, * the result of this method always returns false * @return true if the Subject supplied with the WikiContex= t * posesses the Role or GroupPrincipal, false other= wise */ public final boolean isUserInRole( WikiSession session, Principal princi= pal ) { if ( session =3D=3D null || principal =3D=3D null || AuthenticationManager.isUserPrincipal( principal ) ) { return false; } // Any type of user can possess a built-in role if ( principal instanceof Role && Role.isBuiltInRole( (Role)principa= l ) ) { return session.hasPrincipal( principal ); } // Only authenticated users can posssess groups or custom roles if ( session.isAuthenticated() && AuthenticationManager.isRolePrinci= pal( 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 * @return the current Authorizer */ public final Authorizer getAuthorizer() throws WikiSecurityException { if ( m_authorizer !=3D null ) { return m_authorizer; } throw new WikiSecurityException( "Authorizer did not initialize prop= erly. Check the logs." ); } /** *

Determines if the Subject associated with a supplied WikiSession c= ontains * a desired user Principal or built-in Role principal, OR is a member a * Group or external Role. The rules are as follows:

*
    *
  1. First, if desired Principal is a Role or GroupPrincipal, delegate= to * {@link #isUserInRole(WikiSession, Principal)} and * return the result.
  2. *
  3. 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.
  4. *
*

Note: if the Principal parameter is a user principal, the sess= ion * must be authenticated in order for the user to "possess it". Anonymou= s * or asserted sessions will never posseess a named user principal.=

* @param session the current wiki session, which must be non-null. If n= ull, * the result of this method always returns false * @param principal the Principal (role, group, or user principal) to lo= ok * for, which must be non-null. If null, the result of this * method always returns false * @return true if the Subject supplied with the WikiContex= t * posesses the Role, GroupPrincipal or desired * user Principal, false otherwise */ protected boolean hasRoleOrPrincipal( WikiSession session, Principal pri= ncipal ) { // If either parameter is null, always deny if( session =3D=3D null || principal =3D=3D 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.isUserPrincip= al( principal ) ) { String principalName =3D principal.getName(); Principal[] userPrincipals =3D session.getPrincipals(); for( Principal userPrincipal : userPrincipals ) { if( userPrincipal.getName().equals( principalName ) ) { return true; } } } return false; } /** * 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 e= ngine * @throws WikiException if the AuthorizationManager cannot be initializ= ed */ @SuppressWarnings("deprecation") public final void initialize( WikiEngine engine, Properties properties )= throws WikiException { m_engine =3D engine; m_useJAAS =3D AuthenticationManager.SECURITY_JAAS.equals( properties= .getProperty(AuthenticationManager.PROP_SECURITY, AuthenticationManager.SECU= RITY_JAAS ) ); if( !m_useJAAS ) return; // // JAAS authorization continues // m_authorizer =3D getAuthorizerImplementation( properties ); m_authorizer.initialize( engine, properties ); // Initialize local security policy try { String policyFileName =3D properties.getProperty( POLICY, DEFAUL= T_POLICY ); URL policyURL =3D AuthenticationManager.findConfigFile( engine, = policyFileName ); =20 if (policyURL !=3D null)=20 { File policyFile =3D new File( policyURL.getPath() ); log.info("We found security policy URL: " + policyURL + " an= d transformed it to file " + policyFile.getAbsolutePath()); m_localPolicy =3D new LocalPolicy( policyFile, engine.getCon= tentEncoding() ); m_localPolicy.refresh(); log.info( "Initialized default security policy: " + policyFi= le.getAbsolutePath() ); } else { StringBuffer sb =3D new StringBuffer( "JSPWiki was unable to= initialize the " ); sb.append( "default security policy (WEB-INF/jspwiki.policy)= file. " ); sb.append( "Please ensure that the jspwiki.policy file exist= s in the default location. " ); sb.append( "This file should exist regardless of the existan= ce of a global policy file. " ); sb.append( "The global policy file is identified by the java= .security.policy variable. " ); WikiSecurityException wse =3D new WikiSecurityException( sb.= toString() ); log.fatal( sb.toString(), wse ); throw wse; } } catch ( PolicyException e ) { log.error("Could not initialize local security policy: " + e.get= Message() ); throw new WikiException( "Could not initialize local security po= licy: " + e.getMessage(), e ); } //Roven 2012-08-10 m_useJVMPermTest =3D "true".equals( properties.getProperty("jspwiki.JVMwideSecurity", "true").toLo= werCase()); =20 } /** * Returns true if JSPWiki's JAAS authorization system * is used for authorization in addition to container controls. * @return the result */ protected boolean isJAASAuthorized() { return m_useJAAS; } /** * Attempts to locate and initialize a Authorizer to use with this manag= er. * 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 final Authorizer getAuthorizerImplementation( Properties props )= throws WikiException { String authClassName =3D props.getProperty( PROP_AUTHORIZER, DEFAULT= _AUTHORIZER ); return (Authorizer) locateImplementation( authClassName ); } private final Object locateImplementation( String clazz ) throws WikiExc= eption { if ( clazz !=3D null ) { try { Class authClass =3D ClassUtil.findClass( "org.apache.wiki= .auth.authorize", clazz ); Object impl =3D authClass.newInstance(); return impl; } catch( ClassNotFoundException e ) { log.fatal( "Authorizer " + clazz + " cannot be found", e ); throw new WikiException( "Authorizer " + clazz + " cannot be= found", e ); } catch( InstantiationException e ) { log.fatal( "Authorizer " + clazz + " cannot be created", e )= ; throw new WikiException( "Authorizer " + clazz + " cannot be= created", e ); } catch( IllegalAccessException e ) { log.fatal( "You are not allowed to access this authorizer cl= ass", e ); throw new WikiException( "You are not allowed to access this= authorizer class", e ); } } throw new NoRequiredPropertyException( "Unable to find a " + PROP_AU= THORIZER + " 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( Principal[] principals, Permissi= on permission ) { for ( Principal principal : principals ) { // Get ProtectionDomain for this Principal from cache, or create= new one ProtectionDomain pd =3D m_cachedPds.get( principal ); if ( pd =3D=3D null ) { ClassLoader cl =3D this.getClass().getClassLoader(); CodeSource cs =3D new CodeSource( null, (Certificate[])null = ); pd =3D 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 codeBase is effectively this class, * not that of the caller. Therefore, this method will work best when wh= at * matters in the policy is who makes the permission check, not * what the caller's code source is. Internally, this method works by * executing Subject.doAsPrivileged with a privileged actio= n * that simply calls {@link java.security.AccessController#checkPermissi= on(Permission)}. * @see AccessController#checkPermission(java.security.Permission) . A * caught exception (or lack thereof) determines whether the privi= lege * is absent (or present). * @param session the WikiSession whose permission status is being queri= ed * @param permission the Permission the Subject must possess * @return true if the Subject posesses the permission, * false otherwise */ protected final boolean checkStaticPermission( final WikiSession session= , final Permission permission ) { if( !m_useJAAS ) return true; Boolean allowed =3D (Boolean) WikiSession.doPrivileged( session, new= PrivilegedAction() { public Boolean run() { //Roven 2012-08-10 Begin if(m_useJVMPermTest || ! (permission instanceof AllPermission) && ! (permission instanceof GroupPermission) && ! (permission instanceof PagePermission) && ! (permission instanceof WikiPermission) ) { try { // Check the JVM-wide security policy first AccessController.checkPermission( permission ); return Boolean.TRUE; } catch( AccessControlException e ) { // Global policy denied the permission } } //Roven 2012-08-10 End // Try the local policy - check each Role/Group and User Pri= ncipal if ( allowedByLocalPolicy( session.getRoles(), permission ) = || allowedByLocalPolicy( session.getPrincipals(), permissi= on ) ) { return Boolean.TRUE; } return Boolean.FALSE; } } ); return allowed.booleanValue(); } /** *

Given a supplied string representing a Principal's name from an Ac= l, 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:

*
    *
  1. If the name matches one of the built-in {@link org.apache.wiki.au= th.authorize.Role} names, * return that built-in Role
  2. *
  3. If the name matches one supplied by the current * {@link org.apache.wiki.auth.Authorizer}, return that Role
  4. *
  5. If the name matches a group managed by the * current {@link org.apache.wiki.auth.authorize.GroupManager}, return t= hat Group
  6. *
  7. Otherwise, assume that the name represents a user * principal. Using the current {@link org.apache.wiki.auth.user.UserDat= abase}, find the * first user who matches the supplied name by calling * {@link org.apache.wiki.auth.user.UserDatabase#find(String)}.
  8. *
  9. Finally, if a user cannot be found, manufacture * and return a generic {@link org.apache.wiki.auth.acl.UnresolvedPrinci= pal}
  10. *
* @param name the name of the Principal to resolve * @return the fully-resolved Principal */ public final Principal resolvePrincipal( String name ) { if( !m_useJAAS ) { return new UnresolvedPrincipal(name); } // Check built-in Roles first Role role =3D new Role(name); if ( Role.isBuiltInRole( role ) ) { return role; } // Check Authorizer Roles Principal principal =3D m_authorizer.findRole( name ); if ( principal !=3D null ) { return principal; } // Check Groups principal =3D m_engine.getGroupManager().findRole( name ); if ( principal !=3D null ) { return principal; } // Ok, no luck---this must be a user principal Principal[] principals =3D null; UserProfile profile =3D null; UserDatabase db =3D m_engine.getUserManager().getUserDatabase(); try { profile =3D db.find( name ); principals =3D db.getPrincipals( profile.getLoginName() ); for (int i =3D 0; i < principals.length; i++) { principal =3D principals[i]; if ( principal.getName().equals( name ) ) { return principal; } } } catch( NoSuchPrincipalException e ) { // We couldn't find the user... } // Ok, no luck---mark this as unresolved and move on return new UnresolvedPrincipal( name ); } // events processing ...................................................= .... /** * Registers a WikiEventListener with this instance. * @param listener the event listener */ public final synchronized void addWikiEventListener( WikiEventListener l= istener ) { WikiEventManager.addWikiEventListener( this, listener ); } /** * Un-registers a WikiEventListener with this instance. * @param listener the event listener */ public final synchronized void removeWikiEventListener( WikiEventListene= r listener ) { WikiEventManager.removeWikiEventListener( this, listener ); } /** * 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 final void fireEvent( int type, Principal user, Object permiss= ion ) { if ( WikiEventManager.isListening(this) ) { WikiEventManager.fireEvent(this,new WikiSecurityEvent(this,type,= user,permission)); } } } --=_5vtokqkf32m8 Content-Type: text/plain; charset=UTF-8; name="SecurityVerifier.java" Content-Disposition: attachment; filename="SecurityVerifier.java" Content-Transfer-Encoding: quoted-printable /* JSPWiki - a JSP-based WikiWiki clone. 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. =20 */ package org.apache.wiki.auth; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.security.*; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import javax.security.auth.Subject; import javax.security.auth.spi.LoginModule; import org.apache.commons.lang.ArrayUtils; import org.apache.log4j.Logger; import org.freshcookies.security.policy.PolicyReader; import org.jdom.JDOMException; import org.apache.wiki.InternalWikiException; import org.apache.wiki.WikiEngine; import org.apache.wiki.WikiException; import org.apache.wiki.WikiSession; import org.apache.wiki.auth.authorize.*; import org.apache.wiki.auth.permissions.AllPermission; import org.apache.wiki.auth.permissions.GroupPermission; import org.apache.wiki.auth.permissions.PermissionFactory; import org.apache.wiki.auth.permissions.WikiPermission; import org.apache.wiki.auth.user.UserDatabase; import org.apache.wiki.auth.user.UserProfile; /** * Helper class for verifying JSPWiki's security configuration. Invoked by * admin/SecurityConfig.jsp. * @since 2.4 */ public final class SecurityVerifier { private static final long serialVersionUID =3D -38595633= 55089169941L; private WikiEngine m_engine; private boolean m_isSecurityPolicyConfigured =3D false; private Principal[] m_policyPrincipals =3D new Princ= ipal[0]; private WikiSession m_session; /** Message prefix for errors. */ public static final String ERROR =3D "Error."; /** Message prefix for warnings. */ public static final String WARNING =3D "Warning.= "; /** Message prefix for information messages. */ public static final String INFO =3D "Info."; /** Message topic for policy errors. */ public static final String ERROR_POLICY =3D "Error.Po= licy"; /** Message topic for policy warnings. */ public static final String WARNING_POLICY =3D "Warning.= Policy"; /** Message topic for policy information messages. */ public static final String INFO_POLICY =3D "Info.Pol= icy"; /** Message topic for JAAS errors. */ public static final String ERROR_JAAS =3D "Error.Ja= as"; /** Message topic for JAAS warnings. */ public static final String WARNING_JAAS =3D "Warning.= Jaas"; /** Message topic for role-checking errors. */ public static final String ERROR_ROLES =3D "Error.Ro= les"; /** Message topic for role-checking information messages. */ public static final String INFO_ROLES =3D "Info.Rol= es"; /** Message topic for user database errors. */ public static final String ERROR_DB =3D "Error.Us= erDatabase"; /** Message topic for user database warnings. */ public static final String WARNING_DB =3D "Warning.= UserDatabase"; /** Message topic for user database information messages. */ public static final String INFO_DB =3D "Info.Use= rDatabase"; /** Message topic for group database errors. */ public static final String ERROR_GROUPS =3D "Error.Gr= oupDatabase"; /** Message topic for group database warnings. */ public static final String WARNING_GROUPS =3D "Warning.= GroupDatabase"; /** Message topic for group database information messages. */ public static final String INFO_GROUPS =3D "Info.Gro= upDatabase"; /** Message topic for JAAS information messages. */ public static final String INFO_JAAS =3D "Info.Jaa= s"; private static final String[] CONTAINER_ACTIONS =3D new Strin= g[] { "View pages= ", "Comment on existing pages", "Edit pages", "Upload attachments", "Create a new group", "Renam= e an existing page", "Delete pages" }; private static final String[] CONTAINER_JSPS =3D new Strin= g[] { "/Wiki.jsp"= , "/Comment.jsp", "/Edit.jsp", "/Upload.jsp", "/NewGroup.jsp", "/Rename.jsp", "/Delete.jsp" }; private static final String BG_GREEN =3D "bgcolor= =3D\"#c0ffc0\""; private static final String BG_RED =3D "bgcolor= =3D\"#ffc0c0\""; private static final Logger LOG =3D Logger.getL= ogger( SecurityVerifier.class.getName() ); /** Usually permissions are checked by JVMwide security * before than by internal security. * In IBM WebSphere (and may be other web container) * ther check against Wiki permissions (Group, Page All & Wiki) * always returns true. * In this case it must be disabled to have jspwiki.policy work as aspec= ted * Roven 2012-08-10 **/ =20 private boolean m_useJVMPermTest =3D true; /** * Constructs a new SecurityVerifier for a supplied WikiEngine and WikiS= ession. * @param engine the wiki engine * @param session the wiki session (typically, that of an administrator) */ public SecurityVerifier( WikiEngine engine, WikiSession session ) { super(); m_engine =3D engine; m_session =3D session; m_session.clearMessages(); //Roven 2012-08-10 m_useJVMPermTest =3D "true".equals(m_engine.getWikiProperties() .getProperty("jspwiki.JVMwideSecurity", "true").toLowerCase()); verifyJaas(); verifyPolicy(); try { verifyPolicyAndContainerRoles(); } catch ( WikiException e ) { m_session.addMessage( ERROR_ROLES, e.getMessage() ); } verifyGroupDatabase(); verifyUserDatabase(); } /** * Returns an array of unique Principals from the JSPWIki security polic= y * file. This array will be zero-length if the policy file was not * successfully located, or if the file did not specify any Principals i= n * the policy. * @return the array of principals */ public final Principal[] policyPrincipals() { return m_policyPrincipals; } /** * Formats and returns an HTML table containing sample permissions and w= hat * roles are allowed to have them. This method will throw an * {@link IllegalStateException} if the authorizer is not of type * {@link org.apache.wiki.auth.authorize.WebContainerAuthorizer} * @return the formatted HTML table containing the result of the tests */ public final String policyRoleTable() { Principal[] roles =3D m_policyPrincipals; String wiki =3D m_engine.getApplicationName(); String[] pages =3D new String[] { "Main", "Index", "GroupTest", "GroupAdmin" }; String[] pageActions =3D new String[] { "view", "edit", "modify", "rename", "delete" }; String[] groups =3D new String[] { "Admin", "TestGroup", "Foo" }; String[] groupActions =3D new String[] { "view", "edit", null, null, "delete" }; // Calculate column widths String colWidth; if ( pageActions.length > 0 && roles.length > 0 ) { colWidth =3D String.valueOf( 67f / ( pageActions.length * roles.= length ) ) + "%"; } else { colWidth =3D "67%"; } StringBuffer s =3D new StringBuffer(); // Write the table header s.append( "\n" ); s.append( " \n" ); s.append( " \n" ); s.append( " \n" ); s.append( " \n" ); } s.append( " \n" ); // Print a column for each role s.append( " \n" ); for( int i =3D 0; i < roles.length; i++ ) { for( String pageAction : pageActions ) { String action =3D pageAction.substring( 0, 1 ); s.append( " \n" ); } } s.append( " \n" ); // Write page permission tests first for( String page : pages ) { s.append( " \n" ); s.append( " \n" ); } // Now do the group tests for( String group : groups ) { s.append( " \n" ); s.append( " \n" ); for( Principal role : roles ) { for( String groupAction : groupActions ) { Permission permission =3D null; if ( groupAction !=3D null) { permission =3D new GroupPermission( wiki + ":" + gro= up, groupAction ); } s.append( printPermissionTest( permission, role, 1 ) ); } } s.append( " \n" ); } // Now check the wiki-wide permissions String[] wikiPerms =3D new String[] { "createGroups", "createPages", "login", "editPreferences", "editPr= ofile" }; for( String wikiPerm : wikiPerms ) { s.append( " \n" ); s.append( " \n" ); for( Principal role : roles ) { Permission permission =3D new WikiPermission( wiki, wikiPerm= ); s.append( printPermissionTest( permission, role, pageActions= .length ) ); } s.append( " \n" ); } // Lastly, check for AllPermission s.append( " \n" ); s.append( " \n" ); for( Principal role : roles ) { Permission permission =3D new AllPermission( wiki ); s.append( printPermissionTest( permission, role, pageActions.len= gth ) ); } s.append( " \n" ); // We're done! s.append( "
Permission\n" ); for( int i =3D 0; i < roles.length; i++ ) { s.append( " " + roles[i].getName() + "
" + action= + "
PagePermission \"" + wiki + ":" + page + "\"<= /td>\n" ); for( Principal role : roles ) { for( String pageAction : pageActions ) { Permission permission =3D PermissionFactory.getPagePermi= ssion( wiki + ":" + page, pageAction ); s.append( printPermissionTest( permission, role, 1 ) ); } } s.append( "
GroupPermission \"" + wiki + ":" + group + "\= "
WikiPermission \"" + wiki + "\",\"" + wikiPer= m + "\"
AllPermission \"" + wiki + "\"
" ); return s.toString(); } /** * Prints a <td> HTML element with the results of a permission tes= t. * @param perm the permission to format * @param allowed whether the permission is allowed */ private final String printPermissionTest( Permission permission, Princip= al principal, int cols ) { StringBuffer s =3D new StringBuffer(); if ( permission =3D=3D null ) { s.append( " " ); s.append( " \n" ); } else { boolean allowed =3D verifyStaticPermission( principal, permissio= n ); s.append( " " : BG_RED + ">" ); s.append( " \n" ); } return s.toString(); } /** * Formats and returns an HTML table containing the roles the web contai= ner * is aware of, and whether each role maps to particular JSPs. This meth= od * throws an {@link IllegalStateException} if the authorizer is not of t= ype * {@link org.apache.wiki.auth.authorize.WebContainerAuthorizer} * @return the formatted HTML table containing the result of the tests * @throws WikiException if tests fail for unexpected reasons */ public final String containerRoleTable() throws WikiException { AuthorizationManager authorizationManager =3D m_engine.getAuthorizat= ionManager(); Authorizer authorizer =3D authorizationManager.getAuthorizer(); // If authorizer not WebContainerAuthorizer, print error message if ( !( authorizer instanceof WebContainerAuthorizer ) ) { throw new IllegalStateException( "Authorizer should be WebContai= nerAuthorizer" ); } // Now, print a table with JSP pages listed on the left, and // an evaluation of each pages' constraints for each role // we discovered StringBuffer s =3D new StringBuffer(); Principal[] roles =3D authorizer.getRoles(); s.append( "\n" ); s.append( "\n" ); s.append( " \n" ); s.append( " \n" ); s.append( " \n" ); s.append( " = \n" ); s.append( " \n" ); s.append( " \n" ); s.append( " \n" ); for( Principal role : roles ) { s.append( " \n" ); } s.append( "\n" ); s.append( "\n" ); s.append( "\n" ); try { WebContainerAuthorizer wca =3D (WebContainerAuthorizer) authoriz= er; for( int i =3D 0; i < CONTAINER_ACTIONS.length; i++ ) { String action =3D CONTAINER_ACTIONS[i]; String jsp =3D CONTAINER_JSPS[i]; // Print whether the page is constrained for each role boolean allowsAnonymous =3D !wca.isConstrained( jsp, Role.AL= L ); s.append( " \n" ); s.append( " \n" ); s.append( " \n" ); s.append( " \n" ); for( Principal role : roles ) { boolean allowed =3D allowsAnonymous || wca.isConstrained= ( jsp, (Role)role ); s.append( " \n" ); } s.append( " \n" ); } } catch( JDOMException e ) { // If we couldn't evaluate constraints it means // there's some sort of IO mess or parsing issue LOG.error( "Malformed XML in web.xml", e ); throw new InternalWikiException( e.getClass().getName() + ": " += e.getMessage() ); } s.append( "\n" ); s.append( "
ActionPageRoles
Anonymous" + role.getName() + "
" + action + "" + jsp + "" : BG_RED + ">" ); s.append( " " : BG_RED + ">" ); s.append( " 
\n" ); return s.toString(); } /** * Returns true if the Java security policy is configured * correctly, and it verifies as valid. * @return the result of the configuration check */ public final boolean isSecurityPolicyConfigured() { return m_isSecurityPolicyConfigured; } /** * If the active Authorizer is the WebContainerAuthorizer, returns the r= oles * it knows about; otherwise, a zero-length array. * @return the roles parsed from web.xml, or a zero-length = array * @throws WikiException if the web authorizer cannot obtain the list of= roles */ public final Principal[] webContainerRoles() throws WikiException { Authorizer authorizer =3D m_engine.getAuthorizationManager().getAuth= orizer(); if ( authorizer instanceof WebContainerAuthorizer ) { return ( (WebContainerAuthorizer) authorizer ).getRoles(); } return new Principal[0]; } /** * Verifies that the roles given in the security policy are reflected by= the * container web.xml file. * @throws WikiException if the web authorizer cannot verify the roles */ protected final void verifyPolicyAndContainerRoles() throws WikiExceptio= n { Authorizer authorizer =3D m_engine.getAuthorizationManager().getAuth= orizer(); Principal[] containerRoles =3D authorizer.getRoles(); boolean missing =3D false; for( Principal principal : m_policyPrincipals ) { if ( principal instanceof Role ) { Role role =3D (Role) principal; boolean isContainerRole =3D ArrayUtils.contains( containerRo= les, role ); if ( !Role.isBuiltInRole( role ) && !isContainerRole ) { m_session.addMessage( ERROR_ROLES, "Role '" + role.getNa= me() + "' is defined in security policy but not in web.xml." ); missing =3D true; } } } if ( !missing ) { m_session.addMessage( INFO_ROLES, "Every non-standard role defin= ed in the security policy was also found in web.xml." ); } } /** * Verifies that the group datbase was initialized properly, and that * user add and delete operations work as they should. */ protected final void verifyGroupDatabase() { GroupManager mgr =3D m_engine.getGroupManager(); GroupDatabase db =3D null; try { db =3D m_engine.getGroupManager().getGroupDatabase(); } catch ( WikiSecurityException e ) { m_session.addMessage( ERROR_GROUPS, "Could not retrieve GroupMan= ager: " + e.getMessage() ); } // Check for obvious error conditions if ( mgr =3D=3D null || db =3D=3D null ) { if ( mgr =3D=3D null ) { m_session.addMessage( ERROR_GROUPS, "GroupManager is null; J= SPWiki could not " + "initialize it. Check the error logs." ); } if ( db =3D=3D null ) { m_session.addMessage( ERROR_GROUPS, "GroupDatabase is null; = JSPWiki could not " + "initialize it. Check the error logs." ); } return; } // Everything initialized OK... // Tell user what class of database this is. m_session.addMessage( INFO_GROUPS, "GroupDatabase is of type '" + db= .getClass().getName() + "'. It appears to be initialized properly." ); // Now, see how many groups we have. int oldGroupCount =3D 0; try { Group[] groups =3D db.groups(); oldGroupCount =3D groups.length; m_session.addMessage( INFO_GROUPS, "The group database contains = " + oldGroupCount + " groups." ); } catch ( WikiSecurityException e ) { m_session.addMessage( ERROR_GROUPS, "Could not obtain a list of = current groups: " + e.getMessage() ); return; } // Try adding a bogus group with random name String name =3D "TestGroup" + String.valueOf( System.currentTimeMill= is() ); Group group =3D null; try { // Create dummy test group group =3D mgr.parseGroup( name, "", true ); Principal user =3D new WikiPrincipal( "TestUser" ); group.add( user ); db.save( group, new WikiPrincipal("SecurityVerifier") ); // Make sure the group saved successfully if ( db.groups().length =3D=3D oldGroupCount ) { m_session.addMessage( ERROR_GROUPS, "Could not add a test gr= oup to the database." ); return; } m_session.addMessage( INFO_GROUPS, "The group database allows ne= w groups to be created, as it should." ); } catch ( WikiSecurityException e ) { m_session.addMessage( ERROR_GROUPS, "Could not add a group to th= e database: " + e.getMessage() ); return; } // Now delete the group; should be back to old count try { db.delete( group ); if ( db.groups().length !=3D oldGroupCount ) { m_session.addMessage( ERROR_GROUPS, "Could not delete a test= group from the database." ); return; } m_session.addMessage( INFO_GROUPS, "The group database allows gr= oups to be deleted, as it should." ); } catch ( WikiSecurityException e ) { m_session.addMessage( ERROR_GROUPS, "Could not delete a test gro= up from the database: " + e.getMessage() ); return; } m_session.addMessage( INFO_GROUPS, "The group database configuration= looks fine." ); } /** * Verfies the JAAS configuration. The configuration is valid if value o= f the * jspwiki.properties property * {@value org.apache.wiki.auth.AuthenticationManager#PROP_LOGIN_MODULE} * resolves to a valid class on the classpath. */ protected final void verifyJaas() { // See if JAAS is on AuthorizationManager authMgr =3D m_engine.getAuthorizationManager(); if ( !authMgr.isJAASAuthorized() ) { m_session.addMessage( ERROR_JAAS, "JSPWiki's JAAS-based authenti= cation " + "and authorization system is turned off (your jspwiki.pr= operties file " + "contains the setting 'jspwiki.security =3D container'. = This " + "setting disables authorization checks and is meant for = testing " + "and troubleshooting only. The test results on this page= will not " + "be reliable as a result. You should set this to 'jaas' = " + "so that security works properly." ); } =20 // Verify that the specified JAAS moduie corresponds to a class we c= an load successfully. String jaasClass =3D m_engine.getWikiProperties().getProperty( Authe= nticationManager.PROP_LOGIN_MODULE ); if ( jaasClass =3D=3D null || jaasClass.length() =3D=3D 0 ) { m_session.addMessage( ERROR_JAAS, "The value of the '" + Authent= icationManager.PROP_LOGIN_MODULE + "' property was null or blank. This is a fatal error. Th= is value should be set to a valid LoginModule implementation " + "on the classpath." ); return; } =20 // See if we can find the LoginModule on the classpath Class c =3D null; try { m_session.addMessage( INFO_JAAS, "The property '" + Authenticati= onManager.PROP_LOGIN_MODULE + "' specified the class '" + jaasClass + ".= '" ); c =3D Class.forName( jaasClass ); } catch( ClassNotFoundException e ) { m_session.addMessage( ERROR_JAAS, "We could not find the the cla= ss '" + jaasClass + "' on the " + "classpath. This is fatal error." ); } =20 // Is the specified class actually a LoginModule? if ( LoginModule.class.isAssignableFrom( c ) ) { m_session.addMessage( INFO_JAAS, "We found the the class '" + ja= asClass + "' on the " + "classpath, and it is a LoginModule implementation. Good= !" ); } else { m_session.addMessage( ERROR_JAAS, "We found the the class '" + j= aasClass + "' on the " + "classpath, but it does not seem to be LoginModule implementatio= n! This is fatal error." ); } } /** * Looks up a file name based on a JRE system property and returns the a= ssociated * File object if it exists. This method adds messages with the topic pr= efix=20 * {@link #ERROR} and {@link #INFO} as appropriate, with the suffix matc= hing the=20 * supplied property. * @param property the system property to look up * @return the file object, or null if not found */ protected final File getFileFromProperty( String property ) { String propertyValue =3D null; try { propertyValue =3D System.getProperty( property ); if ( propertyValue =3D=3D null ) { m_session.addMessage( "Error." + property, "The system prope= rty '" + property + "' is null." ); return null; } // // It's also possible to use "=3D=3D" to mark a property. We r= emove that // here so that we can actually find the property file, then. // if( propertyValue.startsWith("=3D") ) { propertyValue =3D propertyValue.substring(1); } try { m_session.addMessage( "Info." + property, "The system proper= ty '" + property + "' is set to: " + propertyValue + "." ); // Prepend a file: prefix if not there already if ( !propertyValue.startsWith( "file:" ) ) { propertyValue =3D "file:" + propertyValue; } URL url =3D new URL( propertyValue ); File file =3D new File( url.getPath() ); if ( file.exists() ) { m_session.addMessage( "Info." + property, "File '" + pro= pertyValue + "' exists in the filesystem." ); return file; } } catch( MalformedURLException e ) { // Swallow exception because we can't find it anyway } m_session.addMessage( "Error." + property, "File '" + propertyVa= lue + "' doesn't seem to exist. This might be a problem." ); return null; } catch( SecurityException e ) { m_session.addMessage( "Error." + property, "We could not read sy= stem property '" + property + "'. This is probably because you are running with a se= curity manager." ); return null; } } /** * Verfies the Java security policy configuration. The configuration is * valid if value of the local policy (at WEB-INF/jspwiki.policy * resolves to an existing file, and the policy file contained therein * represents a valid policy. */ @SuppressWarnings("unchecked") protected final void verifyPolicy() { // Look up the policy file and set the status text. URL policyURL =3D AuthenticationManager.findConfigFile( m_engine, Au= thorizationManager.DEFAULT_POLICY ); String path =3D policyURL.getPath(); if ( path.startsWith("file:") ) { path =3D path.substring( 5 ); } File policyFile =3D new File( path ); // Next, verify the policy try { // Get the file PolicyReader policy =3D new PolicyReader( policyFile ); m_session.addMessage( INFO_POLICY, "The security policy '" + pol= icy.getFile() + "' exists." ); // See if there is a keystore that's valid KeyStore ks =3D policy.getKeyStore(); if ( ks =3D=3D null ) { m_session.addMessage( WARNING_POLICY, "Policy file does not have a keystore... at least not on= e that we can locate. If your policy file " + "does not contain any 'signedBy' blocks, this is probabl= y ok." ); } else { m_session.addMessage( INFO_POLICY, "The security policy specifies a keystore, and we were a= ble to locate it in the filesystem." ); } // Verify the file policy.read(); List errors =3D policy.getMessages(); if ( errors.size() > 0 ) { for( Exception e : errors ) { m_session.addMessage( ERROR_POLICY, e.getMessage() ); } } else { m_session.addMessage( INFO_POLICY, "The security policy look= s fine." ); m_isSecurityPolicyConfigured =3D true; } // Stash the unique principals mentioned in the file, // plus our standard roles. Set principals =3D new LinkedHashSet(); principals.add( Role.ALL ); principals.add( Role.ANONYMOUS ); principals.add( Role.ASSERTED ); principals.add( Role.AUTHENTICATED ); ProtectionDomain[] domains =3D policy.getProtectionDomains(); for ( ProtectionDomain domain : domains ) { for( Principal principal : domain.getPrincipals() ) { principals.add( principal ); } } m_policyPrincipals =3D principals.toArray( new Principal[princip= als.size()] ); } catch( IOException e ) { m_session.addMessage( ERROR_POLICY, e.getMessage() ); } } /** * Verifies that a particular Principal possesses a Permission, as defin= ed * in the security policy file. * @param principal the principal * @param permission the permission * @return the result, based on consultation with the active Java securi= ty * policy */ protected final boolean verifyStaticPermission( Principal principal, fin= al Permission permission ) { Subject subject =3D new Subject(); subject.getPrincipals().add( principal ); boolean allowedByGlobalPolicy =3D false; if(m_useJVMPermTest) //Roven 2012-08-10 { allowedByGlobalPolicy =3D ((Boolean) Subject.doAsPrivileged( subject, new PrivilegedAction() { public Object run() { try { AccessController.checkPermission( permission ); return Boolean.TRUE; } catch ( AccessControlException e ) { return Boolean.FALSE; } } }, null )).booleanValue(); } if ( allowedByGlobalPolicy ) { return true; } // Check local policy Principal[] principals =3D new Principal[]{ principal }; return m_engine.getAuthorizationManager().allowedByLocalPolicy( prin= cipals, permission ); } /** * Verifies that the user datbase was initialized properly, and that * user add and delete operations work as they should. */ protected final void verifyUserDatabase() { UserDatabase db =3D m_engine.getUserManager().getUserDatabase(); // Check for obvious error conditions if ( db =3D=3D null ) { m_session.addMessage( ERROR_DB, "UserDatabase is null; JSPWiki c= ould not " + "initialize it. Check the error logs." ); return; } if ( db instanceof UserManager.DummyUserDatabase ) { m_session.addMessage( ERROR_DB, "UserDatabase is DummyUserDataba= se; JSPWiki " + "may not have been able to initialize the database you s= upplied in " + "jspwiki.properties, or you left the 'jspwiki.userdataba= se' property " + "blank. Check the error logs." ); } // Tell user what class of database this is. m_session.addMessage( INFO_DB, "UserDatabase is of type '" + db.getC= lass().getName() + "'. It appears to be initialized properly." ); // Now, see how many users we have. int oldUserCount =3D 0; try { Principal[] users =3D db.getWikiNames(); oldUserCount =3D users.length; m_session.addMessage( INFO_DB, "The user database contains " + o= ldUserCount + " users." ); } catch ( WikiSecurityException e ) { m_session.addMessage( ERROR_DB, "Could not obtain a list of curr= ent users: " + e.getMessage() ); return; } // Try adding a bogus user with random name String loginName =3D "TestUser" + String.valueOf( System.currentTime= Millis() ); try { UserProfile profile =3D db.newProfile(); profile.setEmail( "testuser@testville.com" ); profile.setLoginName( loginName ); profile.setFullname( "FullName"+loginName ); profile.setPassword( "password" ); db.save(profile); // Make sure the profile saved successfully if ( db.getWikiNames().length =3D=3D oldUserCount ) { m_session.addMessage( ERROR_DB, "Could not add a test user t= o the database." ); return; } m_session.addMessage( INFO_DB, "The user database allows new use= rs to be created, as it should." ); } catch ( WikiSecurityException e ) { m_session.addMessage( ERROR_DB, "Could not add a test user to th= e database: " + e.getMessage() ); return; } // Now delete the profile; should be back to old count try { db.deleteByLoginName( loginName ); if ( db.getWikiNames().length !=3D oldUserCount ) { m_session.addMessage( ERROR_DB, "Could not delete a test use= r from the database." ); return; } m_session.addMessage( INFO_DB, "The user database allows users t= o be deleted, as it should." ); } catch ( WikiSecurityException e ) { m_session.addMessage( ERROR_DB, "Could not delete a test user to= the database: " + e.getMessage() ); return; } m_session.addMessage( INFO_DB, "The user database configuration look= s fine." ); } } --=_5vtokqkf32m8--